diff --git a/README.md b/README.md index f5a0d58ca..36df4aee8 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ bazel build -c opt //:nighthawk ``` USAGE: -bazel-bin/nighthawk_client [--latency-response-header-name ] +bazel-bin/nighthawk_client [--allow-envoy-deprecated-v2-api] +[--latency-response-header-name ] [--stats-flush-interval ] [--stats-sinks ] ... [--no-duration] [--simple-warmup] @@ -83,6 +84,10 @@ format> Where: +--allow-envoy-deprecated-v2-api +Set to allow usage of the v2 api. (Not recommended, support will stop +in Q1 2021). Default: false + --latency-response-header-name Set an optional header name that will be returned in responses, whose values will be tracked in a latency histogram if set. Can be used in diff --git a/api/client/options.proto b/api/client/options.proto index d1108e908..3274dd015 100644 --- a/api/client/options.proto +++ b/api/client/options.proto @@ -106,7 +106,7 @@ message H1ConnectionReuseStrategy { // TODO(oschaaf): Ultimately this will be a load test specification. The fact that it // can arrive via CLI is just a concrete detail. Change this to reflect that. -// highest unused number is 38 +// highest unused number is 39 message CommandLineOptions { // The target requests-per-second rate. Default: 5. google.protobuf.UInt32Value requests_per_second = 1 @@ -220,6 +220,8 @@ message CommandLineOptions { // "emit_previous_request_delta_in_response_header" to record elapsed time between request // arrivals. google.protobuf.StringValue latency_response_header_name = 36; + // Set to allow usage of the v2 api. (Not recommended, support will stop in Q1 2021). + google.protobuf.BoolValue allow_envoy_deprecated_v2_api = 38 [deprecated = true]; // Provide an execution starting date and time. Optional, any value specified must be in the // future. google.protobuf.Timestamp scheduled_start = 105; diff --git a/include/nighthawk/client/options.h b/include/nighthawk/client/options.h index 5e6dc8292..a04292a86 100644 --- a/include/nighthawk/client/options.h +++ b/include/nighthawk/client/options.h @@ -75,6 +75,8 @@ class Options { virtual std::vector statsSinks() const PURE; virtual uint32_t statsFlushInterval() const PURE; virtual std::string responseHeaderWithLatencyInput() const PURE; + virtual bool allowEnvoyDeprecatedV2Api() const PURE; + virtual absl::optional scheduled_start() const PURE; /** * Converts an Options instance to an equivalent CommandLineOptions instance in terms of option diff --git a/source/client/options_impl.cc b/source/client/options_impl.cc index b4ff7ae3e..0ed825fe7 100644 --- a/source/client/options_impl.cc +++ b/source/client/options_impl.cc @@ -315,6 +315,12 @@ OptionsImpl::OptionsImpl(int argc, const char* const* argv) { "Default: \"\"", false, "", "string", cmd); + TCLAP::SwitchArg allow_envoy_deprecated_v2_api( + "", "allow-envoy-deprecated-v2-api", + "Set to allow usage of the v2 api. (Not recommended, support will stop in Q1 2021). Default: " + "false", + cmd); + Utility::parseCommand(cmd, argc, argv); // --duration and --no-duration are mutually exclusive @@ -447,6 +453,7 @@ OptionsImpl::OptionsImpl(int argc, const char* const* argv) { } TCLAP_SET_IF_SPECIFIED(stats_flush_interval, stats_flush_interval_); TCLAP_SET_IF_SPECIFIED(latency_response_header_name, latency_response_header_name_); + TCLAP_SET_IF_SPECIFIED(allow_envoy_deprecated_v2_api, allow_envoy_deprecated_v2_api_); // CLI-specific tests. // TODO(oschaaf): as per mergconflicts's remark, it would be nice to aggregate @@ -652,6 +659,8 @@ OptionsImpl::OptionsImpl(const nighthawk::client::CommandLineOptions& options) { std::copy(options.labels().begin(), options.labels().end(), std::back_inserter(labels_)); latency_response_header_name_ = PROTOBUF_GET_WRAPPED_OR_DEFAULT( options, latency_response_header_name, latency_response_header_name_); + allow_envoy_deprecated_v2_api_ = PROTOBUF_GET_WRAPPED_OR_DEFAULT( + options, allow_envoy_deprecated_v2_api, allow_envoy_deprecated_v2_api_); if (options.has_scheduled_start()) { const auto elapsed_since_epoch = std::chrono::nanoseconds(options.scheduled_start().nanos()) + std::chrono::seconds(options.scheduled_start().seconds()); @@ -834,6 +843,8 @@ CommandLineOptionsPtr OptionsImpl::toCommandLineOptionsInternal() const { command_line_options->mutable_stats_flush_interval()->set_value(stats_flush_interval_); command_line_options->mutable_latency_response_header_name()->set_value( latency_response_header_name_); + command_line_options->mutable_allow_envoy_deprecated_v2_api()->set_value( + allow_envoy_deprecated_v2_api_); if (scheduled_start_.has_value()) { *(command_line_options->mutable_scheduled_start()) = Envoy::ProtobufUtil::TimeUtil::NanosecondsToTimestamp( diff --git a/source/client/options_impl.h b/source/client/options_impl.h index 7132aba01..b84d80d3e 100644 --- a/source/client/options_impl.h +++ b/source/client/options_impl.h @@ -93,6 +93,7 @@ class OptionsImpl : public Options, public Envoy::Logger::Loggable scheduled_start() const override { return scheduled_start_; } private: @@ -150,6 +151,7 @@ class OptionsImpl : public Options, public Envoy::Logger::Loggable stats_sinks_; uint32_t stats_flush_interval_{5}; std::string latency_response_header_name_; + bool allow_envoy_deprecated_v2_api_{false}; absl::optional scheduled_start_; }; diff --git a/source/client/process_impl.cc b/source/client/process_impl.cc index cbf3b695d..dc8560238 100644 --- a/source/client/process_impl.cc +++ b/source/client/process_impl.cc @@ -276,10 +276,28 @@ ProcessImpl::mergeWorkerStatistics(const std::vector& workers) return merged_statistics; } +void ProcessImpl::allowEnvoyDeprecatedV2Api(envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + auto* admin_layer = bootstrap.mutable_layered_runtime()->add_layers(); + admin_layer->set_name("admin layer"); + admin_layer->mutable_admin_layer(); + envoy::config::bootstrap::v3::RuntimeLayer* runtime_layer = + bootstrap.mutable_layered_runtime()->add_layers(); + runtime_layer->set_name("static_layer"); + Envoy::ProtobufWkt::Value proto_true; + proto_true.set_string_value("true"); + (*runtime_layer->mutable_static_layer() + ->mutable_fields())["envoy.reloadable_features.enable_deprecated_v2_api"] = proto_true; +} + void ProcessImpl::createBootstrapConfiguration(envoy::config::bootstrap::v3::Bootstrap& bootstrap, const std::vector& uris, const UriPtr& request_source_uri, - int number_of_clusters) const { + int number_of_clusters, + bool allow_envoy_deprecated_v2_api) const { + if (allow_envoy_deprecated_v2_api) { + allowEnvoyDeprecatedV2Api(bootstrap); + } + for (int i = 0; i < number_of_clusters; i++) { auto* cluster = bootstrap.mutable_static_resources()->add_clusters(); RELEASE_ASSERT(!uris.empty(), "illegal configuration with zero endpoints"); @@ -466,7 +484,8 @@ bool ProcessImpl::runInternal(OutputCollector& collector, const std::vector( Envoy::Runtime::LoaderPtr{new Envoy::Runtime::LoaderImpl( - *dispatcher_, tls_, {}, *local_info_, store_root_, generator_, + *dispatcher_, tls_, bootstrap.layered_runtime(), *local_info_, store_root_, generator_, Envoy::ProtobufMessage::getStrictValidationVisitor(), *api_)}); ssl_context_manager_ = std::make_unique( diff --git a/source/client/process_impl.h b/source/client/process_impl.h index d14b86e6a..03a99a72a 100644 --- a/source/client/process_impl.h +++ b/source/client/process_impl.h @@ -30,6 +30,7 @@ #include "external/envoy/source/exe/process_wide.h" #include "external/envoy/source/extensions/transport_sockets/tls/context_manager_impl.h" #include "external/envoy/source/server/config_validation/admin.h" +#include "external/envoy_api/envoy/config/bootstrap/v3/bootstrap.pb.h" #include "client/benchmark_client_impl.h" #include "client/factories_impl.h" @@ -84,6 +85,12 @@ class ProcessImpl : public Process, public Envoy::Logger::Loggable& uris, - const UriPtr& request_source_uri, int number_of_workers) const; + const UriPtr& request_source_uri, int number_of_workers, + bool allow_envoy_deprecated_v2_api) const; void maybeCreateTracingDriver(const envoy::config::trace::v3::Tracing& configuration); - void configureComponentLogLevels(spdlog::level::level_enum level); /** * Prepare the ProcessImpl instance by creating and configuring the workers it needs for execution diff --git a/test/integration/BUILD b/test/integration/BUILD index 1290e6090..c9cd5ad68 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -13,6 +13,7 @@ py_library( name = "integration_test_base", data = [ "configurations/nighthawk_http_origin.yaml", + "configurations/nighthawk_http_origin_envoy_deprecated_v2_api.yaml", "configurations/nighthawk_https_origin.yaml", "configurations/nighthawk_track_timings.yaml", "configurations/sni_origin.yaml", diff --git a/test/integration/configurations/nighthawk_http_origin_envoy_deprecated_v2_api.yaml b/test/integration/configurations/nighthawk_http_origin_envoy_deprecated_v2_api.yaml new file mode 100644 index 000000000..0e795b6ba --- /dev/null +++ b/test/integration/configurations/nighthawk_http_origin_envoy_deprecated_v2_api.yaml @@ -0,0 +1,39 @@ +# This file is intentionally using the v2 api: it is used to test support for that. +admin: + access_log_path: $tmpdir/nighthawk-test-server-admin-access.log + profile_path: $tmpdir/nighthawk-test-server.prof + address: + socket_address: { address: $server_ip, port_value: 0 } +static_resources: + listeners: + - address: + socket_address: + address: $server_ip + port_value: 0 + filter_chains: + - filters: + - name: envoy.http_connection_manager + config: + generate_request_id: false + codec_type: auto + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: service + domains: + - "*" + http_filters: + - name: test-server + config: + response_body_size: 10 + response_headers: + - { header: { key: "x-nh", value: "1"}} + - name: envoy.router + config: + dynamic_stats: false +layered_runtime: + layers: + - name: static_layer + static_layer: + envoy.reloadable_features.enable_deprecated_v2_api: true diff --git a/test/integration/integration_test_fixtures.py b/test/integration/integration_test_fixtures.py index 7850eef26..34fea1d15 100644 --- a/test/integration/integration_test_fixtures.py +++ b/test/integration/integration_test_fixtures.py @@ -56,13 +56,15 @@ class IntegrationTestBase(): This class will be refactored (https://github.com/envoyproxy/nighthawk/issues/258). """ - def __init__(self, ip_version, server_config, backend_count=1): + def __init__(self, ip_version, server_config, backend_count=1, bootstrap_version_arg=None): """Initialize the IntegrationTestBase instance. Args: ip_version: a single IP mode that this instance will test: IpVersion.IPV4 or IpVersion.IPV6 server_config: path to the server configuration backend_count: number of Nighthawk Test Server backends to run, to allow testing MultiTarget mode + bootstrap_version_arg: An optional int, specify a bootstrap cli argument value for the test server binary. If None is specified, no bootstrap cli argment will be passed. + Attributes: ip_version: IP version that the proxy should use when listening. server_ip: string containing the server ip that will be used to listen @@ -90,6 +92,7 @@ def __init__(self, ip_version, server_config, backend_count=1): self._test_servers = [] self._backend_count = backend_count self._test_id = "" + self._bootstrap_version_arg = bootstrap_version_arg # TODO(oschaaf): For the NH test server, add a way to let it determine a port by itself and pull that # out. @@ -141,7 +144,8 @@ def _tryStartTestServers(self): self.server_ip, self.ip_version, parameters=self.parameters, - tag=self.tag) + tag=self.tag, + bootstrap_version_arg=self._bootstrap_version_arg) if not test_server.start(): return False self._test_servers.append(test_server) @@ -283,7 +287,7 @@ def startNighthawkGrpcService(self, service_name="traffic-generator-service"): class HttpIntegrationTestBase(IntegrationTestBase): """Base for running plain http tests against the Nighthawk test server. - NOTE: any script that consumes derivations of this, needs to needs also explictly + NOTE: any script that consumes derivations of this, needs to also explicitly import server_config, to avoid errors caused by the server_config not being found by pytest. """ @@ -297,6 +301,25 @@ def getTestServerRootUri(self): return super(HttpIntegrationTestBase, self).getTestServerRootUri(False) +class HttpIntegrationTestBaseWithEnvoyDeprecatedV2Bootstrap(IntegrationTestBase): + """Base for running plain http tests against the Nighthawk test server. + + NOTE: any script that consumes derivations of this, needs to also explicitly + import server_config, to avoid errors caused by the server_config not being found + by pytest. + """ + + def __init__(self, ip_version, server_config): + """See base class.""" + super(HttpIntegrationTestBaseWithEnvoyDeprecatedV2Bootstrap, + self).__init__(ip_version, server_config, bootstrap_version_arg=2) + + def getTestServerRootUri(self): + """See base class.""" + return super(HttpIntegrationTestBaseWithEnvoyDeprecatedV2Bootstrap, + self).getTestServerRootUri(False) + + class MultiServerHttpIntegrationTestBase(IntegrationTestBase): """Base for running plain http tests against multiple Nighthawk test servers.""" @@ -378,6 +401,19 @@ def http_test_server_fixture(request, server_config): f.tearDown() +@pytest.fixture(params=determineIpVersionsFromEnvironment()) +def http_test_server_fixture_envoy_deprecated_v2_api(request, server_config): + """Fixture for setting up a test environment with http server configuration that uses v2 configuration. + + Yields: + HttpIntegrationTestBaseWithEnvoyDeprecatedV2Bootstrap: A fully set up instance. Tear down will happen automatically. + """ + f = HttpIntegrationTestBaseWithEnvoyDeprecatedV2Bootstrap(request.param, server_config) + f.setUp() + yield f + f.tearDown() + + @pytest.fixture(params=determineIpVersionsFromEnvironment()) def https_test_server_fixture(request, server_config): """Fixture for setting up a test environment with the stock https server configuration. diff --git a/test/integration/nighthawk_test_server.py b/test/integration/nighthawk_test_server.py index e23911a3e..b4ee5d056 100644 --- a/test/integration/nighthawk_test_server.py +++ b/test/integration/nighthawk_test_server.py @@ -51,8 +51,15 @@ class TestServerBase(object): tmpdir: String, indicates the location used to store outputs like logs. """ - def __init__(self, server_binary_path, config_template_path, server_ip, ip_version, - server_binary_config_path_arg, parameters, tag): + def __init__(self, + server_binary_path, + config_template_path, + server_ip, + ip_version, + server_binary_config_path_arg, + parameters, + tag, + bootstrap_version_arg=None): """Initialize a TestServerBase instance. Args: @@ -63,6 +70,7 @@ def __init__(self, server_binary_path, config_template_path, server_ip, ip_versi server_binary_config_path_arg (str): Specify the name of the CLI argument the test server binary uses to accept a configuration path. parameters (dict): Supply to provide configuration template parameter replacement values. tag (str): Supply to get recognizeable output locations. + bootstrap_version_arg (int, optional): specify a bootstrap cli argument value for the test server binary. """ assert ip_version != IpVersion.UNKNOWN self.ip_version = ip_version @@ -82,6 +90,7 @@ def __init__(self, server_binary_path, config_template_path, server_ip, ip_versi self._parameterized_config_path = "" self._instance_id = str(random.randint(1, 1024 * 1024 * 1024)) self._server_binary_config_path_arg = server_binary_config_path_arg + self._bootstrap_version_arg = bootstrap_version_arg self._prepareForExecution() def _prepareForExecution(self): @@ -121,6 +130,9 @@ def _serverThreadRunner(self): self._parameterized_config_path, "-l", "debug", "--base-id", self._instance_id, "--admin-address-path", self._admin_address_path, "--concurrency", "1" ] + if self._bootstrap_version_arg is not None: + args = args + ["--bootstrap-version", str(self._bootstrap_version_arg)] + logging.info("Test server popen() args: %s" % str.join(" ", args)) self._server_process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = self._server_process.communicate() @@ -228,7 +240,8 @@ def __init__(self, server_ip, ip_version, parameters=dict(), - tag=""): + tag="", + bootstrap_version_arg=None): """Initialize a NighthawkTestServer instance. Args: @@ -238,9 +251,16 @@ def __init__(self, ip_version (IPVersion): IPVersion enum member indicating the ip version that the server should use when listening. parameters (dictionary, optional): Directionary with replacement values for substition purposes in the server configuration template. Defaults to dict(). tag (str, optional): Tags. Supply this to get recognizeable output locations. Defaults to "". + bootstrap_version_arg (String, optional): Specify a cli argument value for --bootstrap-version when running the server. """ - super(NighthawkTestServer, self).__init__(server_binary_path, config_template_path, server_ip, - ip_version, "--config-path", parameters, tag) + super(NighthawkTestServer, self).__init__(server_binary_path, + config_template_path, + server_ip, + ip_version, + "--config-path", + parameters, + tag, + bootstrap_version_arg=bootstrap_version_arg) def getCliVersionString(self): """Get the version string as written to the output by the CLI.""" diff --git a/test/integration/test_integration_basics.py b/test/integration/test_integration_basics.py index 3fe989aa6..630095abb 100644 --- a/test/integration/test_integration_basics.py +++ b/test/integration/test_integration_basics.py @@ -10,11 +10,10 @@ from threading import Thread from test.integration.common import IpVersion -from test.integration.integration_test_fixtures import (http_test_server_fixture, - https_test_server_fixture, - multi_http_test_server_fixture, - multi_https_test_server_fixture, - server_config) +from test.integration.integration_test_fixtures import ( + http_test_server_fixture, http_test_server_fixture_envoy_deprecated_v2_api, + https_test_server_fixture, https_test_server_fixture, multi_http_test_server_fixture, + multi_https_test_server_fixture, server_config) from test.integration import asserts from test.integration import utility @@ -69,6 +68,48 @@ def test_http_h1(http_test_server_fixture): asserts.assertEqual(len(counters), 12) +@pytest.mark.parametrize('server_config', [ + "nighthawk/test/integration/configurations/nighthawk_http_origin_envoy_deprecated_v2_api.yaml" +]) +def test_nighthawk_test_server_envoy_deprecated_v2_api( + http_test_server_fixture_envoy_deprecated_v2_api): + """Test that the v2 configuration works for the test server.""" + parsed_json, _ = http_test_server_fixture_envoy_deprecated_v2_api.runNighthawkClient([ + http_test_server_fixture_envoy_deprecated_v2_api.getTestServerRootUri(), "--duration", "100", + "--termination-predicate", "benchmark.http_2xx:24" + ]) + + counters = http_test_server_fixture_envoy_deprecated_v2_api.getNighthawkCounterMapFromJson( + parsed_json) + asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25) + + +def test_nighthawk_client_v2_api_explicitly_set(http_test_server_fixture): + """Test that the v2 api works when requested to.""" + parsed_json, _ = http_test_server_fixture.runNighthawkClient([ + http_test_server_fixture.getTestServerRootUri(), "--duration", "100", + "--termination-predicate", "benchmark.pool_connection_failure:0", "--failure-predicate", + "foo:1", "--allow-envoy-deprecated-v2-api", "--transport-socket", + "{name:\"envoy.transport_sockets.tls\",typed_config:{\"@type\":\"type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext\",\"common_tls_context\":{}}}" + ]) + + counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json) + asserts.assertCounterEqual(counters, "benchmark.pool_connection_failure", 1) + + +# TODO(oschaaf): This ought to work after the Envoy update. +def DISABLED_test_nighthawk_client_v2_api_breaks_by_default(http_test_server_fixture): + """Test that the v2 api breaks us when it's not explicitly requested.""" + _, _ = http_test_server_fixture.runNighthawkClient([ + http_test_server_fixture.getTestServerRootUri(), "--duration", "100", + "--termination-predicate", "benchmark.pool_connection_failure:0", "--failure-predicate", + "foo:1", "--transport-socket", + "{name:\"envoy.transport_sockets.tls\",typed_config:{\"@type\":\"type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext\",\"common_tls_context\":{}}}" + ], + expect_failure=True, + as_json=False) + + def _mini_stress_test(fixture, args): # run a test with more rps then we can handle, and a very small client-side queue. # we should observe both lots of successfull requests as well as time spend in blocking mode., diff --git a/test/mocks/client/mock_options.h b/test/mocks/client/mock_options.h index 04fc35ec0..a6e85d42c 100644 --- a/test/mocks/client/mock_options.h +++ b/test/mocks/client/mock_options.h @@ -57,6 +57,7 @@ class MockOptions : public Options { MOCK_CONST_METHOD0(statsSinks, std::vector()); MOCK_CONST_METHOD0(statsFlushInterval, uint32_t()); MOCK_CONST_METHOD0(responseHeaderWithLatencyInput, std::string()); + MOCK_CONST_METHOD0(allowEnvoyDeprecatedV2Api, bool()); MOCK_CONST_METHOD0(scheduled_start, absl::optional()); }; diff --git a/test/options_test.cc b/test/options_test.cc index d65604b67..a1f6c143b 100644 --- a/test/options_test.cc +++ b/test/options_test.cc @@ -118,7 +118,7 @@ TEST_F(OptionsImplTest, AlmostAll) { "--experimental-h2-use-multiple-connections " "--experimental-h1-connection-reuse-strategy lru --label label1 --label label2 {} " "--simple-warmup --stats-sinks {} --stats-sinks {} --stats-flush-interval 10 " - "--latency-response-header-name zz", + "--latency-response-header-name zz --allow-envoy-deprecated-v2-api", client_name_, "{name:\"envoy.transport_sockets.tls\"," "typed_config:{\"@type\":\"type.googleapis.com/" @@ -193,6 +193,7 @@ TEST_F(OptionsImplTest, AlmostAll) { "183412668: \"envoy.config.metrics.v2.StatsSink\"\n", options->statsSinks()[1].DebugString()); EXPECT_EQ("zz", options->responseHeaderWithLatencyInput()); + EXPECT_TRUE(options->allowEnvoyDeprecatedV2Api()); // Check that our conversion to CommandLineOptionsPtr makes sense. CommandLineOptionsPtr cmd = options->toCommandLineOptions(); @@ -251,6 +252,8 @@ TEST_F(OptionsImplTest, AlmostAll) { EXPECT_TRUE(util(cmd->stats_sinks(0), options->statsSinks()[0])); EXPECT_TRUE(util(cmd->stats_sinks(1), options->statsSinks()[1])); EXPECT_EQ(cmd->latency_response_header_name().value(), options->responseHeaderWithLatencyInput()); + ASSERT_TRUE(cmd->has_allow_envoy_deprecated_v2_api()); + EXPECT_EQ(cmd->allow_envoy_deprecated_v2_api().value(), options->allowEnvoyDeprecatedV2Api()); // TODO(#433) Here and below, replace comparisons once we choose a proto diff. OptionsImpl options_from_proto(*cmd); std::string s1 = Envoy::MessageUtil::getYamlStringFromMessage( @@ -594,6 +597,22 @@ TEST_F(OptionsImplTest, PrefetchConnectionsFlag) { MalformedArgvException, "Couldn't find match for argument"); } +TEST_F(OptionsImplTest, AllowEnvoyDeprecatedV2ApiFlag) { + EXPECT_FALSE(TestUtility::createOptionsImpl(fmt::format("{} {}", client_name_, good_test_uri_)) + ->allowEnvoyDeprecatedV2Api()); + EXPECT_TRUE(TestUtility::createOptionsImpl(fmt::format("{} --allow-envoy-deprecated-v2-api {}", + client_name_, good_test_uri_)) + ->allowEnvoyDeprecatedV2Api()); + EXPECT_THROW_WITH_REGEX( + TestUtility::createOptionsImpl( + fmt::format("{} --allow-envoy-deprecated-v2-api 0 {}", client_name_, good_test_uri_)), + MalformedArgvException, "Couldn't find match for argument"); + EXPECT_THROW_WITH_REGEX( + TestUtility::createOptionsImpl( + fmt::format("{} --allow-envoy-deprecated-v2-api true {}", client_name_, good_test_uri_)), + MalformedArgvException, "Couldn't find match for argument"); +} + // Test --concurrency, which is a bit special. It's an int option, which also accepts 'auto' as // a value. We need to implement some stuff ourselves to get this to work, hence we don't run it // through the OptionsImplIntTest. diff --git a/test/process_test.cc b/test/process_test.cc index 7d1191790..077f60ef4 100644 --- a/test/process_test.cc +++ b/test/process_test.cc @@ -9,6 +9,7 @@ #include "external/envoy/test/test_common/registry.h" #include "external/envoy/test/test_common/simulated_time_system.h" #include "external/envoy/test/test_common/utility.h" +#include "external/envoy_api/envoy/config/bootstrap/v3/bootstrap.pb.h" #include "common/uri_impl.h" @@ -180,6 +181,32 @@ TEST_P(ProcessTest, NoFlushWhenCancelExecutionBeforeLoadTestBegin) { EXPECT_EQ(numFlushes, 0); } +TEST(RuntimeConfiguration, allowEnvoyDeprecatedV2Api) { + envoy::config::bootstrap::v3::Bootstrap bootstrap; + EXPECT_EQ(bootstrap.DebugString(), ""); + ProcessImpl::allowEnvoyDeprecatedV2Api(bootstrap); + std::cerr << bootstrap.DebugString() << std::endl; + EXPECT_EQ(bootstrap.DebugString(), R"EOF(layered_runtime { + layers { + name: "admin layer" + admin_layer { + } + } + layers { + name: "static_layer" + static_layer { + fields { + key: "envoy.reloadable_features.enable_deprecated_v2_api" + value { + string_value: "true" + } + } + } + } +} +)EOF"); +} + /** * Fixture for executing the Nighthawk process with simulated time. */