Skip to content

Commit

Permalink
Mobile: Replace direct response APIs with test server in Swift (#27429)
Browse files Browse the repository at this point in the history
This is a followup to #25582

We migrate the swift tests to use a mock test server. And then delete the direct response engine builder functionality entirely.

Signed-off-by: caschoener <schoener@google.com>
  • Loading branch information
caschoener committed May 23, 2023
1 parent 7c4bbe1 commit 67e4108
Show file tree
Hide file tree
Showing 27 changed files with 154 additions and 707 deletions.
3 changes: 2 additions & 1 deletion mobile/bazel/apple.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
load("@envoy//bazel:envoy_build_system.bzl", "envoy_mobile_defines")
load("//bazel:config.bzl", "MINIMUM_IOS_VERSION")

def envoy_objc_library(name, hdrs = [], visibility = [], data = [], deps = [], module_name = None, sdk_frameworks = [], srcs = []):
def envoy_objc_library(name, hdrs = [], visibility = [], data = [], deps = [], module_name = None, sdk_frameworks = [], srcs = [], testonly = False):
native.objc_library(
name = name,
srcs = srcs,
Expand All @@ -15,6 +15,7 @@ def envoy_objc_library(name, hdrs = [], visibility = [], data = [], deps = [], m
visibility = visibility,
data = data,
deps = deps,
testonly = testonly,
)

# Macros providing a way to easily/consistently define Swift/ObjC unit test targets.
Expand Down
131 changes: 0 additions & 131 deletions mobile/library/cc/engine_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,6 @@ EngineBuilder& EngineBuilder::setRuntimeGuard(std::string guard, bool value) {
return *this;
}

EngineBuilder&
EngineBuilder::addDirectResponse(DirectResponseTesting::DirectResponse direct_response) {
direct_responses_.push_back(direct_response);
return *this;
}

EngineBuilder& EngineBuilder::setOverrideConfigForTests(std::string config) {
config_override_for_tests_ = std::move(config);
return *this;
Expand Down Expand Up @@ -319,46 +313,6 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate
remote_service->set_name("remote_service");
remote_service->add_domains("127.0.0.1");

for (auto& direct_response_in : direct_responses_) {
auto* direct_response_route = remote_service->add_routes();
auto* direct_response = direct_response_route->mutable_direct_response();
direct_response->set_status(direct_response_in.status);
direct_response->mutable_body()->set_inline_string(direct_response_in.body);
auto* direct_response_route_match = direct_response_route->mutable_match();
auto matcher = direct_response_in.matcher;
if (!matcher.fullPath.empty()) {
direct_response_route_match->set_path(matcher.fullPath);
} else if (!matcher.pathPrefix.empty()) {
direct_response_route_match->set_prefix(matcher.pathPrefix);
}

for (auto& header : matcher.headers) {
auto* direct_response_headers = direct_response_route_match->add_headers();
direct_response_headers->set_name(header.name);
switch (header.mode) {
case DirectResponseTesting::MatchMode::Contains:
direct_response_headers->set_contains_match(header.value);
break;
case DirectResponseTesting::MatchMode::Exact:
direct_response_headers->set_exact_match(header.value);
break;
case DirectResponseTesting::MatchMode::Prefix:
direct_response_headers->set_prefix_match(header.value);
break;
case DirectResponseTesting::MatchMode::Suffix:
direct_response_headers->set_suffix_match(header.value);
break;
}
}

for (auto& header_in : direct_response_in.headers) {
auto* resp_header = direct_response_route->add_response_headers_to_add();
auto* header = resp_header->mutable_header();
header->set_key(header_in.first);
header->set_value(header_in.second);
}
}

auto* route = remote_service->add_routes();
route->mutable_match()->set_prefix("/");
route->mutable_direct_response()->set_status(404);
Expand All @@ -370,38 +324,6 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate
api_service->set_include_attempt_count_in_response(true);
api_service->add_domains("*");

for (auto& direct_response_in : direct_responses_) {
auto* this_route = api_service->add_routes();
auto* mutable_route = this_route->mutable_route();
mutable_route->set_cluster("fake_remote");
auto* direct_response_route_match = this_route->mutable_match();
auto matcher = direct_response_in.matcher;
if (!matcher.fullPath.empty()) {
direct_response_route_match->set_path(matcher.fullPath);
} else if (!matcher.pathPrefix.empty()) {
direct_response_route_match->set_prefix(matcher.pathPrefix);
}

for (auto& header : matcher.headers) {
auto* direct_response_headers = direct_response_route_match->add_headers();
direct_response_headers->set_name(header.name);
switch (header.mode) {
case DirectResponseTesting::MatchMode::Contains:
direct_response_headers->set_contains_match(header.value);
break;
case DirectResponseTesting::MatchMode::Exact:
direct_response_headers->set_exact_match(header.value);
break;
case DirectResponseTesting::MatchMode::Prefix:
direct_response_headers->set_prefix_match(header.value);
break;
case DirectResponseTesting::MatchMode::Suffix:
direct_response_headers->set_suffix_match(header.value);
break;
}
}
}

route = api_service->add_routes();
route->mutable_match()->set_prefix("/");
route->add_request_headers_to_remove("x-forwarded-proto");
Expand Down Expand Up @@ -540,14 +462,6 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate
tag_filter->mutable_typed_config()->PackFrom(tag_config);
}

if (!direct_responses_.empty()) {
auto* cache_reset_filter = hcm->add_http_filters();
cache_reset_filter->set_name("envoy.filters.http.route_cache_reset");
cache_reset_filter->mutable_typed_config()->set_type_url(
"type.googleapis.com/"
"envoymobile.extensions.filters.http.route_cache_reset.RouteCacheReset");
}

// Set up the always-present filters
envoymobile::extensions::filters::http::network_configuration::NetworkConfiguration
network_config;
Expand Down Expand Up @@ -617,35 +531,6 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate

auto* static_resources = bootstrap->mutable_static_resources();

if (!direct_responses_.empty()) {
auto* fake_remote_listener = static_resources->add_listeners();
fake_remote_listener->set_name("fake_remote_listener");
auto* base_address = fake_remote_listener->mutable_address();
base_address->mutable_socket_address()->set_address("127.0.0.1");
base_address->mutable_socket_address()->set_port_value(10101);
auto* filter = fake_remote_listener->add_filter_chains()->add_filters();
envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager
fake_remote_listener_config;
filter->set_name("envoy.filters.network.http_connection_manager");
fake_remote_listener_config.set_stat_prefix("remote_hcm");
auto* route_config = fake_remote_listener_config.mutable_route_config();
route_config->set_name("remote_route");
auto* virtual_host = route_config->add_virtual_hosts();
virtual_host->add_domains("*");
virtual_host->set_name("remote_service");
auto* route = virtual_host->add_routes();
route->mutable_match()->set_prefix("/");
route->mutable_direct_response()->set_status(404);
route->mutable_direct_response()->mutable_body()->set_inline_string("not found");
route->add_request_headers_to_remove("x-forwarded-proto");
route->add_request_headers_to_remove("x-envoy-mobile-cluster");
auto* router_filter = fake_remote_listener_config.add_http_filters();
envoy::extensions::filters::http::router::v3::Router router_config;
router_filter->set_name("envoy.router");
router_filter->mutable_typed_config()->PackFrom(router_config);
filter->mutable_typed_config()->PackFrom(fake_remote_listener_config);
}

// Finally create the base listener, and point it at the HCM.
auto* base_listener = static_resources->add_listeners();
base_listener->set_name("base_api_listener");
Expand Down Expand Up @@ -696,22 +581,6 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate
base_tls_socket.set_name("envoy.transport_sockets.http_11_proxy");
base_tls_socket.mutable_typed_config()->PackFrom(ssl_proxy_socket);

if (!direct_responses_.empty()) {
// fake remote cluster
auto* fake_remote_cluster = static_resources->add_clusters();
fake_remote_cluster->set_name("fake_remote");
fake_remote_cluster->set_type(envoy::config::cluster::v3::Cluster::LOGICAL_DNS);
fake_remote_cluster->mutable_connect_timeout()->set_seconds(30);
fake_remote_cluster->mutable_load_assignment()->set_cluster_name("fake_remote");
auto* address = fake_remote_cluster->mutable_load_assignment()
->add_endpoints()
->add_lb_endpoints()
->mutable_endpoint()
->mutable_address();
address->mutable_socket_address()->set_address("127.0.0.1");
address->mutable_socket_address()->set_port_value(10101);
}

envoy::extensions::upstreams::http::v3::HttpProtocolOptions h2_protocol_options;
h2_protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options();
if (!stats_domain_.empty()) {
Expand Down
5 changes: 0 additions & 5 deletions mobile/library/cc/engine_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ class EngineBuilder {

EngineBuilder& setRuntimeGuard(std::string guard, bool value);

// Add a direct response. For testing purposes only.
// TODO(jpsim): Move this out of the main engine builder API
EngineBuilder& addDirectResponse(DirectResponseTesting::DirectResponse direct_response);

// These functions don't affect the Bootstrap configuration but instead perform registrations.
EngineBuilder& addKeyValueStore(std::string name, KeyValueStoreSharedPtr key_value_store);
EngineBuilder& addStringAccessor(std::string name, StringAccessorSharedPtr accessor);
Expand Down Expand Up @@ -189,7 +185,6 @@ class EngineBuilder {

std::vector<NativeFilterConfig> native_filter_chain_;
std::vector<std::string> dns_preresolve_hostnames_;
std::vector<DirectResponseTesting::DirectResponse> direct_responses_;

std::vector<std::pair<std::string, bool>> runtime_guards_;
absl::flat_hash_map<std::string, StringAccessorSharedPtr> string_accessors_;
Expand Down
3 changes: 0 additions & 3 deletions mobile/library/objective-c/EnvoyConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) NSString *appVersion;
@property (nonatomic, strong) NSString *appId;
@property (nonatomic, strong) NSDictionary<NSString *, NSString *> *runtimeGuards;
@property (nonatomic, strong) NSArray<EMODirectResponse *> *typedDirectResponses;
@property (nonatomic, strong) NSArray<EnvoyNativeFilterConfig *> *nativeFilterChain;
@property (nonatomic, strong) NSArray<EnvoyHTTPFilterFactory *> *httpPlatformFilterFactories;
@property (nonatomic, strong) NSDictionary<NSString *, EnvoyStringAccessor *> *stringAccessors;
Expand Down Expand Up @@ -94,8 +93,6 @@ NS_ASSUME_NONNULL_BEGIN
appId:(NSString *)appId
runtimeGuards:
(NSDictionary<NSString *, NSString *> *)runtimeGuards
typedDirectResponses:
(NSArray<EMODirectResponse *> *)typedDirectResponses
nativeFilterChain:
(NSArray<EnvoyNativeFilterConfig *> *)nativeFilterChain
platformFilterChain:
Expand Down
7 changes: 0 additions & 7 deletions mobile/library/objective-c/EnvoyConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled
appId:(NSString *)appId
runtimeGuards:
(NSDictionary<NSString *, NSString *> *)runtimeGuards
typedDirectResponses:
(NSArray<EMODirectResponse *> *)typedDirectResponses
nativeFilterChain:
(NSArray<EnvoyNativeFilterConfig *> *)nativeFilterChain
platformFilterChain:
Expand Down Expand Up @@ -160,7 +158,6 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled
self.appVersion = appVersion;
self.appId = appId;
self.runtimeGuards = runtimeGuards;
self.typedDirectResponses = typedDirectResponses;
self.nativeFilterChain = nativeFilterChain;
self.httpPlatformFilterFactories = httpPlatformFilterFactories;
self.stringAccessors = stringAccessors;
Expand Down Expand Up @@ -211,10 +208,6 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled
builder.setRuntimeGuard([key toCXXString], value);
}

for (EMODirectResponse *directResponse in self.typedDirectResponses) {
builder.addDirectResponse([directResponse toCXX]);
}

builder.addConnectTimeoutSeconds(self.connectTimeoutSeconds);

builder.addDnsFailureRefreshSeconds(self.dnsFailureRefreshSecondsBase,
Expand Down
1 change: 0 additions & 1 deletion mobile/library/swift/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ swift_library(
"StreamClientImpl.swift",
"StreamIntel.swift",
"StreamPrototype.swift",
"TestEngineBuilder.swift",
"Trailers.swift",
"extensions/UserDefaults+KeyValueStore.swift",
"filters/AsyncRequestFilter.swift",
Expand Down
15 changes: 0 additions & 15 deletions mobile/library/swift/EngineBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ open class EngineBuilder: NSObject {
private var stringAccessors: [String: EnvoyStringAccessor] = [:]
private var keyValueStores: [String: EnvoyKeyValueStore] = [:]
private var runtimeGuards: [String: Bool] = [:]
private var directResponses: [DirectResponse] = []
private var statsSinks: [String] = []
private var rtdsLayerName: String?
private var rtdsTimeoutSeconds: UInt32 = 0
Expand Down Expand Up @@ -693,15 +692,6 @@ open class EngineBuilder: NSObject {
return self
}

/// Add a direct response to be used when configuring the engine.
/// This function is internal so it is not publicly exposed to production builders,
/// but is available for use by the `TestEngineBuilder`.
///
/// - parameter directResponse: The response configuration to add.
func addDirectResponseInternal(_ directResponse: DirectResponse) {
self.directResponses.append(directResponse)
}

func makeConfig() -> EnvoyConfiguration {
EnvoyConfiguration(
adminInterfaceEnabled: self.adminInterfaceEnabled,
Expand Down Expand Up @@ -733,7 +723,6 @@ open class EngineBuilder: NSObject {
appVersion: self.appVersion,
appId: self.appId,
runtimeGuards: self.runtimeGuards.mapValues({ "\($0)" }),
typedDirectResponses: self.directResponses.map({ $0.toObjC() }),
nativeFilterChain: self.nativeFilterChain,
platformFilterChain: self.platformFilterChain,
stringAccessors: self.stringAccessors,
Expand Down Expand Up @@ -816,10 +805,6 @@ private extension EngineBuilder {
cxxBuilder.setRuntimeGuard(runtimeGuard.toCXX(), value)
}

for directResponse in self.directResponses {
cxxBuilder.addDirectResponse(directResponse.toCXX())
}

for filter in self.nativeFilterChain.reversed() {
cxxBuilder.addNativeFilter(filter.name.toCXX(), filter.typedConfig.toCXX())
}
Expand Down
19 changes: 0 additions & 19 deletions mobile/library/swift/TestEngineBuilder.swift

This file was deleted.

31 changes: 23 additions & 8 deletions mobile/test/common/integration/test_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "test/integration/server.h"
#include "test/test_common/environment.h"
#include "test/test_common/network_utility.h"

namespace Envoy {

Expand Down Expand Up @@ -58,29 +59,35 @@ TestServer::TestServer()
.WillByDefault(testing::ReturnRef(*stats_store_.rootScope()));
}

void TestServer::startTestServer(bool use_quic) {
void TestServer::startTestServer(TestServerType test_server_type) {
ASSERT(!upstream_);
// pre-setup: see https://github.com/envoyproxy/envoy/blob/main/test/test_runner.cc
Logger::Context logging_state(spdlog::level::level_enum::err,
"[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v", lock, false, false);
// end pre-setup
Network::DownstreamTransportSocketFactoryPtr factory;

if (use_quic) {
switch (test_server_type) {
case TestServerType::HTTP3:
upstream_config_.upstream_protocol_ = Http::CodecType::HTTP3;
upstream_config_.udp_fake_upstream_ = FakeUpstreamConfig::UdpConfig();
} else {
factory = createQuicUpstreamTlsContext(factory_context_);
break;
case TestServerType::HTTP2_WITH_TLS:
upstream_config_.upstream_protocol_ = Http::CodecType::HTTP2;
factory = createUpstreamTlsContext(factory_context_);
break;
case TestServerType::HTTP1_WITHOUT_TLS:
upstream_config_.upstream_protocol_ = Http::CodecType::HTTP1;
factory = Network::Test::createRawBufferDownstreamSocketFactory();
break;
}

Network::DownstreamTransportSocketFactoryPtr factory =
use_quic ? createQuicUpstreamTlsContext(factory_context_)
: createUpstreamTlsContext(factory_context_);

upstream_ = std::make_unique<AutonomousUpstream>(std::move(factory), port_, version_,
upstream_config_, true);

// Legacy behavior for cronet tests.
if (use_quic) {
if (test_server_type == TestServerType::HTTP3) {
upstream_->setResponseHeaders(
std::make_unique<Http::TestResponseHeaderMapImpl>(Http::TestResponseHeaderMapImpl(
{{":status", "200"},
Expand All @@ -102,4 +109,12 @@ int TestServer::getServerPort() {
ASSERT(upstream_);
return upstream_->localAddress()->ip()->port();
}

void TestServer::setHeadersAndData(absl::string_view header_key, absl::string_view header_value,
absl::string_view response_body) {
upstream_->setResponseHeaders(
std::make_unique<Http::TestResponseHeaderMapImpl>(Http::TestResponseHeaderMapImpl(
{{std::string(header_key), std::string(header_value)}, {":status", "200"}})));
upstream_->setResponseBody(std::string(response_body));
}
} // namespace Envoy
Loading

0 comments on commit 67e4108

Please sign in to comment.