Add CoreConfiguration::WithSubstituteBuilder that restores config after test (#30403)

* Add CoreConfiguration::Mocker that restores config after test

* Rename Mocker to WithSubstituteBuilder
pull/30317/head^2
Yousuk Seung 3 years ago committed by GitHub
parent 8d792b7721
commit 55849467fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 83
      src/core/lib/config/core_configuration.h
  2. 36
      test/core/client_channel/resolvers/binder_resolver_test.cc
  3. 32
      test/core/client_channel/service_config_test.cc
  4. 2
      test/core/handshake/readahead_handshaker_server_ssl.cc
  5. 2
      test/core/security/channel_creds_registry_test.cc

@ -20,6 +20,8 @@
#include <atomic>
#include <functional>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_args_preconditioning.h"
#include "src/core/lib/resolver/resolver_registry.h"
#include "src/core/lib/security/credentials/channel_creds_registry.h"
@ -76,6 +78,50 @@ class CoreConfiguration {
CoreConfiguration* Build();
};
// Stores a builder for RegisterBuilder
struct RegisteredBuilder {
std::function<void(Builder*)> builder;
RegisteredBuilder* next;
};
// Temporarily replaces core configuration with what is built from the
// provided BuildFunc that takes (Builder*) and returns void.
// Requires no concurrent Get() be called. Restores current core
// configuration when this object is destroyed. The default builder
// is not backed up or restored.
//
// Useful for running multiple tests back to back in the same process
// without side effects from previous tests.
class WithSubstituteBuilder {
public:
template <typename BuildFunc>
explicit WithSubstituteBuilder(BuildFunc build) {
// Build core configuration to replace.
Builder builder;
build(&builder);
CoreConfiguration* p = builder.Build();
// Backup current core configuration and replace/reset.
config_restore_ =
CoreConfiguration::config_.exchange(p, std::memory_order_acquire);
builders_restore_ = CoreConfiguration::builders_.exchange(
nullptr, std::memory_order_acquire);
}
~WithSubstituteBuilder() {
// Reset and restore.
Reset();
GPR_ASSERT(CoreConfiguration::config_.exchange(
config_restore_, std::memory_order_acquire) == nullptr);
GPR_ASSERT(CoreConfiguration::builders_.exchange(
builders_restore_, std::memory_order_acquire) == nullptr);
}
private:
CoreConfiguration* config_restore_;
RegisteredBuilder* builders_restore_;
};
// Lifetime methods
// Get the core configuration; if it does not exist, create it.
@ -87,36 +133,11 @@ class CoreConfiguration {
return BuildNewAndMaybeSet();
}
// Build a special core configuration.
// Requires no concurrent Get() be called.
// Doesn't call the regular BuildCoreConfiguration function, instead calls
// `build`.
// BuildFunc is a callable that takes a Builder* and returns void.
// We use a template instead of std::function<void(Builder*)> to avoid
// including std::function in this widely used header, and to ensure no code
// is generated in programs that do not use this function.
// This is sometimes useful for testing.
template <typename BuildFunc>
static void BuildSpecialConfiguration(BuildFunc build) {
// Build bespoke configuration
Builder builder;
build(&builder);
CoreConfiguration* p = builder.Build();
// Swap in final configuration, deleting anything that was already present.
delete config_.exchange(p, std::memory_order_release);
}
// Attach a registration function globally.
// Each registration function is called *in addition to*
// BuildCoreConfiguration for the default core configuration. When using
// BuildSpecialConfiguration, one can use CallRegisteredBuilders to call them.
// Must be called before a configuration is built.
// BuildCoreConfiguration for the default core configuration.
static void RegisterBuilder(std::function<void(Builder*)> builder);
// Call all registered builders.
// See RegisterBuilder for why you might want to call this.
static void CallRegisteredBuilders(Builder* builder);
// Drop the core configuration. Users must ensure no other threads are
// accessing the configuration.
// Clears any dynamically registered builders.
@ -128,10 +149,8 @@ class CoreConfiguration {
template <typename BuildFunc, typename RunFunc>
static void RunWithSpecialConfiguration(BuildFunc build_configuration,
RunFunc code_to_run) {
Reset();
BuildSpecialConfiguration(build_configuration);
WithSubstituteBuilder builder(build_configuration);
code_to_run();
Reset();
}
// Accessors
@ -165,12 +184,6 @@ class CoreConfiguration {
private:
explicit CoreConfiguration(Builder* builder);
// Stores a builder for RegisterBuilder
struct RegisteredBuilder {
std::function<void(Builder*)> builder;
RegisteredBuilder* next;
};
// Create a new CoreConfiguration, and either set it or throw it away.
// We allow multiple CoreConfiguration's to be created in parallel.
static const CoreConfiguration& BuildNewAndMaybeSet();

@ -50,26 +50,29 @@ class BinderResolverTest : public ::testing::Test {
}
~BinderResolverTest() override {}
static void SetUpTestSuite() {
grpc_core::CoreConfiguration::Reset();
grpc_core::CoreConfiguration::BuildSpecialConfiguration(
[](grpc_core::CoreConfiguration::Builder* builder) {
BuildCoreConfiguration(builder);
if (!builder->resolver_registry()->HasResolverFactory("binder")) {
// Binder resolver will only be registered on platforms that support
// binder transport. If it is not registered on current platform, we
// manually register it here for testing purpose.
RegisterBinderResolver(builder);
ASSERT_TRUE(
builder->resolver_registry()->HasResolverFactory("binder"));
}
});
builder_ =
std::make_unique<grpc_core::CoreConfiguration::WithSubstituteBuilder>(
[](grpc_core::CoreConfiguration::Builder* builder) {
BuildCoreConfiguration(builder);
if (!builder->resolver_registry()->HasResolverFactory("binder")) {
// Binder resolver will only be registered on platforms that
// support binder transport. If it is not registered on current
// platform, we manually register it here for testing purpose.
RegisterBinderResolver(builder);
ASSERT_TRUE(
builder->resolver_registry()->HasResolverFactory("binder"));
}
});
grpc_init();
if (grpc_core::CoreConfiguration::Get()
.resolver_registry()
.LookupResolverFactory("binder") == nullptr) {
}
}
static void TearDownTestSuite() { grpc_shutdown(); }
static void TearDownTestSuite() {
grpc_shutdown();
builder_.reset();
}
void SetUp() override { ASSERT_TRUE(factory_); }
@ -133,8 +136,13 @@ class BinderResolverTest : public ::testing::Test {
private:
grpc_core::ResolverFactory* factory_;
static std::unique_ptr<grpc_core::CoreConfiguration::WithSubstituteBuilder>
builder_;
};
std::unique_ptr<grpc_core::CoreConfiguration::WithSubstituteBuilder>
BinderResolverTest::builder_;
} // namespace
// Authority is not allowed

@ -152,8 +152,7 @@ class ErrorParser : public ServiceConfigParser::Parser {
class ServiceConfigTest : public ::testing::Test {
protected:
void SetUp() override {
CoreConfiguration::Reset();
CoreConfiguration::BuildSpecialConfiguration(
builder_ = std::make_unique<CoreConfiguration::WithSubstituteBuilder>(
[](CoreConfiguration::Builder* builder) {
builder->service_config_parser()->RegisterParser(
absl::make_unique<TestParser1>());
@ -167,6 +166,9 @@ class ServiceConfigTest : public ::testing::Test {
"test_parser_2"),
1);
}
private:
std::unique_ptr<CoreConfiguration::WithSubstituteBuilder> builder_;
};
TEST_F(ServiceConfigTest, ErrorCheck1) {
@ -406,7 +408,7 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
TEST(ServiceConfigParserTest, DoubleRegistration) {
CoreConfiguration::Reset();
ASSERT_DEATH_IF_SUPPORTED(
CoreConfiguration::BuildSpecialConfiguration(
CoreConfiguration::WithSubstituteBuilder builder(
[](CoreConfiguration::Builder* builder) {
builder->service_config_parser()->RegisterParser(
absl::make_unique<ErrorParser>("xyzabc"));
@ -420,8 +422,7 @@ TEST(ServiceConfigParserTest, DoubleRegistration) {
class ErroredParsersScopingTest : public ::testing::Test {
protected:
void SetUp() override {
CoreConfiguration::Reset();
CoreConfiguration::BuildSpecialConfiguration(
builder_ = std::make_unique<CoreConfiguration::WithSubstituteBuilder>(
[](CoreConfiguration::Builder* builder) {
builder->service_config_parser()->RegisterParser(
absl::make_unique<ErrorParser>("ep1"));
@ -435,6 +436,9 @@ class ErroredParsersScopingTest : public ::testing::Test {
CoreConfiguration::Get().service_config_parser().GetParserIndex("ep2"),
1);
}
private:
std::unique_ptr<CoreConfiguration::WithSubstituteBuilder> builder_;
};
TEST_F(ErroredParsersScopingTest, GlobalParams) {
@ -469,8 +473,7 @@ TEST_F(ErroredParsersScopingTest, MethodParams) {
class ClientChannelParserTest : public ::testing::Test {
protected:
void SetUp() override {
CoreConfiguration::Reset();
CoreConfiguration::BuildSpecialConfiguration(
builder_ = std::make_unique<CoreConfiguration::WithSubstituteBuilder>(
[](CoreConfiguration::Builder* builder) {
builder->service_config_parser()->RegisterParser(
absl::make_unique<internal::ClientChannelServiceConfigParser>());
@ -479,6 +482,9 @@ class ClientChannelParserTest : public ::testing::Test {
"client_channel"),
0);
}
private:
std::unique_ptr<CoreConfiguration::WithSubstituteBuilder> builder_;
};
TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigPickFirst) {
@ -754,8 +760,7 @@ TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
class RetryParserTest : public ::testing::Test {
protected:
void SetUp() override {
CoreConfiguration::Reset();
CoreConfiguration::BuildSpecialConfiguration(
builder_ = std::make_unique<CoreConfiguration::WithSubstituteBuilder>(
[](CoreConfiguration::Builder* builder) {
builder->service_config_parser()->RegisterParser(
absl::make_unique<internal::RetryServiceConfigParser>());
@ -764,6 +769,9 @@ class RetryParserTest : public ::testing::Test {
"retry"),
0);
}
private:
std::unique_ptr<CoreConfiguration::WithSubstituteBuilder> builder_;
};
TEST_F(RetryParserTest, ValidRetryThrottling) {
@ -1446,8 +1454,7 @@ TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutBadValue) {
class MessageSizeParserTest : public ::testing::Test {
protected:
void SetUp() override {
CoreConfiguration::Reset();
CoreConfiguration::BuildSpecialConfiguration(
builder_ = std::make_unique<CoreConfiguration::WithSubstituteBuilder>(
[](CoreConfiguration::Builder* builder) {
builder->service_config_parser()->RegisterParser(
absl::make_unique<MessageSizeParser>());
@ -1456,6 +1463,9 @@ class MessageSizeParserTest : public ::testing::Test {
"message_size"),
0);
}
private:
std::unique_ptr<CoreConfiguration::WithSubstituteBuilder> builder_;
};
TEST_F(MessageSizeParserTest, Valid) {

@ -79,7 +79,7 @@ class ReadAheadHandshakerFactory : public HandshakerFactory {
} // namespace grpc_core
TEST(HandshakeServerWithReadaheadHandshakerTest, MainTest) {
grpc_core::CoreConfiguration::BuildSpecialConfiguration(
grpc_core::CoreConfiguration::WithSubstituteBuilder builder(
[](grpc_core::CoreConfiguration::Builder* builder) {
BuildCoreConfiguration(builder);
builder->handshaker_registry()->RegisterHandshakerFactory(

@ -81,7 +81,7 @@ TEST_F(ChannelCredsRegistryTest, Register) {
nullptr);
// Registration.
CoreConfiguration::BuildSpecialConfiguration(
CoreConfiguration::WithSubstituteBuilder builder(
[](CoreConfiguration::Builder* builder) {
BuildCoreConfiguration(builder);
builder->channel_creds_registry()->RegisterChannelCredsFactory(

Loading…
Cancel
Save