1 // Copyright 2017 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15
16 #include <gmock/gmock.h>
17 #include <gtest/gtest.h>
18
19 #include <memory>
20
21 #include "absl/memory/memory.h"
22 #include "absl/strings/str_cat.h"
23 #include "src/core/client_channel/backup_poller.h"
24 #include "src/core/config/config_vars.h"
25 #include "src/core/util/env.h"
26 #include "src/proto/grpc/lookup/v1/rls.pb.h"
27 #include "src/proto/grpc/lookup/v1/rls_config.pb.h"
28 #include "test/core/test_util/scoped_env_var.h"
29 #include "test/cpp/end2end/rls_server.h"
30 #include "test/cpp/end2end/xds/xds_end2end_test_lib.h"
31
32 namespace grpc {
33 namespace testing {
34 namespace {
35
36 using ::grpc::lookup::v1::RouteLookupClusterSpecifier;
37 using ::grpc::lookup::v1::RouteLookupConfig;
38
39 using ::grpc_core::testing::ScopedExperimentalEnvVar;
40
41 constexpr char kRlsTestKey[] = "test_key";
42 constexpr char kRlsTestKey1[] = "key1";
43 constexpr char kRlsTestValue[] = "test_value";
44 constexpr char kRlsHostKey[] = "host_key";
45 constexpr char kRlsServiceKey[] = "service_key";
46 constexpr char kRlsServiceValue[] = "grpc.testing.EchoTestService";
47 constexpr char kRlsMethodKey[] = "method_key";
48 constexpr char kRlsMethodValue[] = "Echo";
49 constexpr char kRlsConstantKey[] = "constant_key";
50 constexpr char kRlsConstantValue[] = "constant_value";
51 constexpr char kRlsClusterSpecifierPluginInstanceName[] = "rls_plugin_instance";
52
53 class RlsTest : public XdsEnd2endTest {
54 protected:
55 class RlsServerThread : public ServerThread {
56 public:
RlsServerThread(XdsEnd2endTest * test_obj)57 explicit RlsServerThread(XdsEnd2endTest* test_obj)
58 : ServerThread(test_obj, /*use_xds_enabled_server=*/false),
59 rls_service_(new RlsServiceImpl()) {}
60
rls_service()61 RlsServiceImpl* rls_service() { return rls_service_.get(); }
62
63 private:
Type()64 const char* Type() override { return "Rls"; }
65
RegisterAllServices(ServerBuilder * builder)66 void RegisterAllServices(ServerBuilder* builder) override {
67 builder->RegisterService(rls_service_.get());
68 }
69
StartAllServices()70 void StartAllServices() override { rls_service_->Start(); }
71
ShutdownAllServices()72 void ShutdownAllServices() override { rls_service_->Shutdown(); }
73
74 std::shared_ptr<RlsServiceImpl> rls_service_;
75 };
76
RlsTest()77 RlsTest() {
78 rls_server_ = std::make_unique<RlsServerThread>(this);
79 rls_server_->Start();
80 }
81
TearDown()82 void TearDown() override {
83 rls_server_->Shutdown();
84 XdsEnd2endTest::TearDown();
85 }
86
87 std::unique_ptr<RlsServerThread> rls_server_;
88 };
89
90 // Test both with and without RDS.
91 INSTANTIATE_TEST_SUITE_P(
92 XdsTest, RlsTest,
93 ::testing::Values(XdsTestType(), XdsTestType().set_enable_rds_testing()),
94 &XdsTestType::Name);
95
TEST_P(RlsTest,XdsRoutingClusterSpecifierPlugin)96 TEST_P(RlsTest, XdsRoutingClusterSpecifierPlugin) {
97 ScopedExperimentalEnvVar env_var("GRPC_EXPERIMENTAL_XDS_RLS_LB");
98 CreateAndStartBackends(2);
99 const char* kNewClusterName = "new_cluster";
100 const char* kNewEdsServiceName = "new_eds_service_name";
101 const size_t kNumEchoRpcs = 5;
102 // Populate new EDS resources.
103 EdsResourceArgs args({
104 {"locality0", CreateEndpointsForBackends(0, 1)},
105 });
106 EdsResourceArgs args1({
107 {"locality0", CreateEndpointsForBackends(1, 2)},
108 });
109 balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
110 balancer_->ads_service()->SetEdsResource(
111 BuildEdsResource(args1, kNewEdsServiceName));
112 // Populate new CDS resources.
113 Cluster new_cluster = default_cluster_;
114 new_cluster.set_name(kNewClusterName);
115 new_cluster.mutable_eds_cluster_config()->set_service_name(
116 kNewEdsServiceName);
117 balancer_->ads_service()->SetCdsResource(new_cluster);
118 // Prepare the RLSLookupConfig and configure all the keys; change route
119 // configurations to use cluster specifier plugin.
120 rls_server_->rls_service()->SetResponse(
121 BuildRlsRequest({{kRlsTestKey, kRlsTestValue},
122 {kRlsHostKey, kServerName},
123 {kRlsServiceKey, kRlsServiceValue},
124 {kRlsMethodKey, kRlsMethodValue},
125 {kRlsConstantKey, kRlsConstantValue}}),
126 BuildRlsResponse({kNewClusterName}));
127 RouteLookupConfig route_lookup_config;
128 auto* key_builder = route_lookup_config.add_grpc_keybuilders();
129 auto* name = key_builder->add_names();
130 name->set_service(kRlsServiceValue);
131 name->set_method(kRlsMethodValue);
132 auto* header = key_builder->add_headers();
133 header->set_key(kRlsTestKey);
134 header->add_names(kRlsTestKey1);
135 header->add_names("key2");
136 auto* extra_keys = key_builder->mutable_extra_keys();
137 extra_keys->set_host(kRlsHostKey);
138 extra_keys->set_service(kRlsServiceKey);
139 extra_keys->set_method(kRlsMethodKey);
140 (*key_builder->mutable_constant_keys())[kRlsConstantKey] = kRlsConstantValue;
141 route_lookup_config.set_lookup_service(
142 absl::StrCat("localhost:", rls_server_->port()));
143 route_lookup_config.set_cache_size_bytes(5000);
144 RouteLookupClusterSpecifier rls;
145 *rls.mutable_route_lookup_config() = std::move(route_lookup_config);
146 RouteConfiguration new_route_config = default_route_config_;
147 auto* plugin = new_route_config.add_cluster_specifier_plugins();
148 plugin->mutable_extension()->set_name(kRlsClusterSpecifierPluginInstanceName);
149 plugin->mutable_extension()->mutable_typed_config()->PackFrom(rls);
150 auto* default_route =
151 new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
152 default_route->mutable_route()->set_cluster_specifier_plugin(
153 kRlsClusterSpecifierPluginInstanceName);
154 SetRouteConfiguration(balancer_.get(), new_route_config);
155 auto rpc_options = RpcOptions().set_metadata({{kRlsTestKey1, kRlsTestValue}});
156 WaitForAllBackends(DEBUG_LOCATION, 1, 2, /*check_status=*/nullptr,
157 WaitForBackendOptions(), rpc_options);
158 CheckRpcSendOk(DEBUG_LOCATION, kNumEchoRpcs, rpc_options);
159 // Make sure RPCs all go to the correct backend.
160 EXPECT_EQ(kNumEchoRpcs, backends_[1]->backend_service()->request_count());
161 }
162
TEST_P(RlsTest,XdsRoutingClusterSpecifierPluginDisabled)163 TEST_P(RlsTest, XdsRoutingClusterSpecifierPluginDisabled) {
164 grpc_core::testing::ScopedEnvVar env_var("GRPC_EXPERIMENTAL_XDS_RLS_LB",
165 "false");
166 CreateAndStartBackends(1);
167 // Populate new EDS resources.
168 EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}});
169 balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
170 // Prepare the RLSLookupConfig and configure all the keys; change route
171 // configurations to use cluster specifier plugin.
172 RouteLookupConfig route_lookup_config;
173 auto* key_builder = route_lookup_config.add_grpc_keybuilders();
174 auto* name = key_builder->add_names();
175 name->set_service(kRlsServiceValue);
176 name->set_method(kRlsMethodValue);
177 auto* header = key_builder->add_headers();
178 header->set_key(kRlsTestKey);
179 header->add_names(kRlsTestKey1);
180 route_lookup_config.set_lookup_service(
181 absl::StrCat("localhost:", rls_server_->port()));
182 route_lookup_config.set_cache_size_bytes(5000);
183 RouteLookupClusterSpecifier rls;
184 *rls.mutable_route_lookup_config() = std::move(route_lookup_config);
185 RouteConfiguration new_route_config = default_route_config_;
186 auto* plugin = new_route_config.add_cluster_specifier_plugins();
187 plugin->mutable_extension()->set_name(kRlsClusterSpecifierPluginInstanceName);
188 plugin->mutable_extension()->mutable_typed_config()->PackFrom(rls);
189 auto* route = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0);
190 route->mutable_route()->set_cluster_specifier_plugin(
191 kRlsClusterSpecifierPluginInstanceName);
192 auto* default_route = new_route_config.mutable_virtual_hosts(0)->add_routes();
193 default_route->mutable_match()->set_prefix("");
194 default_route->mutable_route()->set_cluster(kDefaultClusterName);
195 SetRouteConfiguration(balancer_.get(), new_route_config);
196 // Ensure we ignore the cluster specifier plugin and send traffic according to
197 // the default route.
198 auto rpc_options = RpcOptions().set_metadata({{kRlsTestKey1, kRlsTestValue}});
199 WaitForAllBackends(DEBUG_LOCATION, 0, 1, /*check_status=*/nullptr,
200 WaitForBackendOptions(), rpc_options);
201 }
202
203 } // namespace
204 } // namespace testing
205 } // namespace grpc
206
main(int argc,char ** argv)207 int main(int argc, char** argv) {
208 grpc::testing::TestEnvironment env(&argc, argv);
209 ::testing::InitGoogleTest(&argc, argv);
210 // Make the backup poller poll very frequently in order to pick up
211 // updates from all the subchannels's FDs.
212 grpc_core::ConfigVars::Overrides overrides;
213 overrides.client_channel_backup_poll_interval_ms = 1;
214 grpc_core::ConfigVars::SetOverrides(overrides);
215 #if TARGET_OS_IPHONE
216 // Workaround Apple CFStream bug
217 grpc_core::SetEnv("grpc_cfstream", "0");
218 #endif
219 grpc_init();
220 const auto result = RUN_ALL_TESTS();
221 grpc_shutdown();
222 return result;
223 }
224