diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index 1385bfc3fa..25e5758a9a 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -37,6 +37,7 @@ Features: - iOS: add support for integrating Envoy Mobile via the Swift Package Manager - android: create simple persistent SharedPreferencesStore (:issue: `#2319 <2319>`) - iOS: A documentation archive is now included in the GitHub release artifact (:issue: `#2335 <2335>`) +- api: improved C++ APIs compatibility with Java / Kotlin / Swift (:issue `#2362 <2362>`) 0.4.6 (April 26, 2022) ======================== diff --git a/library/cc/bridge_utility.cc b/library/cc/bridge_utility.cc index aea3858e63..d5ba013efc 100644 --- a/library/cc/bridge_utility.cc +++ b/library/cc/bridge_utility.cc @@ -47,7 +47,7 @@ RawHeaderMap envoyHeadersAsRawHeaderMap(envoy_headers raw_headers) { // free instead of release_envoy_headers // because we already free each envoy_data individually // during calls to envoy_data_as_string - free(raw_headers.entries); + release_envoy_headers(raw_headers); return headers; } diff --git a/library/cc/engine_builder.cc b/library/cc/engine_builder.cc index 5d9477f645..8a4f00e6fd 100644 --- a/library/cc/engine_builder.cc +++ b/library/cc/engine_builder.cc @@ -93,6 +93,11 @@ EngineBuilder& EngineBuilder::setDeviceOs(const std::string& device_os) { return *this; } +EngineBuilder& EngineBuilder::setStreamIdleTimeoutSeconds(int stream_idle_timeout_seconds) { + this->stream_idle_timeout_seconds_ = stream_idle_timeout_seconds; + return *this; +} + EngineBuilder& EngineBuilder::enableGzip(bool gzip_on) { this->gzip_filter_ = gzip_on; return *this; @@ -166,10 +171,16 @@ EngineSharedPtr EngineBuilder::build() { envoy_event_tracker null_tracker{}; - auto config_str = this->generateConfigStr(); + std::string config_str; + if (config_override_for_tests_.empty()) { + config_str = this->generateConfigStr(); + } else { + config_str = config_override_for_tests_; + } auto envoy_engine = init_engine(this->callbacks_->asEnvoyEngineCallbacks(), null_logger, null_tracker); - run_engine(envoy_engine, config_str.c_str(), logLevelToString(this->log_level_).c_str()); + run_engine(envoy_engine, config_str.c_str(), logLevelToString(this->log_level_).c_str(), + this->admin_address_path_for_tests_.c_str()); // we can't construct via std::make_shared // because Engine is only constructible as a friend diff --git a/library/cc/engine_builder.h b/library/cc/engine_builder.h index f978fff14c..af04bf59ec 100644 --- a/library/cc/engine_builder.h +++ b/library/cc/engine_builder.h @@ -33,6 +33,7 @@ class EngineBuilder { EngineBuilder& setAppVersion(const std::string& app_version); EngineBuilder& setAppId(const std::string& app_id); EngineBuilder& setDeviceOs(const std::string& app_id); + EngineBuilder& setStreamIdleTimeoutSeconds(int stream_idle_timeout_seconds); EngineBuilder& enableGzip(bool gzip_on); EngineBuilder& enableBrotli(bool brotli_on); @@ -46,6 +47,9 @@ class EngineBuilder { // Filter): EngineBuilder& addNativeFilter(name: String = UUID.randomUUID().toString(), // typedConfig: String): EngineBuilder& addStringAccessor(name: String, accessor: // EnvoyStringAccessor): EngineBuilder { +protected: + void setOverrideConfigForTests(std::string config) { config_override_for_tests_ = config; } + void setAdminAddressPathForTests(std::string admin) { admin_address_path_for_tests_ = admin; } private: LogLevel log_level_ = LogLevel::info; @@ -66,6 +70,8 @@ class EngineBuilder { std::string app_id_ = "unspecified"; std::string device_os_ = "unspecified"; std::string virtual_clusters_ = "[]"; + std::string config_override_for_tests_ = ""; + std::string admin_address_path_for_tests_ = ""; int stream_idle_timeout_seconds_ = 15; int per_try_idle_timeout_seconds_ = 15; bool gzip_filter_ = true; diff --git a/library/cc/stream_callbacks.cc b/library/cc/stream_callbacks.cc index 1a6203f9cd..8673094d1a 100644 --- a/library/cc/stream_callbacks.cc +++ b/library/cc/stream_callbacks.cc @@ -10,7 +10,8 @@ namespace Platform { namespace { -void* c_on_headers(envoy_headers headers, bool end_stream, envoy_stream_intel, void* context) { +void* c_on_headers(envoy_headers headers, bool end_stream, envoy_stream_intel intel, + void* context) { auto stream_callbacks = *static_cast(context); if (stream_callbacks->on_headers.has_value()) { auto raw_headers = envoyHeadersAsRawHeaderMap(headers); @@ -22,7 +23,9 @@ void* c_on_headers(envoy_headers headers, bool end_stream, envoy_stream_intel, v builder.set(pair.first, pair.second); } auto on_headers = stream_callbacks->on_headers.value(); - on_headers(builder.build(), end_stream); + on_headers(builder.build(), end_stream, intel); + } else { + release_envoy_headers(headers); } return context; } @@ -32,11 +35,13 @@ void* c_on_data(envoy_data data, bool end_stream, envoy_stream_intel, void* cont if (stream_callbacks->on_data.has_value()) { auto on_data = stream_callbacks->on_data.value(); on_data(data, end_stream); + } else { + release_envoy_data(data); } return context; } -void* c_on_trailers(envoy_headers metadata, envoy_stream_intel, void* context) { +void* c_on_trailers(envoy_headers metadata, envoy_stream_intel intel, void* context) { auto stream_callbacks = *static_cast(context); if (stream_callbacks->on_trailers.has_value()) { auto raw_headers = envoyHeadersAsRawHeaderMap(metadata); @@ -45,13 +50,15 @@ void* c_on_trailers(envoy_headers metadata, envoy_stream_intel, void* context) { builder.set(pair.first, pair.second); } auto on_trailers = stream_callbacks->on_trailers.value(); - on_trailers(builder.build()); + on_trailers(builder.build(), intel); + } else { + release_envoy_headers(metadata); } return context; } -void* c_on_error(envoy_error raw_error, envoy_stream_intel, envoy_final_stream_intel, - void* context) { +void* c_on_error(envoy_error raw_error, envoy_stream_intel intel, + envoy_final_stream_intel final_intel, void* context) { auto stream_callbacks_ptr = static_cast(context); auto stream_callbacks = *stream_callbacks_ptr; if (stream_callbacks->on_error.has_value()) { @@ -60,40 +67,41 @@ void* c_on_error(envoy_error raw_error, envoy_stream_intel, envoy_final_stream_i error->message = Data::Utility::copyToString(raw_error.message); error->attempt_count = absl::optional(raw_error.attempt_count); auto on_error = stream_callbacks->on_error.value(); - on_error(error); + on_error(error, intel, final_intel); } + release_envoy_error(raw_error); delete stream_callbacks_ptr; return nullptr; } -void* c_on_complete(envoy_stream_intel, envoy_final_stream_intel, void* context) { +void* c_on_complete(envoy_stream_intel intel, envoy_final_stream_intel final_intel, void* context) { auto stream_callbacks_ptr = static_cast(context); auto stream_callbacks = *stream_callbacks_ptr; if (stream_callbacks->on_complete.has_value()) { auto on_complete = stream_callbacks->on_complete.value(); - on_complete(); + on_complete(intel, final_intel); } delete stream_callbacks_ptr; return nullptr; } -void* c_on_cancel(envoy_stream_intel, envoy_final_stream_intel, void* context) { +void* c_on_cancel(envoy_stream_intel intel, envoy_final_stream_intel final_intel, void* context) { auto stream_callbacks_ptr = static_cast(context); auto stream_callbacks = *stream_callbacks_ptr; if (stream_callbacks->on_cancel.has_value()) { auto on_cancel = stream_callbacks->on_cancel.value(); - on_cancel(); + on_cancel(intel, final_intel); } delete stream_callbacks_ptr; return nullptr; } -void* c_on_send_window_available(envoy_stream_intel, void* context) { +void* c_on_send_window_available(envoy_stream_intel intel, void* context) { auto stream_callbacks_ptr = static_cast(context); auto stream_callbacks = *stream_callbacks_ptr; if (stream_callbacks->on_send_window_available.has_value()) { auto on_send_window_available = stream_callbacks->on_send_window_available.value(); - on_send_window_available(); + on_send_window_available(intel); } delete stream_callbacks_ptr; return nullptr; diff --git a/library/cc/stream_callbacks.h b/library/cc/stream_callbacks.h index 4a7622fa3e..21c9769bb3 100644 --- a/library/cc/stream_callbacks.h +++ b/library/cc/stream_callbacks.h @@ -17,13 +17,18 @@ namespace Platform { class Stream; using StreamSharedPtr = std::shared_ptr; -using OnHeadersCallback = std::function; +using OnHeadersCallback = std::function; using OnDataCallback = std::function; -using OnTrailersCallback = std::function; -using OnErrorCallback = std::function; -using OnCompleteCallback = std::function; -using OnCancelCallback = std::function; -using OnSendWindowAvailableCallback = std::function; +using OnTrailersCallback = + std::function; +using OnErrorCallback = std::function; +using OnCompleteCallback = + std::function; +using OnCancelCallback = + std::function; +using OnSendWindowAvailableCallback = std::function; // See library/common/types/c_types.h for what these callbacks should do. struct StreamCallbacks : public std::enable_shared_from_this { diff --git a/library/cc/stream_prototype.cc b/library/cc/stream_prototype.cc index b3224b4da1..7764d0af2f 100644 --- a/library/cc/stream_prototype.cc +++ b/library/cc/stream_prototype.cc @@ -9,10 +9,10 @@ StreamPrototype::StreamPrototype(EngineSharedPtr engine) : engine_(engine) { this->callbacks_ = std::make_shared(); } -StreamSharedPtr StreamPrototype::start() { +StreamSharedPtr StreamPrototype::start(bool explicit_flow_control) { auto envoy_stream = init_stream(this->engine_->engine_); start_stream(this->engine_->engine_, envoy_stream, this->callbacks_->asEnvoyHttpCallbacks(), - false); + explicit_flow_control); return std::make_shared(this->engine_->engine_, envoy_stream); } diff --git a/library/cc/stream_prototype.h b/library/cc/stream_prototype.h index d285fa7e57..3278a7a2f0 100644 --- a/library/cc/stream_prototype.h +++ b/library/cc/stream_prototype.h @@ -20,7 +20,7 @@ class StreamPrototype { public: StreamPrototype(EngineSharedPtr engine); - StreamSharedPtr start(); + StreamSharedPtr start(bool explicit_flow_control = false); StreamPrototype& setOnHeaders(OnHeadersCallback closure); StreamPrototype& setOnData(OnDataCallback closure); diff --git a/library/common/engine.cc b/library/common/engine.cc index 74b9e34743..e342fa07f6 100644 --- a/library/common/engine.cc +++ b/library/common/engine.cc @@ -27,16 +27,19 @@ Engine::Engine(envoy_engine_callbacks callbacks, envoy_logger logger, Envoy::Api::External::registerApi(std::string(envoy_event_tracker_api_name), &event_tracker_); } -envoy_status_t Engine::run(const std::string config, const std::string log_level) { +envoy_status_t Engine::run(const std::string config, const std::string log_level, + const std::string admin_address_path) { // Start the Envoy on the dedicated thread. Note: due to how the assignment operator works with // std::thread, main_thread_ is the same object after this call, but its state is replaced with // that of the temporary. The temporary object's state becomes the default state, which does // nothing. - main_thread_ = std::thread(&Engine::main, this, std::string(config), std::string(log_level)); + main_thread_ = std::thread(&Engine::main, this, std::string(config), std::string(log_level), + admin_address_path); return ENVOY_SUCCESS; } -envoy_status_t Engine::main(const std::string config, const std::string log_level) { +envoy_status_t Engine::main(const std::string config, const std::string log_level, + const std::string admin_address_path) { // Using unique_ptr ensures main_common's lifespan is strictly scoped to this function. std::unique_ptr main_common; const std::string name = "envoy"; @@ -51,8 +54,12 @@ envoy_status_t Engine::main(const std::string config, const std::string log_leve concurrency_option.c_str(), concurrency_arg.c_str(), log_flag.c_str(), - log_level.c_str(), - nullptr}; + log_level.c_str()}; + if (!admin_address_path.empty()) { + envoy_argv.push_back("--admin-address-path"); + envoy_argv.push_back(admin_address_path.c_str()); + } + envoy_argv.push_back(nullptr); { Thread::LockGuard lock(mutex_); try { diff --git a/library/common/engine.h b/library/common/engine.h index 82c2eff943..f4a551bd32 100644 --- a/library/common/engine.h +++ b/library/common/engine.h @@ -34,8 +34,10 @@ class Engine : public Logger::Loggable { * Run the engine with the provided configuration. * @param config, the Envoy bootstrap configuration to use. * @param log_level, the log level. + * @param admin_address_path to set --admin-address-path, or an empty string if not needed. */ - envoy_status_t run(std::string config, std::string log_level); + envoy_status_t run(std::string config, std::string log_level, + const std::string admin_address_path); /** * Immediately terminate the engine, if running. @@ -128,7 +130,7 @@ class Engine : public Logger::Loggable { Upstream::ClusterManager& getClusterManager(); private: - envoy_status_t main(std::string config, std::string log_level); + envoy_status_t main(std::string config, std::string log_level, std::string admin_address_path); static void logInterfaces(absl::string_view event, std::vector& interfaces); diff --git a/library/common/engine_handle.cc b/library/common/engine_handle.cc index 8cccdce1b9..c80d3a5ecc 100644 --- a/library/common/engine_handle.cc +++ b/library/common/engine_handle.cc @@ -23,11 +23,12 @@ envoy_engine_t EngineHandle::initEngine(envoy_engine_callbacks callbacks, envoy_ return 1; } -envoy_status_t EngineHandle::runEngine(envoy_engine_t, const char* config, const char* log_level) { +envoy_status_t EngineHandle::runEngine(envoy_engine_t, const char* config, const char* log_level, + const char* admin_address_path) { // This will change once multiple engine support is in place. // https://github.com/envoyproxy/envoy-mobile/issues/332 if (auto e = engine()) { - e->run(config, log_level); + e->run(config, log_level, admin_address_path); return ENVOY_SUCCESS; } diff --git a/library/common/engine_handle.h b/library/common/engine_handle.h index 90a8784df0..cc322e54bd 100644 --- a/library/common/engine_handle.h +++ b/library/common/engine_handle.h @@ -30,7 +30,8 @@ class EngineHandle { static envoy_engine_t initEngine(envoy_engine_callbacks callbacks, envoy_logger logger, envoy_event_tracker event_tracker); - static envoy_status_t runEngine(envoy_engine_t, const char* config, const char* log_level); + static envoy_status_t runEngine(envoy_engine_t, const char* config, const char* log_level, + const char* admin_address_path); static void terminateEngine(envoy_engine_t); static EngineSharedPtr strong_engine_; @@ -39,7 +40,8 @@ class EngineHandle { // Allow a specific list of functions to access the internal setup/teardown functionality. friend envoy_engine_t(::init_engine)(envoy_engine_callbacks callbacks, envoy_logger logger, envoy_event_tracker event_tracker); - friend envoy_status_t(::run_engine)(envoy_engine_t, const char* config, const char* log_level); + friend envoy_status_t(::run_engine)(envoy_engine_t, const char* config, const char* log_level, + const char* admin_address_path); friend void ::terminate_engine(envoy_engine_t engine); }; diff --git a/library/common/jni/jni_interface.cc b/library/common/jni/jni_interface.cc index 50617b90d4..2ee2de15dc 100644 --- a/library/common/jni/jni_interface.cc +++ b/library/common/jni/jni_interface.cc @@ -120,7 +120,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr extern "C" JNIEXPORT jint JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibrary_runEngine( JNIEnv* env, jclass, jlong engine, jstring config, jstring log_level) { return run_engine(engine, env->GetStringUTFChars(config, nullptr), - env->GetStringUTFChars(log_level, nullptr)); + env->GetStringUTFChars(log_level, nullptr), ""); } extern "C" JNIEXPORT void JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibrary_terminateEngine( diff --git a/library/common/main_interface.cc b/library/common/main_interface.cc index a8a70d6c7c..b9fcb4851e 100644 --- a/library/common/main_interface.cc +++ b/library/common/main_interface.cc @@ -182,8 +182,9 @@ envoy_engine_t init_engine(envoy_engine_callbacks callbacks, envoy_logger logger return Envoy::EngineHandle::initEngine(callbacks, logger, event_tracker); } -envoy_status_t run_engine(envoy_engine_t engine, const char* config, const char* log_level) { - return Envoy::EngineHandle::runEngine(engine, config, log_level); +envoy_status_t run_engine(envoy_engine_t engine, const char* config, const char* log_level, + const char* admin_path) { + return Envoy::EngineHandle::runEngine(engine, config, log_level, admin_path); } void terminate_engine(envoy_engine_t engine) { Envoy::EngineHandle::terminateEngine(engine); } diff --git a/library/common/main_interface.h b/library/common/main_interface.h index 45b239f964..4fd3f5c80f 100644 --- a/library/common/main_interface.h +++ b/library/common/main_interface.h @@ -191,9 +191,11 @@ envoy_engine_t init_engine(envoy_engine_callbacks callbacks, envoy_logger logger * @param engine, handle to the engine to run. * @param config, the configuration blob to run envoy with. * @param log_level, the logging level to run envoy with. + * @param admin_path, the file path to log the admin address to if desired. * @return envoy_status_t, the resulting status of the operation. */ -envoy_status_t run_engine(envoy_engine_t engine, const char* config, const char* log_level); +envoy_status_t run_engine(envoy_engine_t engine, const char* config, const char* log_level, + const char* admin_path); /** * Terminate an engine. Further interactions with a terminated engine, or streams created by a diff --git a/library/objective-c/EnvoyEngineImpl.m b/library/objective-c/EnvoyEngineImpl.m index 3b583fb2a7..c298cd62bd 100644 --- a/library/objective-c/EnvoyEngineImpl.m +++ b/library/objective-c/EnvoyEngineImpl.m @@ -560,7 +560,7 @@ - (int)runWithConfigYAML:(NSString *)configYAML logLevel:(NSString *)logLevel { // Envoy exceptions will only be caught here when compiled for 64-bit arches. // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html @try { - return (int)run_engine(_engineHandle, configYAML.UTF8String, logLevel.UTF8String); + return (int)run_engine(_engineHandle, configYAML.UTF8String, logLevel.UTF8String, ""); } @catch (NSException *exception) { NSLog(@"[Envoy] exception caught: %@", exception); [NSNotificationCenter.defaultCenter postNotificationName:@"EnvoyError" object:self]; diff --git a/library/python/envoy_requests/common/core.py b/library/python/envoy_requests/common/core.py index 76aca16f68..4225ea1497 100644 --- a/library/python/envoy_requests/common/core.py +++ b/library/python/envoy_requests/common/core.py @@ -31,13 +31,13 @@ def make_stream( response: Response, set_stream_complete: Callable[[], None], ): - def _on_headers(headers: envoy_engine.ResponseHeaders, _: bool): + def _on_headers(headers: envoy_engine.ResponseHeaders, _: bool, intel: envoy_engine.StreamIntel): response.status_code = headers.http_status() for key in headers: value = headers[key] response.headers[key] = value[0] if len(value) == 1 else value - def _on_trailers(trailers: envoy_engine.ResponseTrailers): + def _on_trailers(trailers: envoy_engine.ResponseTrailers, intel: envoy_engine.StreamIntel): for key in trailers: value = trailers[key] response.trailers[key] = value[0] if len(value) == 1 else value @@ -45,14 +45,14 @@ def _on_trailers(trailers: envoy_engine.ResponseTrailers): def _on_data(data: bytes, _: bool): response.body_raw.extend(data) - def _on_complete(): + def _on_complete(intel: envoy_engine.StreamIntel, _: envoy_engine.FinalStreamIntel): set_stream_complete() - def _on_error(error: envoy_engine.EnvoyError): + def _on_error(error: envoy_engine.EnvoyError, intel: envoy_engine.StreamIntel, _: envoy_engine.FinalStreamIntel): response.envoy_error = error set_stream_complete() - def _on_cancel(): + def _on_cancel(intel: envoy_engine.StreamIntel, _: envoy_engine.FinalStreamIntel): set_stream_complete() return ( @@ -64,7 +64,7 @@ def _on_cancel(): .set_on_complete(executor.wrap(_on_complete)) .set_on_error(executor.wrap(_on_error)) .set_on_cancel(executor.wrap(_on_cancel)) - .start() + .start(False) ) diff --git a/library/python/module_definition.cc b/library/python/module_definition.cc index 10fdbfe5c9..be2321863f 100644 --- a/library/python/module_definition.cc +++ b/library/python/module_definition.cc @@ -30,7 +30,7 @@ #include "library/cc/stream_client.h" #include "library/cc/stream_prototype.h" #include "library/cc/upstream_http_protocol.h" - +#include "library/common/types/c_types.h" #include "library/common/types/c_types.h" #include "library/python/engine_builder_shim.h" @@ -148,6 +148,16 @@ PYBIND11_MODULE(envoy_engine, m) { .def("remove", &RequestTrailersBuilder::remove) .def("build", &RequestTrailersBuilder::build); + py::class_(m, "StreamIntel") + .def("stream_start_ms", [](envoy_stream_intel intel) { return intel.stream_id; }) + .def("connection_id", [](envoy_stream_intel intel) { return intel.connection_id; }) + .def("attempt_count", [](envoy_stream_intel intel) { return intel.attempt_count; }) + .def("consumed_bytes_from_response", + [](envoy_stream_intel intel) { return intel.consumed_bytes_from_response; }); + + py::class_(m, "FinalStreamIntel") + .def("response_flags", [](envoy_final_stream_intel intel) { return intel.response_flags; }); + py::class_(m, "ResponseHeaders") .def("__getitem__", &ResponseHeaders::operator[]) .def("__len__", diff --git a/test/cc/integration/lifetimes_test.cc b/test/cc/integration/lifetimes_test.cc index a91aaf069a..5588bcb4dd 100644 --- a/test/cc/integration/lifetimes_test.cc +++ b/test/cc/integration/lifetimes_test.cc @@ -59,16 +59,22 @@ void sendRequest(Platform::EngineSharedPtr engine, Status& status, absl::Notification& stream_complete) { auto stream_prototype = engine->streamClient()->newStreamPrototype(); auto stream = (*stream_prototype) - .setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool end_stream) { + .setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, + envoy_stream_intel) { status.status_code = headers->httpStatus(); status.end_stream = end_stream; }) - .setOnComplete([&]() { stream_complete.Notify(); }) - .setOnError([&](Platform::EnvoyErrorSharedPtr envoy_error) { + .setOnComplete([&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }) + .setOnError([&](Platform::EnvoyErrorSharedPtr envoy_error, envoy_stream_intel, + envoy_final_stream_intel) { (void)envoy_error; stream_complete.Notify(); }) - .setOnCancel([&]() { stream_complete.Notify(); }) + .setOnCancel([&](envoy_stream_intel, envoy_final_stream_intel) { + stream_complete.Notify(); + }) .start(); auto request_headers = diff --git a/test/cc/integration/send_headers_test.cc b/test/cc/integration/send_headers_test.cc index 0d7482654d..fae054c4fc 100644 --- a/test/cc/integration/send_headers_test.cc +++ b/test/cc/integration/send_headers_test.cc @@ -69,16 +69,20 @@ TEST(TestSendHeaders, CanSendHeaders) { Platform::StreamSharedPtr stream; auto stream_prototype = engine->streamClient()->newStreamPrototype(); - stream_prototype->setOnHeaders([&](Platform::ResponseHeadersSharedPtr headers, bool end_stream) { - status.status_code = headers->httpStatus(); - status.end_stream = end_stream; - }); - stream_prototype->setOnComplete([&]() { stream_complete.Notify(); }); - stream_prototype->setOnError([&](Platform::EnvoyErrorSharedPtr envoy_error) { - (void)envoy_error; - stream_complete.Notify(); - }); - stream_prototype->setOnCancel([&]() { stream_complete.Notify(); }); + stream_prototype->setOnHeaders( + [&](Platform::ResponseHeadersSharedPtr headers, bool end_stream, envoy_stream_intel) { + status.status_code = headers->httpStatus(); + status.end_stream = end_stream; + }); + stream_prototype->setOnComplete( + [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }); + stream_prototype->setOnError( + [&](Platform::EnvoyErrorSharedPtr envoy_error, envoy_stream_intel, envoy_final_stream_intel) { + (void)envoy_error; + stream_complete.Notify(); + }); + stream_prototype->setOnCancel( + [&](envoy_stream_intel, envoy_final_stream_intel) { stream_complete.Notify(); }); stream = stream_prototype->start(); diff --git a/test/common/engine_test.cc b/test/common/engine_test.cc index 30465e6666..3d3701d4f2 100644 --- a/test/common/engine_test.cc +++ b/test/common/engine_test.cc @@ -50,7 +50,7 @@ struct TestEngineHandle { envoy_engine_t handle_; TestEngineHandle(envoy_engine_callbacks callbacks, const std::string& level) { handle_ = init_engine(callbacks, {}, {}); - run_engine(handle_, MINIMAL_TEST_CONFIG.c_str(), level.c_str()); + run_engine(handle_, MINIMAL_TEST_CONFIG.c_str(), level.c_str(), ""); } void terminate() { terminate_engine(handle_); } diff --git a/test/common/integration/base_client_integration_test.cc b/test/common/integration/base_client_integration_test.cc index 6f66f03884..191eeee99e 100644 --- a/test/common/integration/base_client_integration_test.cc +++ b/test/common/integration/base_client_integration_test.cc @@ -7,13 +7,36 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "library/cc/engine_builder.h" #include "library/common/config/internal.h" #include "library/common/http/header_utility.h" namespace Envoy { namespace { +void validateStreamIntel(const envoy_final_stream_intel& final_intel, bool expect_dns) { + if (expect_dns) { + EXPECT_NE(-1, final_intel.dns_start_ms); + EXPECT_NE(-1, final_intel.dns_end_ms); + } + // This test doesn't do TLS. + EXPECT_EQ(-1, final_intel.ssl_start_ms); + EXPECT_EQ(-1, final_intel.ssl_end_ms); + + ASSERT_NE(-1, final_intel.stream_start_ms); + ASSERT_NE(-1, final_intel.connect_start_ms); + ASSERT_NE(-1, final_intel.connect_end_ms); + ASSERT_NE(-1, final_intel.sending_start_ms); + ASSERT_NE(-1, final_intel.sending_end_ms); + ASSERT_NE(-1, final_intel.response_start_ms); + ASSERT_NE(-1, final_intel.stream_end_ms); + + ASSERT_LE(final_intel.stream_start_ms, final_intel.connect_start_ms); + ASSERT_LE(final_intel.connect_start_ms, final_intel.connect_end_ms); + ASSERT_LE(final_intel.connect_end_ms, final_intel.sending_start_ms); + ASSERT_LE(final_intel.sending_start_ms, final_intel.sending_end_ms); + ASSERT_LE(final_intel.response_start_ms, final_intel.stream_end_ms); +} + // Use the Envoy mobile default config as much as possible in this test. // There are some config modifiers below which do result in deltas. std::string defaultConfig() { @@ -24,88 +47,95 @@ std::string defaultConfig() { } // namespace -Http::ResponseHeaderMapPtr toResponseHeaders(envoy_headers headers) { - std::unique_ptr transformed_headers = - Http::ResponseHeaderMapImpl::create(); - transformed_headers->setFormatter( - std::make_unique< - Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>( - false, envoy::extensions::http::header_formatters::preserve_case::v3:: - PreserveCaseFormatterConfig::DEFAULT)); - Http::Utility::toEnvoyHeaders(*transformed_headers, headers); - return transformed_headers; -} - BaseClientIntegrationTest::BaseClientIntegrationTest(Network::Address::IpVersion ip_version) : BaseIntegrationTest(ip_version, defaultConfig()) { + skip_tag_extraction_rule_check_ = true; + full_dispatcher_ = api_->allocateDispatcher("fake_envoy_mobile"); use_lds_ = false; autonomous_upstream_ = true; defer_listener_finalization_ = true; - - HttpTestUtility::addDefaultHeaders(default_request_headers_); - - config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - // The default stats config has overenthusiastic filters. - bootstrap.clear_stats_config(); - }); } void BaseClientIntegrationTest::initialize() { BaseIntegrationTest::initialize(); + stream_prototype_ = engine_->streamClient()->newStreamPrototype(); - bridge_callbacks_.context = &cc_; - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool, envoy_stream_intel intel, - void* context) -> void* { - Http::ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc_ = static_cast(context); - cc_->on_headers_calls++; - cc_->status = response_headers->Status()->value().getStringView(); - cc_->on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; - return nullptr; - }; - bridge_callbacks_.on_data = [](envoy_data c_data, bool, envoy_stream_intel, - void* context) -> void* { - callbacks_called* cc_ = static_cast(context); - cc_->on_data_calls++; + stream_prototype_->setOnHeaders( + [this](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel intel) { + cc_.on_headers_calls++; + cc_.status = absl::StrCat(headers->httpStatus()); + cc_.on_header_consumed_bytes_from_response = intel.consumed_bytes_from_response; + }); + stream_prototype_->setOnData([this](envoy_data c_data, bool) { + cc_.on_data_calls++; release_envoy_data(c_data); - return nullptr; - }; - bridge_callbacks_.on_complete = [](envoy_stream_intel, envoy_final_stream_intel final_intel, - void* context) -> void* { - callbacks_called* cc_ = static_cast(context); - cc_->final_intel = final_intel; - cc_->on_complete_received_byte_count = final_intel.received_byte_count; - cc_->on_complete_calls++; - cc_->terminal_callback->setReady(); - return nullptr; - }; - bridge_callbacks_.on_error = [](envoy_error error, envoy_stream_intel, envoy_final_stream_intel, - void* context) -> void* { - release_envoy_error(error); - callbacks_called* cc_ = static_cast(context); - cc_->on_error_calls++; - cc_->terminal_callback->setReady(); - return nullptr; - }; - bridge_callbacks_.on_cancel = [](envoy_stream_intel, envoy_final_stream_intel final_intel, - void* context) -> void* { + }); + stream_prototype_->setOnComplete( + [this](envoy_stream_intel, envoy_final_stream_intel final_intel) { + validateStreamIntel(final_intel, expect_dns_); + cc_.on_complete_received_byte_count = final_intel.received_byte_count; + cc_.on_complete_calls++; + cc_.terminal_callback->setReady(); + }); + stream_prototype_->setOnError( + [this](Platform::EnvoyErrorSharedPtr, envoy_stream_intel, envoy_final_stream_intel) { + cc_.on_error_calls++; + cc_.terminal_callback->setReady(); + }); + stream_prototype_->setOnCancel([this](envoy_stream_intel, envoy_final_stream_intel final_intel) { EXPECT_NE(-1, final_intel.stream_start_ms); - callbacks_called* cc_ = static_cast(context); - cc_->on_cancel_calls++; - cc_->terminal_callback->setReady(); - return nullptr; - }; - - ConditionalInitializer server_started; - test_server_->server().dispatcher().post([this, &server_started]() -> void { - http_client_ = std::make_unique( - test_server_->server().listenerManager().apiListener()->get().http()->get(), *dispatcher_, - test_server_->statStore(), test_server_->server().api().randomGenerator()); - dispatcher_->drain(test_server_->server().dispatcher()); - server_started.setReady(); + cc_.on_cancel_calls++; + cc_.terminal_callback->setReady(); }); - server_started.waitReady(); - default_request_headers_.setHost(fake_upstreams_[0]->localAddress()->asStringView()); + + stream_ = (*stream_prototype_).start(explicit_flow_control_); + std::string host(fake_upstreams_[0]->localAddress()->asStringView()); + Platform::RequestHeadersBuilder builder(Platform::RequestMethod::GET, scheme_, host, "/"); + for (auto& entry : custom_headers_) { + auto values = {entry.second}; + builder.set(entry.first, values); + } + if (upstreamProtocol() == Http::CodecType::HTTP2) { + builder.addUpstreamHttpProtocol(Platform::UpstreamHttpProtocol::HTTP2); + } + default_request_headers_ = std::make_shared(builder.build()); +} + +void BaseClientIntegrationTest::threadRoutine(absl::Notification& engine_running) { + setOnEngineRunning([&]() { engine_running.Notify(); }); + engine_ = build(); + full_dispatcher_->run(Event::Dispatcher::RunType::Block); +} + +void BaseClientIntegrationTest::TearDown() { + test_server_.reset(); + fake_upstreams_.clear(); + engine_->terminate(); + engine_.reset(); + full_dispatcher_->exit(); + envoy_thread_->join(); +} + +void BaseClientIntegrationTest::createEnvoy() { + std::vector ports; + for (auto& upstream : fake_upstreams_) { + if (upstream->localAddress()->ip()) { + ports.push_back(upstream->localAddress()->ip()->port()); + } + } + + finalizeConfigWithPorts(config_helper_, ports, use_lds_); + + if (override_builder_config_) { + setOverrideConfigForTests(MessageUtil::getYamlStringFromMessage(config_helper_.bootstrap())); + } else { + ENVOY_LOG_MISC(warn, "Using builder config and ignoring config modifiers"); + } + + absl::Notification engine_running; + envoy_thread_ = api_->threadFactory().createThread( + [this, &engine_running]() -> void { threadRoutine(engine_running); }); + engine_running.WaitForNotification(); } void BaseClientIntegrationTest::cleanup() { diff --git a/test/common/integration/base_client_integration_test.h b/test/common/integration/base_client_integration_test.h index 6c6afa060e..0e1b98124f 100644 --- a/test/common/integration/base_client_integration_test.h +++ b/test/common/integration/base_client_integration_test.h @@ -2,6 +2,9 @@ #include "test/integration/integration.h" +#include "library/cc/engine_builder.h" +#include "library/cc/stream.h" +#include "library/cc/stream_prototype.h" #include "library/common/http/client.h" #include "library/common/types/c_types.h" @@ -29,7 +32,7 @@ Http::ResponseHeaderMapPtr toResponseHeaders(envoy_headers headers); // // TODO(junr03): move this to derive from the ApiListenerIntegrationTest after moving that class // into a test lib. -class BaseClientIntegrationTest : public BaseIntegrationTest { +class BaseClientIntegrationTest : public BaseIntegrationTest, public Platform::EngineBuilder { public: BaseClientIntegrationTest(Network::Address::IpVersion ip_version); virtual ~BaseClientIntegrationTest() = default; @@ -37,14 +40,27 @@ class BaseClientIntegrationTest : public BaseIntegrationTest { protected: virtual void initialize() override; virtual void cleanup(); + void createEnvoy() override; + void threadRoutine(absl::Notification& engine_running); + // Must be called manually by subclasses in their TearDown(); + void TearDown(); Event::ProvisionalDispatcherPtr dispatcher_ = std::make_unique(); Http::ClientPtr http_client_{}; envoy_http_callbacks bridge_callbacks_; ConditionalInitializer terminal_callback_; callbacks_called cc_{0, 0, 0, 0, 0, 0, 0, "", &terminal_callback_, {}}; - Http::TestRequestHeaderMapImpl default_request_headers_; - envoy_stream_t stream_{1}; + std::shared_ptr default_request_headers_; + absl::flat_hash_map custom_headers_; + Event::DispatcherPtr full_dispatcher_; + Platform::StreamPrototypeSharedPtr stream_prototype_; + Platform::StreamSharedPtr stream_; + Platform::EngineSharedPtr engine_; + Thread::ThreadPtr envoy_thread_; + std::string scheme_ = "http"; + bool explicit_flow_control_ = false; + bool expect_dns_ = true; + bool override_builder_config_ = false; }; } // namespace Envoy diff --git a/test/common/integration/client_integration_test.cc b/test/common/integration/client_integration_test.cc index e64ab4079c..4a22f50472 100644 --- a/test/common/integration/client_integration_test.cc +++ b/test/common/integration/client_integration_test.cc @@ -7,34 +7,15 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "library/common/data/utility.h" +#include "library/common/engine.h" #include "library/common/http/header_utility.h" +#include "library/common/types/c_types.h" + +using testing::ReturnRef; namespace Envoy { namespace { -void validateStreamIntel(const envoy_final_stream_intel& final_intel) { - EXPECT_NE(-1, final_intel.dns_start_ms); - EXPECT_NE(-1, final_intel.dns_end_ms); - - // This test doesn't do TLS. - EXPECT_EQ(-1, final_intel.ssl_start_ms); - EXPECT_EQ(-1, final_intel.ssl_end_ms); - - ASSERT_NE(-1, final_intel.stream_start_ms); - ASSERT_NE(-1, final_intel.connect_start_ms); - ASSERT_NE(-1, final_intel.connect_end_ms); - ASSERT_NE(-1, final_intel.sending_start_ms); - ASSERT_NE(-1, final_intel.sending_end_ms); - ASSERT_NE(-1, final_intel.response_start_ms); - ASSERT_NE(-1, final_intel.stream_end_ms); - - ASSERT_LE(final_intel.stream_start_ms, final_intel.connect_start_ms); - ASSERT_LE(final_intel.connect_start_ms, final_intel.connect_end_ms); - ASSERT_LE(final_intel.connect_end_ms, final_intel.sending_start_ms); - ASSERT_LE(final_intel.sending_start_ms, final_intel.sending_end_ms); - ASSERT_LE(final_intel.response_start_ms, final_intel.stream_end_ms); -} - class ClientIntegrationTest : public BaseClientIntegrationTest, public testing::TestWithParam { public: @@ -49,6 +30,7 @@ class ClientIntegrationTest : public BaseClientIntegrationTest, void TearDown() override { ASSERT_EQ(cc_.on_complete_calls + cc_.on_cancel_calls + cc_.on_error_calls, 1); cleanup(); + BaseClientIntegrationTest::TearDown(); } }; @@ -57,55 +39,39 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, ClientIntegrationTest, TestUtility::ipTestParamsToString); TEST_P(ClientIntegrationTest, Basic) { + Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body"); + custom_headers_.emplace(AutonomousStream::EXPECT_REQUEST_SIZE_BYTES, + std::to_string(request_data.length())); initialize(); - bridge_callbacks_.on_data = [](envoy_data c_data, bool end_stream, envoy_stream_intel, - void* context) -> void* { + stream_prototype_->setOnData([this](envoy_data c_data, bool end_stream) { if (end_stream) { EXPECT_EQ(Data::Utility::copyToString(c_data), ""); } else { EXPECT_EQ(c_data.length, 10); } - callbacks_called* cc_ = static_cast(context); - cc_->on_data_calls++; + cc_.on_data_calls++; release_envoy_data(c_data); - return nullptr; - }; - - // Build a set of request headers. - Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body"); - default_request_headers_.addCopy(AutonomousStream::EXPECT_REQUEST_SIZE_BYTES, - std::to_string(request_data.length())); + }); - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); + stream_->sendHeaders(default_request_headers_, false); - // Build body data envoy_data c_data = Data::Utility::toBridgeData(request_data); + stream_->sendData(c_data); + + Platform::RequestTrailersBuilder builder; + std::shared_ptr trailers = + std::make_shared(builder.build()); + stream_->close(trailers); - // Build a set of request trailers. - // TODO: update the autonomous upstream to assert on trailers, or to send trailers back. - Http::TestRequestTrailerMapImpl trailers; - envoy_headers c_trailers = Http::Utility::toBridgeHeaders(trailers); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, false); - http_client_->sendData(stream_, c_data, false); - http_client_->sendTrailers(stream_, c_trailers); - }); terminal_callback_.waitReady(); - validateStreamIntel(cc_.final_intel); ASSERT_EQ(cc_.on_headers_calls, 1); ASSERT_EQ(cc_.status, "200"); ASSERT_EQ(cc_.on_data_calls, 2); ASSERT_EQ(cc_.on_complete_calls, 1); ASSERT_EQ(cc_.on_header_consumed_bytes_from_response, 27); ASSERT_EQ(cc_.on_complete_received_byte_count, 67); - - // stream_success gets charged for 2xx status codes. - test_server_->waitForCounterEq("http.client.stream_success", 1); } TEST_P(ClientIntegrationTest, BasicNon2xx) { @@ -116,69 +82,41 @@ TEST_P(ClientIntegrationTest, BasicNon2xx) { ->setResponseHeaders(std::make_unique( Http::TestResponseHeaderMapImpl({{":status", "503"}, {"content-length", "0"}}))); - // Build a set of request headers. - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, true); - }); + stream_->sendHeaders(default_request_headers_, true); terminal_callback_.waitReady(); - validateStreamIntel(cc_.final_intel); ASSERT_EQ(cc_.on_error_calls, 0); ASSERT_EQ(cc_.status, "503"); ASSERT_EQ(cc_.on_headers_calls, 1); ASSERT_EQ(cc_.on_complete_calls, 1); - - // stream_failure gets charged for all non-2xx status codes. - test_server_->waitForCounterEq("http.client.stream_failure", 1); } TEST_P(ClientIntegrationTest, BasicReset) { + custom_headers_.emplace(AutonomousStream::RESET_AFTER_REQUEST, "yes"); initialize(); - // Cause an upstream reset after request is complete. - default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_REQUEST, "yes"); - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, true); - }); + stream_->sendHeaders(default_request_headers_, true); terminal_callback_.waitReady(); ASSERT_EQ(cc_.on_error_calls, 1); ASSERT_EQ(cc_.on_headers_calls, 0); - // Reset causes a charge to stream_failure. - test_server_->waitForCounterEq("http.client.stream_failure", 1); } TEST_P(ClientIntegrationTest, BasicCancel) { autonomous_upstream_ = false; initialize(); + ConditionalInitializer headers_callback; - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool, envoy_stream_intel, - void* context) -> void* { - Http::ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc_ = static_cast(context); - cc_->on_headers_calls++; - cc_->status = response_headers->Status()->value().getStringView(); - // Lie and say the request is complete, so the test has something to wait - // on. - cc_->terminal_callback->setReady(); - return nullptr; - }; - - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, true); - }); + stream_prototype_->setOnHeaders( + [this, &headers_callback](Platform::ResponseHeadersSharedPtr headers, bool, + envoy_stream_intel) { + cc_.status = absl::StrCat(headers->httpStatus()); + cc_.on_headers_calls++; + headers_callback.setReady(); + return nullptr; + }); + + stream_->sendHeaders(default_request_headers_, true); Envoy::FakeRawConnectionPtr upstream_connection; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(upstream_connection)); @@ -190,16 +128,15 @@ TEST_P(ClientIntegrationTest, BasicCancel) { // Send an incomplete response. auto response = "HTTP/1.1 200 OK\r\nContent-Length: 15\r\n\r\n"; ASSERT_TRUE(upstream_connection->write(response)); - // For this test only, the terminal callback is called when headers arrive. - terminal_callback_.waitReady(); + headers_callback.waitReady(); ASSERT_EQ(cc_.on_headers_calls, 1); ASSERT_EQ(cc_.status, "200"); ASSERT_EQ(cc_.on_data_calls, 0); ASSERT_EQ(cc_.on_complete_calls, 0); // Now cancel, and make sure the cancel is received. - dispatcher_->post([&]() -> void { http_client_->cancelStream(stream_); }); + stream_->cancel(); terminal_callback_.waitReady(); ASSERT_EQ(cc_.on_headers_calls, 1); @@ -211,27 +148,20 @@ TEST_P(ClientIntegrationTest, BasicCancel) { TEST_P(ClientIntegrationTest, CancelWithPartialStream) { autonomous_upstream_ = false; + explicit_flow_control_ = true; initialize(); + ConditionalInitializer headers_callback; - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool, envoy_stream_intel, - void* context) -> void* { - Http::ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc_ = static_cast(context); - cc_->on_headers_calls++; - cc_->status = response_headers->Status()->value().getStringView(); - // Lie and say the request is complete, so the test has something to wait - // on. - cc_->terminal_callback->setReady(); - return nullptr; - }; - - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream with explicit flow control. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, true); - http_client_->sendHeaders(stream_, c_headers, true); - }); + stream_prototype_->setOnHeaders( + [this, &headers_callback](Platform::ResponseHeadersSharedPtr headers, bool, + envoy_stream_intel) { + cc_.status = absl::StrCat(headers->httpStatus()); + cc_.on_headers_calls++; + headers_callback.setReady(); + return nullptr; + }); + + stream_->sendHeaders(default_request_headers_, true); Envoy::FakeRawConnectionPtr upstream_connection; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(upstream_connection)); @@ -243,8 +173,7 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { // Send a complete response with body. auto response = "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nasd"; ASSERT_TRUE(upstream_connection->write(response)); - // For this test only, the terminal callback is called when headers arrive. - terminal_callback_.waitReady(); + headers_callback.waitReady(); ASSERT_EQ(cc_.on_headers_calls, 1); ASSERT_EQ(cc_.status, "200"); @@ -253,7 +182,7 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { // Due to explicit flow control, the upstream stream is complete, but the // callbacks will not be called for data and completion. Cancel the stream // and make sure the cancel is received. - dispatcher_->post([&]() -> void { http_client_->cancelStream(stream_); }); + stream_->cancel(); terminal_callback_.waitReady(); ASSERT_EQ(cc_.on_headers_calls, 1); @@ -269,51 +198,20 @@ TEST_P(ClientIntegrationTest, CancelWithPartialStream) { // Test header key case sensitivity. TEST_P(ClientIntegrationTest, CaseSensitive) { - Envoy::Extensions::Http::HeaderFormatters::PreserveCase:: - forceRegisterPreserveCaseFormatterFactoryConfig(); - config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - ConfigHelper::HttpProtocolOptions protocol_options; - auto typed_extension_config = protocol_options.mutable_explicit_http_config() - ->mutable_http_protocol_options() - ->mutable_header_key_format() - ->mutable_stateful_formatter(); - typed_extension_config->set_name("preserve_case"); - typed_extension_config->mutable_typed_config()->set_type_url( - "type.googleapis.com/" - "envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig"); - ConfigHelper::setProtocolOptions(*bootstrap.mutable_static_resources()->mutable_clusters(0), - protocol_options); - }); - + custom_headers_.emplace("FoO", "bar"); autonomous_upstream_ = false; initialize(); - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool, envoy_stream_intel, - void* context) -> void* { - Http::ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc_ = static_cast(context); - cc_->on_headers_calls++; - cc_->status = response_headers->Status()->value().getStringView(); - EXPECT_EQ("My-ResponsE-Header", - response_headers->formatter().value().get().format("my-response-header")); - return nullptr; - }; - - // Build a set of request headers. - default_request_headers_.header_map_->setFormatter( - std::make_unique< - Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>( - false, envoy::extensions::http::header_formatters::preserve_case::v3:: - PreserveCaseFormatterConfig::DEFAULT)); - default_request_headers_.addCopy("FoO", "bar"); - default_request_headers_.header_map_->formatter().value().get().processKey("FoO"); - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, true); - }); + stream_prototype_->setOnHeaders( + [this](Platform::ResponseHeadersSharedPtr headers, bool, envoy_stream_intel) { + cc_.status = absl::StrCat(headers->httpStatus()); + cc_.on_headers_calls++; + EXPECT_TRUE(headers->contains("My-ResponsE-Header")); + EXPECT_TRUE((*headers)["My-ResponsE-Header"][0] == "foo"); + return nullptr; + }); + + stream_->sendHeaders(default_request_headers_, true); Envoy::FakeRawConnectionPtr upstream_connection; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(upstream_connection)); @@ -324,53 +222,25 @@ TEST_P(ClientIntegrationTest, CaseSensitive) { &upstream_request)); EXPECT_TRUE(absl::StrContains(upstream_request, "FoO: bar")) << upstream_request; - // Verify that the downstream response has preserved cased headers. + // Send mixed case headers, and verify via setOnHeaders they are received correctly. auto response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nMy-ResponsE-Header: foo\r\n\r\n"; ASSERT_TRUE(upstream_connection->write(response)); terminal_callback_.waitReady(); - validateStreamIntel(cc_.final_intel); ASSERT_EQ(cc_.on_headers_calls, 1); ASSERT_EQ(cc_.status, "200"); ASSERT_EQ(cc_.on_data_calls, 0); ASSERT_EQ(cc_.on_complete_calls, 1); - - // stream_success gets charged for 2xx status codes. - test_server_->waitForCounterEq("http.client.stream_success", 1); } TEST_P(ClientIntegrationTest, TimeoutOnRequestPath) { - config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); - auto* em_hcm = listener->mutable_api_listener()->mutable_api_listener(); - auto hcm = - MessageUtil::anyConvert(*em_hcm); - hcm.mutable_config()->mutable_stream_idle_timeout()->set_seconds(1); - em_hcm->PackFrom(hcm); - }); + setStreamIdleTimeoutSeconds(1); autonomous_upstream_ = false; initialize(); - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool, envoy_stream_intel, - void* context) -> void* { - Http::ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc_ = static_cast(context); - cc_->on_headers_calls++; - cc_->status = response_headers->Status()->value().getStringView(); - return nullptr; - }; - - // Build a set of request headers. - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, false); - }); + stream_->sendHeaders(default_request_headers_, false); Envoy::FakeRawConnectionPtr upstream_connection; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(upstream_connection)); @@ -387,36 +257,11 @@ TEST_P(ClientIntegrationTest, TimeoutOnRequestPath) { } TEST_P(ClientIntegrationTest, TimeoutOnResponsePath) { - config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); - auto* em_hcm = listener->mutable_api_listener()->mutable_api_listener(); - auto hcm = - MessageUtil::anyConvert(*em_hcm); - hcm.mutable_config()->mutable_stream_idle_timeout()->set_seconds(1); - em_hcm->PackFrom(hcm); - }); - + setStreamIdleTimeoutSeconds(1); autonomous_upstream_ = false; initialize(); - bridge_callbacks_.on_headers = [](envoy_headers c_headers, bool, envoy_stream_intel, - void* context) -> void* { - Http::ResponseHeaderMapPtr response_headers = toResponseHeaders(c_headers); - callbacks_called* cc_ = static_cast(context); - cc_->on_headers_calls++; - cc_->status = response_headers->Status()->value().getStringView(); - return nullptr; - }; - - // Build a set of request headers. - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, true); - }); + stream_->sendHeaders(default_request_headers_, true); Envoy::FakeRawConnectionPtr upstream_connection; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(upstream_connection)); diff --git a/test/common/integration/rtds_integration_test.cc b/test/common/integration/rtds_integration_test.cc index 14394fd811..8321107374 100644 --- a/test/common/integration/rtds_integration_test.cc +++ b/test/common/integration/rtds_integration_test.cc @@ -23,29 +23,6 @@ namespace Envoy { namespace { -void validateStreamIntel(const envoy_final_stream_intel& final_intel) { - EXPECT_EQ(-1, final_intel.dns_start_ms); - EXPECT_EQ(-1, final_intel.dns_end_ms); - - // This test doesn't do TLS. - EXPECT_EQ(-1, final_intel.ssl_start_ms); - EXPECT_EQ(-1, final_intel.ssl_end_ms); - - ASSERT_NE(-1, final_intel.stream_start_ms); - ASSERT_NE(-1, final_intel.connect_start_ms); - ASSERT_NE(-1, final_intel.connect_end_ms); - ASSERT_NE(-1, final_intel.sending_start_ms); - ASSERT_NE(-1, final_intel.sending_end_ms); - ASSERT_NE(-1, final_intel.response_start_ms); - ASSERT_NE(-1, final_intel.stream_end_ms); - - ASSERT_LE(final_intel.stream_start_ms, final_intel.connect_start_ms); - ASSERT_LE(final_intel.connect_start_ms, final_intel.connect_end_ms); - ASSERT_LE(final_intel.connect_end_ms, final_intel.sending_start_ms); - ASSERT_LE(final_intel.sending_start_ms, final_intel.sending_end_ms); - ASSERT_LE(final_intel.response_start_ms, final_intel.stream_end_ms); -} - envoy::config::cluster::v3::Cluster createSingleEndpointClusterConfig(const std::string& cluster_name, const std::string& loopbackAddr) { @@ -109,7 +86,7 @@ envoy::config::bootstrap::v3::Admin adminConfig(const std::string& loopbackAddr) address: {} port_value: 0 )EOF", - Platform::null_device_path, loopbackAddr); + ::Platform::null_device_path, loopbackAddr); envoy::config::bootstrap::v3::Admin config; TestUtility::loadFromYaml(yaml, config); @@ -120,10 +97,11 @@ class RtdsIntegrationTest : public BaseClientIntegrationTest, public Grpc::DeltaSotwIntegrationParamTest { public: RtdsIntegrationTest() : BaseClientIntegrationTest(ipVersion()) { + override_builder_config_ = true; // The builder does not yet have RTDS support. + expect_dns_ = false; // TODO(alyssawilk) debug. create_xds_upstream_ = true; sotw_or_delta_ = sotwOrDelta(); - default_request_headers_.setScheme("https"); - default_request_headers_.addCopy("x-envoy-mobile-upstream-protocol", "http2"); + scheme_ = "https"; if (sotw_or_delta_ == Grpc::SotwOrDelta::UnifiedSotw || sotw_or_delta_ == Grpc::SotwOrDelta::UnifiedDelta) { @@ -160,6 +138,8 @@ class RtdsIntegrationTest : public BaseClientIntegrationTest, config_helper_.addConfigModifier([this](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { bootstrap.mutable_admin()->MergeFrom(adminConfig(loopbackAddr())); }); + admin_filename_ = TestEnvironment::temporaryPath("admin_address.txt"); + setAdminAddressPathForTests(admin_filename_); } void SetUp() override { @@ -167,14 +147,22 @@ class RtdsIntegrationTest : public BaseClientIntegrationTest, setUpstreamProtocol(Http::CodecType::HTTP2); } - void TearDown() override { cleanup(); } + void TearDown() override { + cleanup(); + BaseClientIntegrationTest::TearDown(); + } + + void createEnvoy() override { + BaseClientIntegrationTest::createEnvoy(); + std::string admin_str = TestEnvironment::readFileToStringForTest(admin_filename_); + auto addr = Network::Utility::parseInternetAddressAndPort(admin_str); + registerPort("admin", addr->ip()->port()); + } void initialize() override { BaseClientIntegrationTest::initialize(); // Register admin port. - registerTestServerPorts({}); - initial_load_success_ = test_server_->counter("runtime.load_success")->value(); - initial_keys_ = test_server_->gauge("runtime.num_keys")->value(); + // registerTestServerPorts({}); acceptXdsConnection(); } @@ -226,7 +214,7 @@ class RtdsIntegrationTest : public BaseClientIntegrationTest, } uint32_t initial_load_success_{}; - uint32_t initial_keys_{}; + std::string admin_filename_; }; INSTANTIATE_TEST_SUITE_P(IpVersionsClientTypeDelta, RtdsIntegrationTest, @@ -236,44 +224,10 @@ TEST_P(RtdsIntegrationTest, RtdsReload) { addRuntimeRtdsConfig(); initialize(); - bridge_callbacks_.on_data = [](envoy_data c_data, bool end_stream, envoy_stream_intel, - void* context) -> void* { - if (end_stream) { - EXPECT_EQ(Data::Utility::copyToString(c_data), ""); - } else { - EXPECT_EQ(c_data.length, 10); - } - callbacks_called* cc_ = static_cast(context); - cc_->on_data_calls++; - release_envoy_data(c_data); - return nullptr; - }; - - // Build a set of request headers. - Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body"); - default_request_headers_.addCopy(AutonomousStream::EXPECT_REQUEST_SIZE_BYTES, - std::to_string(request_data.length())); - - envoy_headers c_headers = Http::Utility::toBridgeHeaders(default_request_headers_); - - // Build body data - envoy_data c_data = Data::Utility::toBridgeData(request_data); - - // Build a set of request trailers. - // TODO: update the autonomous upstream to assert on trailers, or to send trailers back. - Http::TestRequestTrailerMapImpl trailers; - envoy_headers c_trailers = Http::Utility::toBridgeHeaders(trailers); - - // Create a stream. - dispatcher_->post([&]() -> void { - http_client_->startStream(stream_, bridge_callbacks_, false); - http_client_->sendHeaders(stream_, c_headers, false); - http_client_->sendData(stream_, c_data, false); - http_client_->sendTrailers(stream_, c_trailers); - }); + // Send a request on the data plane. + stream_->sendHeaders(default_request_headers_, true); terminal_callback_.waitReady(); - validateStreamIntel(cc_.final_intel); EXPECT_EQ(cc_.on_headers_calls, 1); EXPECT_EQ(cc_.status, "200"); EXPECT_EQ(cc_.on_data_calls, 2); @@ -282,8 +236,6 @@ TEST_P(RtdsIntegrationTest, RtdsReload) { EXPECT_EQ(cc_.on_error_calls, 0); EXPECT_EQ(cc_.on_header_consumed_bytes_from_response, 13); EXPECT_EQ(cc_.on_complete_received_byte_count, 41); - // stream_success gets charged for 2xx status codes. - test_server_->waitForCounterEq("http.client.stream_success", 1); // Check that the Runtime config is from the static layer. EXPECT_EQ("whatevs", getRuntimeKey("foo")); @@ -301,7 +253,6 @@ TEST_P(RtdsIntegrationTest, RtdsReload) { )EOF"); sendDiscoveryResponse( Config::TypeUrl::get().Runtime, {some_rtds_layer}, {some_rtds_layer}, {}, "1"); - test_server_->waitForCounterGe("runtime.load_success", initial_load_success_ + 1); // Verify that the Runtime config values are from the RTDS response. EXPECT_EQ("bar", getRuntimeKey("foo")); diff --git a/test/common/main_interface_test.cc b/test/common/main_interface_test.cc index c9c22c615d..03005dcd28 100644 --- a/test/common/main_interface_test.cc +++ b/test/common/main_interface_test.cc @@ -137,7 +137,7 @@ TEST(MainInterfaceTest, BasicStream) { } /*on_exit*/, &engine_cbs_context /*context*/}; envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, BUFFERED_TEST_CONFIG.c_str(), level.c_str()); + run_engine(engine_handle, BUFFERED_TEST_CONFIG.c_str(), level.c_str(), ""); ASSERT_TRUE( engine_cbs_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); @@ -203,7 +203,7 @@ TEST(MainInterfaceTest, SendMetadata) { // There is nothing functional about the config used to run the engine, as the created stream is // only used for send_metadata. envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE( engine_cbs_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); @@ -243,7 +243,7 @@ TEST(MainInterfaceTest, ResetStream) { // There is nothing functional about the config used to run the engine, as the created stream is // immediately reset. envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE( engine_cbs_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); @@ -314,7 +314,7 @@ TEST(MainInterfaceTest, RegisterPlatformApi) { // Using the minimal envoy mobile config that allows for running the engine. envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE( engine_cbs_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); @@ -342,7 +342,7 @@ TEST(MainInterfaceTest, InitEngineReturns1) { } /*on_exit*/, &test_context /*context*/}; ASSERT_EQ(1, init_engine(engine_cbs, {}, {})); - run_engine(1, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(1, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); terminate_engine(1); ASSERT_TRUE(test_context.on_exit.WaitForNotificationWithTimeout(absl::Seconds(3))); @@ -366,7 +366,7 @@ TEST(EngineTest, RecordCounter) { &test_context /*context*/}; EXPECT_EQ(ENVOY_FAILURE, record_counter_inc(1, "counter", envoy_stats_notags, 1)); envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); EXPECT_EQ(ENVOY_SUCCESS, record_counter_inc(engine_handle, "counter", envoy_stats_notags, 1)); @@ -388,7 +388,7 @@ TEST(EngineTest, SetGauge) { &test_context /*context*/}; EXPECT_EQ(ENVOY_FAILURE, record_gauge_set(1, "gauge", envoy_stats_notags, 1)); envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); @@ -413,7 +413,7 @@ TEST(EngineTest, AddToGauge) { EXPECT_EQ(ENVOY_FAILURE, record_gauge_add(1, "gauge", envoy_stats_notags, 30)); envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); EXPECT_EQ(ENVOY_SUCCESS, record_gauge_add(engine_handle, "gauge", envoy_stats_notags, 30)); @@ -437,7 +437,7 @@ TEST(EngineTest, SubFromGauge) { EXPECT_EQ(ENVOY_FAILURE, record_gauge_sub(1, "gauge", envoy_stats_notags, 30)); envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); record_gauge_add(engine_handle, "gauge", envoy_stats_notags, 30); @@ -464,7 +464,7 @@ TEST(EngineTest, RecordHistogramValue) { record_histogram_value(1, "histogram", envoy_stats_notags, 99, MILLISECONDS)); envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); record_histogram_value(engine_handle, "histogram", envoy_stats_notags, 99, MILLISECONDS); @@ -506,7 +506,7 @@ TEST(EngineTest, Logger) { &test_context}; envoy_engine_t engine_handle = init_engine(engine_cbs, logger, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); ASSERT_TRUE(test_context.on_log.WaitForNotificationWithTimeout(absl::Seconds(3))); @@ -531,7 +531,7 @@ TEST(EngineTest, EventTrackerRegistersDefaultAPI) { &test_context /*context*/}; envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); // A default event tracker is registered in external API registry. const auto registered_event_tracker = @@ -575,7 +575,7 @@ TEST(EngineTest, EventTrackerRegistersAPI) { &test_context /*context*/}; envoy_engine_t engine_handle = init_engine(engine_cbs, {}, event_tracker); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); const auto registered_event_tracker = @@ -618,7 +618,7 @@ TEST(EngineTest, EventTrackerRegistersAssertionFailureRecordAction) { &test_context /*context*/}; envoy_engine_t engine_handle = init_engine(engine_cbs, {}, event_tracker); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); // Simulate a failed assertion by invoking a debug assertion failure @@ -658,7 +658,7 @@ TEST(EngineTest, EventTrackerRegistersEnvoyBugRecordAction) { &test_context /*context*/}; envoy_engine_t engine_handle = init_engine(engine_cbs, {}, event_tracker); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); // Simulate an envoy bug by invoking an Envoy bug failure @@ -685,7 +685,7 @@ TEST(MainInterfaceTest, ResetConnectivityState) { } /*on_exit*/, &test_context /*context*/}; envoy_engine_t engine_handle = init_engine(engine_cbs, {}, {}); - run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str()); + run_engine(engine_handle, MINIMAL_TEST_CONFIG.c_str(), LEVEL_DEBUG.c_str(), ""); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(3))); ASSERT_EQ(ENVOY_SUCCESS, reset_connectivity_state(engine_handle)); diff --git a/test/performance/test_binary_size.cc b/test/performance/test_binary_size.cc index d49fa644dc..1e12a15799 100644 --- a/test/performance/test_binary_size.cc +++ b/test/performance/test_binary_size.cc @@ -5,4 +5,4 @@ // This binary is used to perform stripped down binary size investigations of the Envoy codebase. // Please refer to the development docs for more information: // https://envoy-mobile.github.io/docs/envoy-mobile/latest/development/performance/binary_size.html -int main() { return run_engine(0, nullptr, nullptr); } +int main() { return run_engine(0, nullptr, nullptr, nullptr); }