1 //
2 // Copyright 2022 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include <stdint.h>
18
19 #include <limits>
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <utility>
24 #include <vector>
25
26 #include <google/protobuf/wrappers.pb.h>
27
28 #include "absl/status/status.h"
29 #include "absl/status/statusor.h"
30 #include "absl/strings/str_format.h"
31 #include "absl/types/optional.h"
32 #include "gtest/gtest.h"
33 #include "upb/mem/arena.hpp"
34 #include "upb/reflection/def.hpp"
35
36 #include <grpc/grpc.h>
37
38 #include "src/core/ext/xds/xds_bootstrap.h"
39 #include "src/core/ext/xds/xds_bootstrap_grpc.h"
40 #include "src/core/ext/xds/xds_client.h"
41 #include "src/core/ext/xds/xds_client_stats.h"
42 #include "src/core/ext/xds/xds_endpoint.h"
43 #include "src/core/ext/xds/xds_health_status.h"
44 #include "src/core/ext/xds/xds_resource_type.h"
45 #include "src/core/lib/address_utils/sockaddr_utils.h"
46 #include "src/core/lib/channel/channel_args.h"
47 #include "src/core/lib/debug/trace.h"
48 #include "src/core/lib/gprpp/crash.h"
49 #include "src/core/lib/gprpp/ref_counted_ptr.h"
50 #include "src/core/lib/iomgr/error.h"
51 #include "src/core/lib/iomgr/resolved_address.h"
52 #include "src/core/resolver/endpoint_addresses.h"
53 #include "src/proto/grpc/testing/xds/v3/address.pb.h"
54 #include "src/proto/grpc/testing/xds/v3/base.pb.h"
55 #include "src/proto/grpc/testing/xds/v3/endpoint.pb.h"
56 #include "src/proto/grpc/testing/xds/v3/health_check.pb.h"
57 #include "src/proto/grpc/testing/xds/v3/percent.pb.h"
58 #include "test/core/util/scoped_env_var.h"
59 #include "test/core/util/test_config.h"
60
61 using envoy::config::endpoint::v3::ClusterLoadAssignment;
62
63 namespace grpc_core {
64 namespace testing {
65 namespace {
66
67 TraceFlag xds_endpoint_resource_type_test_trace(
68 true, "xds_endpoint_resource_type_test");
69
70 class XdsEndpointTest : public ::testing::Test {
71 protected:
XdsEndpointTest()72 XdsEndpointTest()
73 : xds_client_(MakeXdsClient()),
74 decode_context_{xds_client_.get(),
75 *xds_client_->bootstrap().servers().front(),
76 &xds_endpoint_resource_type_test_trace,
77 upb_def_pool_.ptr(), upb_arena_.ptr()} {}
78
MakeXdsClient()79 static RefCountedPtr<XdsClient> MakeXdsClient() {
80 grpc_error_handle error;
81 auto bootstrap = GrpcXdsBootstrap::Create(
82 "{\n"
83 " \"xds_servers\": [\n"
84 " {\n"
85 " \"server_uri\": \"xds.example.com\",\n"
86 " \"channel_creds\": [\n"
87 " {\"type\": \"google_default\"}\n"
88 " ]\n"
89 " }\n"
90 " ]\n"
91 "}");
92 if (!bootstrap.ok()) {
93 Crash(absl::StrFormat("Error parsing bootstrap: %s",
94 bootstrap.status().ToString().c_str()));
95 }
96 return MakeRefCounted<XdsClient>(std::move(*bootstrap),
97 /*transport_factory=*/nullptr,
98 /*event_engine=*/nullptr,
99 /*metrics_reporter=*/nullptr, "foo agent",
100 "foo version");
101 }
102
103 RefCountedPtr<XdsClient> xds_client_;
104 upb::DefPool upb_def_pool_;
105 upb::Arena upb_arena_;
106 XdsResourceType::DecodeContext decode_context_;
107 };
108
TEST_F(XdsEndpointTest,Definition)109 TEST_F(XdsEndpointTest, Definition) {
110 auto* resource_type = XdsEndpointResourceType::Get();
111 ASSERT_NE(resource_type, nullptr);
112 EXPECT_EQ(resource_type->type_url(),
113 "envoy.config.endpoint.v3.ClusterLoadAssignment");
114 EXPECT_FALSE(resource_type->AllResourcesRequiredInSotW());
115 }
116
TEST_F(XdsEndpointTest,UnparseableProto)117 TEST_F(XdsEndpointTest, UnparseableProto) {
118 std::string serialized_resource("\0", 1);
119 auto* resource_type = XdsEndpointResourceType::Get();
120 auto decode_result =
121 resource_type->Decode(decode_context_, serialized_resource);
122 EXPECT_EQ(decode_result.resource.status().code(),
123 absl::StatusCode::kInvalidArgument);
124 EXPECT_EQ(decode_result.resource.status().message(),
125 "Can't parse ClusterLoadAssignment resource.")
126 << decode_result.resource.status();
127 }
128
TEST_F(XdsEndpointTest,MinimumValidConfig)129 TEST_F(XdsEndpointTest, MinimumValidConfig) {
130 ClusterLoadAssignment cla;
131 cla.set_cluster_name("foo");
132 auto* locality = cla.add_endpoints();
133 locality->mutable_load_balancing_weight()->set_value(1);
134 auto* locality_name = locality->mutable_locality();
135 locality_name->set_region("myregion");
136 locality_name->set_zone("myzone");
137 locality_name->set_sub_zone("mysubzone");
138 auto* socket_address = locality->add_lb_endpoints()
139 ->mutable_endpoint()
140 ->mutable_address()
141 ->mutable_socket_address();
142 socket_address->set_address("127.0.0.1");
143 socket_address->set_port_value(443);
144 std::string serialized_resource;
145 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
146 auto* resource_type = XdsEndpointResourceType::Get();
147 auto decode_result =
148 resource_type->Decode(decode_context_, serialized_resource);
149 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
150 ASSERT_TRUE(decode_result.name.has_value());
151 EXPECT_EQ(*decode_result.name, "foo");
152 auto& resource =
153 static_cast<const XdsEndpointResource&>(**decode_result.resource);
154 ASSERT_EQ(resource.priorities.size(), 1);
155 const auto& priority = resource.priorities[0];
156 ASSERT_EQ(priority.localities.size(), 1);
157 const auto& p = *priority.localities.begin();
158 ASSERT_EQ(p.first, p.second.name.get());
159 EXPECT_EQ(p.first->region(), "myregion");
160 EXPECT_EQ(p.first->zone(), "myzone");
161 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
162 EXPECT_EQ(p.second.lb_weight, 1);
163 ASSERT_EQ(p.second.endpoints.size(), 1);
164 const auto& address = p.second.endpoints.front();
165 auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
166 ASSERT_TRUE(addr.ok()) << addr.status();
167 EXPECT_EQ(*addr, "127.0.0.1:443");
168 EXPECT_EQ(address.args(), ChannelArgs()
169 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
170 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
171 XdsHealthStatus::HealthStatus::kUnknown));
172 EXPECT_EQ(resource.drop_config, nullptr);
173 }
174
TEST_F(XdsEndpointTest,EndpointWeight)175 TEST_F(XdsEndpointTest, EndpointWeight) {
176 ClusterLoadAssignment cla;
177 cla.set_cluster_name("foo");
178 auto* locality = cla.add_endpoints();
179 locality->mutable_load_balancing_weight()->set_value(1);
180 auto* locality_name = locality->mutable_locality();
181 locality_name->set_region("myregion");
182 locality_name->set_zone("myzone");
183 locality_name->set_sub_zone("mysubzone");
184 auto* endpoint = locality->add_lb_endpoints();
185 endpoint->mutable_load_balancing_weight()->set_value(3);
186 auto* socket_address =
187 endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
188 socket_address->set_address("127.0.0.1");
189 socket_address->set_port_value(443);
190 std::string serialized_resource;
191 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
192 auto* resource_type = XdsEndpointResourceType::Get();
193 auto decode_result =
194 resource_type->Decode(decode_context_, serialized_resource);
195 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
196 ASSERT_TRUE(decode_result.name.has_value());
197 EXPECT_EQ(*decode_result.name, "foo");
198 auto& resource =
199 static_cast<const XdsEndpointResource&>(**decode_result.resource);
200 ASSERT_EQ(resource.priorities.size(), 1);
201 const auto& priority = resource.priorities[0];
202 ASSERT_EQ(priority.localities.size(), 1);
203 const auto& p = *priority.localities.begin();
204 ASSERT_EQ(p.first, p.second.name.get());
205 EXPECT_EQ(p.first->region(), "myregion");
206 EXPECT_EQ(p.first->zone(), "myzone");
207 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
208 EXPECT_EQ(p.second.lb_weight, 1);
209 ASSERT_EQ(p.second.endpoints.size(), 1);
210 const auto& address = p.second.endpoints.front();
211 auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
212 ASSERT_TRUE(addr.ok()) << addr.status();
213 EXPECT_EQ(*addr, "127.0.0.1:443");
214 EXPECT_EQ(address.args(), ChannelArgs()
215 .Set(GRPC_ARG_ADDRESS_WEIGHT, 3)
216 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
217 XdsHealthStatus::HealthStatus::kUnknown));
218 EXPECT_EQ(resource.drop_config, nullptr);
219 }
220
TEST_F(XdsEndpointTest,IgnoresLocalityWithNoWeight)221 TEST_F(XdsEndpointTest, IgnoresLocalityWithNoWeight) {
222 ClusterLoadAssignment cla;
223 cla.set_cluster_name("foo");
224 auto* locality = cla.add_endpoints();
225 auto* locality_name = locality->mutable_locality();
226 locality_name->set_region("myregion");
227 locality_name->set_zone("myzone");
228 locality_name->set_sub_zone("mysubzone");
229 auto* socket_address = locality->add_lb_endpoints()
230 ->mutable_endpoint()
231 ->mutable_address()
232 ->mutable_socket_address();
233 socket_address->set_address("127.0.0.1");
234 socket_address->set_port_value(443);
235 locality = cla.add_endpoints();
236 *locality = cla.endpoints(0);
237 locality->mutable_load_balancing_weight()->set_value(1);
238 std::string serialized_resource;
239 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
240 auto* resource_type = XdsEndpointResourceType::Get();
241 auto decode_result =
242 resource_type->Decode(decode_context_, serialized_resource);
243 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
244 ASSERT_TRUE(decode_result.name.has_value());
245 EXPECT_EQ(*decode_result.name, "foo");
246 auto& resource =
247 static_cast<const XdsEndpointResource&>(**decode_result.resource);
248 ASSERT_EQ(resource.priorities.size(), 1);
249 const auto& priority = resource.priorities[0];
250 ASSERT_EQ(priority.localities.size(), 1);
251 const auto& p = *priority.localities.begin();
252 ASSERT_EQ(p.first, p.second.name.get());
253 EXPECT_EQ(p.first->region(), "myregion");
254 EXPECT_EQ(p.first->zone(), "myzone");
255 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
256 EXPECT_EQ(p.second.lb_weight, 1);
257 ASSERT_EQ(p.second.endpoints.size(), 1);
258 const auto& address = p.second.endpoints.front();
259 auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
260 ASSERT_TRUE(addr.ok()) << addr.status();
261 EXPECT_EQ(*addr, "127.0.0.1:443");
262 EXPECT_EQ(address.args(), ChannelArgs()
263 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
264 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
265 XdsHealthStatus::HealthStatus::kUnknown));
266 EXPECT_EQ(resource.drop_config, nullptr);
267 }
268
TEST_F(XdsEndpointTest,IgnoresLocalityWithZeroWeight)269 TEST_F(XdsEndpointTest, IgnoresLocalityWithZeroWeight) {
270 ClusterLoadAssignment cla;
271 cla.set_cluster_name("foo");
272 auto* locality = cla.add_endpoints();
273 locality->mutable_load_balancing_weight()->set_value(0);
274 auto* locality_name = locality->mutable_locality();
275 locality_name->set_region("myregion");
276 locality_name->set_zone("myzone");
277 locality_name->set_sub_zone("mysubzone");
278 auto* socket_address = locality->add_lb_endpoints()
279 ->mutable_endpoint()
280 ->mutable_address()
281 ->mutable_socket_address();
282 socket_address->set_address("127.0.0.1");
283 socket_address->set_port_value(443);
284 locality = cla.add_endpoints();
285 *locality = cla.endpoints(0);
286 locality->mutable_load_balancing_weight()->set_value(1);
287 std::string serialized_resource;
288 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
289 auto* resource_type = XdsEndpointResourceType::Get();
290 auto decode_result =
291 resource_type->Decode(decode_context_, serialized_resource);
292 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
293 ASSERT_TRUE(decode_result.name.has_value());
294 EXPECT_EQ(*decode_result.name, "foo");
295 auto& resource =
296 static_cast<const XdsEndpointResource&>(**decode_result.resource);
297 ASSERT_EQ(resource.priorities.size(), 1);
298 const auto& priority = resource.priorities[0];
299 ASSERT_EQ(priority.localities.size(), 1);
300 const auto& p = *priority.localities.begin();
301 ASSERT_EQ(p.first, p.second.name.get());
302 EXPECT_EQ(p.first->region(), "myregion");
303 EXPECT_EQ(p.first->zone(), "myzone");
304 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
305 EXPECT_EQ(p.second.lb_weight, 1);
306 ASSERT_EQ(p.second.endpoints.size(), 1);
307 const auto& address = p.second.endpoints.front();
308 auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
309 ASSERT_TRUE(addr.ok()) << addr.status();
310 EXPECT_EQ(*addr, "127.0.0.1:443");
311 EXPECT_EQ(address.args(), ChannelArgs()
312 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
313 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
314 XdsHealthStatus::HealthStatus::kUnknown));
315 EXPECT_EQ(resource.drop_config, nullptr);
316 }
317
TEST_F(XdsEndpointTest,LocalityWithNoEndpoints)318 TEST_F(XdsEndpointTest, LocalityWithNoEndpoints) {
319 ClusterLoadAssignment cla;
320 cla.set_cluster_name("foo");
321 auto* locality = cla.add_endpoints();
322 locality->mutable_load_balancing_weight()->set_value(1);
323 auto* locality_name = locality->mutable_locality();
324 locality_name->set_region("myregion");
325 locality_name->set_zone("myzone");
326 locality_name->set_sub_zone("mysubzone");
327 std::string serialized_resource;
328 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
329 auto* resource_type = XdsEndpointResourceType::Get();
330 auto decode_result =
331 resource_type->Decode(decode_context_, serialized_resource);
332 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
333 ASSERT_TRUE(decode_result.name.has_value());
334 EXPECT_EQ(*decode_result.name, "foo");
335 auto& resource =
336 static_cast<const XdsEndpointResource&>(**decode_result.resource);
337 ASSERT_EQ(resource.priorities.size(), 1);
338 const auto& priority = resource.priorities[0];
339 ASSERT_EQ(priority.localities.size(), 1);
340 const auto& p = *priority.localities.begin();
341 ASSERT_EQ(p.first, p.second.name.get());
342 EXPECT_EQ(p.first->region(), "myregion");
343 EXPECT_EQ(p.first->zone(), "myzone");
344 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
345 EXPECT_EQ(p.second.lb_weight, 1);
346 EXPECT_EQ(p.second.endpoints.size(), 0);
347 EXPECT_EQ(resource.drop_config, nullptr);
348 }
349
TEST_F(XdsEndpointTest,NoLocality)350 TEST_F(XdsEndpointTest, NoLocality) {
351 ClusterLoadAssignment cla;
352 cla.set_cluster_name("foo");
353 auto* locality = cla.add_endpoints();
354 locality->mutable_load_balancing_weight()->set_value(1);
355 auto* socket_address = locality->add_lb_endpoints()
356 ->mutable_endpoint()
357 ->mutable_address()
358 ->mutable_socket_address();
359 socket_address->set_address("127.0.0.1");
360 socket_address->set_port_value(443);
361 std::string serialized_resource;
362 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
363 auto* resource_type = XdsEndpointResourceType::Get();
364 auto decode_result =
365 resource_type->Decode(decode_context_, serialized_resource);
366 ASSERT_TRUE(decode_result.name.has_value());
367 EXPECT_EQ(*decode_result.name, "foo");
368 EXPECT_EQ(decode_result.resource.status().code(),
369 absl::StatusCode::kInvalidArgument);
370 EXPECT_EQ(decode_result.resource.status().message(),
371 "errors parsing EDS resource: ["
372 "field:endpoints[0].locality error:field not present]")
373 << decode_result.resource.status();
374 }
375
TEST_F(XdsEndpointTest,InvalidPort)376 TEST_F(XdsEndpointTest, InvalidPort) {
377 ClusterLoadAssignment cla;
378 cla.set_cluster_name("foo");
379 auto* locality = cla.add_endpoints();
380 locality->mutable_load_balancing_weight()->set_value(1);
381 auto* locality_name = locality->mutable_locality();
382 locality_name->set_region("myregion");
383 locality_name->set_zone("myzone");
384 locality_name->set_sub_zone("mysubzone");
385 auto* socket_address = locality->add_lb_endpoints()
386 ->mutable_endpoint()
387 ->mutable_address()
388 ->mutable_socket_address();
389 socket_address->set_address("127.0.0.1");
390 socket_address->set_port_value(65537);
391 std::string serialized_resource;
392 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
393 auto* resource_type = XdsEndpointResourceType::Get();
394 auto decode_result =
395 resource_type->Decode(decode_context_, serialized_resource);
396 ASSERT_TRUE(decode_result.name.has_value());
397 EXPECT_EQ(*decode_result.name, "foo");
398 EXPECT_EQ(decode_result.resource.status().code(),
399 absl::StatusCode::kInvalidArgument);
400 EXPECT_EQ(decode_result.resource.status().message(),
401 "errors parsing EDS resource: ["
402 "field:endpoints[0].lb_endpoints[0].endpoint.address"
403 ".socket_address.port_value error:invalid port]")
404 << decode_result.resource.status();
405 }
406
TEST_F(XdsEndpointTest,InvalidAddress)407 TEST_F(XdsEndpointTest, InvalidAddress) {
408 ClusterLoadAssignment cla;
409 cla.set_cluster_name("foo");
410 auto* locality = cla.add_endpoints();
411 locality->mutable_load_balancing_weight()->set_value(1);
412 auto* locality_name = locality->mutable_locality();
413 locality_name->set_region("myregion");
414 locality_name->set_zone("myzone");
415 locality_name->set_sub_zone("mysubzone");
416 auto* socket_address = locality->add_lb_endpoints()
417 ->mutable_endpoint()
418 ->mutable_address()
419 ->mutable_socket_address();
420 socket_address->set_address("not_an_ip_address");
421 socket_address->set_port_value(443);
422 std::string serialized_resource;
423 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
424 auto* resource_type = XdsEndpointResourceType::Get();
425 auto decode_result =
426 resource_type->Decode(decode_context_, serialized_resource);
427 ASSERT_TRUE(decode_result.name.has_value());
428 EXPECT_EQ(*decode_result.name, "foo");
429 EXPECT_EQ(decode_result.resource.status().code(),
430 absl::StatusCode::kInvalidArgument);
431 EXPECT_EQ(decode_result.resource.status().message(),
432 "errors parsing EDS resource: ["
433 "field:endpoints[0].lb_endpoints[0].endpoint.address"
434 ".socket_address error:"
435 "Failed to parse address:not_an_ip_address:443]")
436 << decode_result.resource.status();
437 }
438
TEST_F(XdsEndpointTest,MissingSocketAddress)439 TEST_F(XdsEndpointTest, MissingSocketAddress) {
440 ClusterLoadAssignment cla;
441 cla.set_cluster_name("foo");
442 auto* locality = cla.add_endpoints();
443 locality->mutable_load_balancing_weight()->set_value(1);
444 auto* locality_name = locality->mutable_locality();
445 locality_name->set_region("myregion");
446 locality_name->set_zone("myzone");
447 locality_name->set_sub_zone("mysubzone");
448 locality->add_lb_endpoints()->mutable_endpoint()->mutable_address();
449 std::string serialized_resource;
450 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
451 auto* resource_type = XdsEndpointResourceType::Get();
452 auto decode_result =
453 resource_type->Decode(decode_context_, serialized_resource);
454 ASSERT_TRUE(decode_result.name.has_value());
455 EXPECT_EQ(*decode_result.name, "foo");
456 EXPECT_EQ(decode_result.resource.status().code(),
457 absl::StatusCode::kInvalidArgument);
458 EXPECT_EQ(decode_result.resource.status().message(),
459 "errors parsing EDS resource: ["
460 "field:endpoints[0].lb_endpoints[0].endpoint.address"
461 ".socket_address error:field not present]")
462 << decode_result.resource.status();
463 }
464
TEST_F(XdsEndpointTest,MissingAddress)465 TEST_F(XdsEndpointTest, MissingAddress) {
466 ClusterLoadAssignment cla;
467 cla.set_cluster_name("foo");
468 auto* locality = cla.add_endpoints();
469 locality->mutable_load_balancing_weight()->set_value(1);
470 auto* locality_name = locality->mutable_locality();
471 locality_name->set_region("myregion");
472 locality_name->set_zone("myzone");
473 locality_name->set_sub_zone("mysubzone");
474 locality->add_lb_endpoints()->mutable_endpoint();
475 std::string serialized_resource;
476 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
477 auto* resource_type = XdsEndpointResourceType::Get();
478 auto decode_result =
479 resource_type->Decode(decode_context_, serialized_resource);
480 ASSERT_TRUE(decode_result.name.has_value());
481 EXPECT_EQ(*decode_result.name, "foo");
482 EXPECT_EQ(decode_result.resource.status().code(),
483 absl::StatusCode::kInvalidArgument);
484 EXPECT_EQ(decode_result.resource.status().message(),
485 "errors parsing EDS resource: ["
486 "field:endpoints[0].lb_endpoints[0].endpoint.address "
487 "error:field not present]")
488 << decode_result.resource.status();
489 }
490
TEST_F(XdsEndpointTest,MultipleAddressesPerEndpoint)491 TEST_F(XdsEndpointTest, MultipleAddressesPerEndpoint) {
492 testing::ScopedExperimentalEnvVar env(
493 "GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS");
494 ClusterLoadAssignment cla;
495 cla.set_cluster_name("foo");
496 auto* locality = cla.add_endpoints();
497 locality->mutable_load_balancing_weight()->set_value(1);
498 auto* locality_name = locality->mutable_locality();
499 locality_name->set_region("myregion");
500 locality_name->set_zone("myzone");
501 locality_name->set_sub_zone("mysubzone");
502 auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
503 auto* socket_address = ep->mutable_address()->mutable_socket_address();
504 socket_address->set_address("127.0.0.1");
505 socket_address->set_port_value(443);
506 socket_address = ep->add_additional_addresses()
507 ->mutable_address()
508 ->mutable_socket_address();
509 socket_address->set_address("127.0.0.1");
510 socket_address->set_port_value(444);
511 std::string serialized_resource;
512 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
513 auto* resource_type = XdsEndpointResourceType::Get();
514 auto decode_result =
515 resource_type->Decode(decode_context_, serialized_resource);
516 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
517 ASSERT_TRUE(decode_result.name.has_value());
518 EXPECT_EQ(*decode_result.name, "foo");
519 auto& resource =
520 static_cast<const XdsEndpointResource&>(**decode_result.resource);
521 ASSERT_EQ(resource.priorities.size(), 1);
522 const auto& priority = resource.priorities[0];
523 ASSERT_EQ(priority.localities.size(), 1);
524 const auto& p = *priority.localities.begin();
525 ASSERT_EQ(p.first, p.second.name.get());
526 EXPECT_EQ(p.first->region(), "myregion");
527 EXPECT_EQ(p.first->zone(), "myzone");
528 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
529 EXPECT_EQ(p.second.lb_weight, 1);
530 ASSERT_EQ(p.second.endpoints.size(), 1);
531 const auto& endpoint = p.second.endpoints.front();
532 ASSERT_EQ(endpoint.addresses().size(), 2);
533 auto addr =
534 grpc_sockaddr_to_string(&endpoint.addresses()[0], /*normalize=*/false);
535 ASSERT_TRUE(addr.ok()) << addr.status();
536 EXPECT_EQ(*addr, "127.0.0.1:443");
537 addr = grpc_sockaddr_to_string(&endpoint.addresses()[1], /*normalize=*/false);
538 ASSERT_TRUE(addr.ok()) << addr.status();
539 EXPECT_EQ(*addr, "127.0.0.1:444");
540 EXPECT_EQ(endpoint.args(), ChannelArgs()
541 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
542 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
543 XdsHealthStatus::HealthStatus::kUnknown));
544 EXPECT_EQ(resource.drop_config, nullptr);
545 }
546
TEST_F(XdsEndpointTest,AdditionalAddressesMissingAddress)547 TEST_F(XdsEndpointTest, AdditionalAddressesMissingAddress) {
548 testing::ScopedExperimentalEnvVar env(
549 "GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS");
550 ClusterLoadAssignment cla;
551 cla.set_cluster_name("foo");
552 auto* locality = cla.add_endpoints();
553 locality->mutable_load_balancing_weight()->set_value(1);
554 auto* locality_name = locality->mutable_locality();
555 locality_name->set_region("myregion");
556 locality_name->set_zone("myzone");
557 locality_name->set_sub_zone("mysubzone");
558 auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
559 auto* socket_address = ep->mutable_address()->mutable_socket_address();
560 socket_address->set_address("127.0.0.1");
561 socket_address->set_port_value(443);
562 ep->add_additional_addresses();
563 std::string serialized_resource;
564 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
565 auto* resource_type = XdsEndpointResourceType::Get();
566 auto decode_result =
567 resource_type->Decode(decode_context_, serialized_resource);
568 ASSERT_TRUE(decode_result.name.has_value());
569 EXPECT_EQ(*decode_result.name, "foo");
570 EXPECT_EQ(decode_result.resource.status().code(),
571 absl::StatusCode::kInvalidArgument);
572 EXPECT_EQ(decode_result.resource.status().message(),
573 "errors parsing EDS resource: ["
574 "field:endpoints[0].lb_endpoints[0].endpoint"
575 ".additional_addresses[0].address error:field not present]")
576 << decode_result.resource.status();
577 }
578
TEST_F(XdsEndpointTest,AdditionalAddressesMissingSocketAddress)579 TEST_F(XdsEndpointTest, AdditionalAddressesMissingSocketAddress) {
580 testing::ScopedExperimentalEnvVar env(
581 "GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS");
582 ClusterLoadAssignment cla;
583 cla.set_cluster_name("foo");
584 auto* locality = cla.add_endpoints();
585 locality->mutable_load_balancing_weight()->set_value(1);
586 auto* locality_name = locality->mutable_locality();
587 locality_name->set_region("myregion");
588 locality_name->set_zone("myzone");
589 locality_name->set_sub_zone("mysubzone");
590 auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
591 auto* socket_address = ep->mutable_address()->mutable_socket_address();
592 socket_address->set_address("127.0.0.1");
593 socket_address->set_port_value(443);
594 ep->add_additional_addresses()->mutable_address();
595 std::string serialized_resource;
596 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
597 auto* resource_type = XdsEndpointResourceType::Get();
598 auto decode_result =
599 resource_type->Decode(decode_context_, serialized_resource);
600 ASSERT_TRUE(decode_result.name.has_value());
601 EXPECT_EQ(*decode_result.name, "foo");
602 EXPECT_EQ(decode_result.resource.status().code(),
603 absl::StatusCode::kInvalidArgument);
604 EXPECT_EQ(decode_result.resource.status().message(),
605 "errors parsing EDS resource: ["
606 "field:endpoints[0].lb_endpoints[0].endpoint"
607 ".additional_addresses[0].address.socket_address "
608 "error:field not present]")
609 << decode_result.resource.status();
610 }
611
TEST_F(XdsEndpointTest,AdditionalAddressesInvalidPort)612 TEST_F(XdsEndpointTest, AdditionalAddressesInvalidPort) {
613 testing::ScopedExperimentalEnvVar env(
614 "GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS");
615 ClusterLoadAssignment cla;
616 cla.set_cluster_name("foo");
617 auto* locality = cla.add_endpoints();
618 locality->mutable_load_balancing_weight()->set_value(1);
619 auto* locality_name = locality->mutable_locality();
620 locality_name->set_region("myregion");
621 locality_name->set_zone("myzone");
622 locality_name->set_sub_zone("mysubzone");
623 auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
624 auto* socket_address = ep->mutable_address()->mutable_socket_address();
625 socket_address->set_address("127.0.0.1");
626 socket_address->set_port_value(443);
627 socket_address = ep->add_additional_addresses()
628 ->mutable_address()
629 ->mutable_socket_address();
630 socket_address->set_address("127.0.0.1");
631 socket_address->set_port_value(65537);
632 std::string serialized_resource;
633 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
634 auto* resource_type = XdsEndpointResourceType::Get();
635 auto decode_result =
636 resource_type->Decode(decode_context_, serialized_resource);
637 ASSERT_TRUE(decode_result.name.has_value());
638 EXPECT_EQ(*decode_result.name, "foo");
639 EXPECT_EQ(decode_result.resource.status().code(),
640 absl::StatusCode::kInvalidArgument);
641 EXPECT_EQ(decode_result.resource.status().message(),
642 "errors parsing EDS resource: ["
643 "field:endpoints[0].lb_endpoints[0].endpoint"
644 ".additional_addresses[0].address.socket_address.port_value "
645 "error:invalid port]")
646 << decode_result.resource.status();
647 }
648
TEST_F(XdsEndpointTest,AdditionalAddressesInvalidAddress)649 TEST_F(XdsEndpointTest, AdditionalAddressesInvalidAddress) {
650 testing::ScopedExperimentalEnvVar env(
651 "GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS");
652 ClusterLoadAssignment cla;
653 cla.set_cluster_name("foo");
654 auto* locality = cla.add_endpoints();
655 locality->mutable_load_balancing_weight()->set_value(1);
656 auto* locality_name = locality->mutable_locality();
657 locality_name->set_region("myregion");
658 locality_name->set_zone("myzone");
659 locality_name->set_sub_zone("mysubzone");
660 auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
661 auto* socket_address = ep->mutable_address()->mutable_socket_address();
662 socket_address->set_address("127.0.0.1");
663 socket_address->set_port_value(443);
664 socket_address = ep->add_additional_addresses()
665 ->mutable_address()
666 ->mutable_socket_address();
667 socket_address->set_address("not_an_ip_address");
668 socket_address->set_port_value(444);
669 std::string serialized_resource;
670 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
671 auto* resource_type = XdsEndpointResourceType::Get();
672 auto decode_result =
673 resource_type->Decode(decode_context_, serialized_resource);
674 ASSERT_TRUE(decode_result.name.has_value());
675 EXPECT_EQ(*decode_result.name, "foo");
676 EXPECT_EQ(decode_result.resource.status().code(),
677 absl::StatusCode::kInvalidArgument);
678 EXPECT_EQ(decode_result.resource.status().message(),
679 "errors parsing EDS resource: ["
680 "field:endpoints[0].lb_endpoints[0].endpoint"
681 ".additional_addresses[0].address.socket_address error:"
682 "Failed to parse address:not_an_ip_address:444]")
683 << decode_result.resource.status();
684 }
685
TEST_F(XdsEndpointTest,IgnoresMultipleAddressesPerEndpointWhenNotEnabled)686 TEST_F(XdsEndpointTest, IgnoresMultipleAddressesPerEndpointWhenNotEnabled) {
687 ClusterLoadAssignment cla;
688 cla.set_cluster_name("foo");
689 auto* locality = cla.add_endpoints();
690 locality->mutable_load_balancing_weight()->set_value(1);
691 auto* locality_name = locality->mutable_locality();
692 locality_name->set_region("myregion");
693 locality_name->set_zone("myzone");
694 locality_name->set_sub_zone("mysubzone");
695 auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
696 auto* socket_address = ep->mutable_address()->mutable_socket_address();
697 socket_address->set_address("127.0.0.1");
698 socket_address->set_port_value(443);
699 socket_address = ep->add_additional_addresses()
700 ->mutable_address()
701 ->mutable_socket_address();
702 socket_address->set_address("127.0.0.1");
703 socket_address->set_port_value(444);
704 std::string serialized_resource;
705 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
706 auto* resource_type = XdsEndpointResourceType::Get();
707 auto decode_result =
708 resource_type->Decode(decode_context_, serialized_resource);
709 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
710 ASSERT_TRUE(decode_result.name.has_value());
711 EXPECT_EQ(*decode_result.name, "foo");
712 auto& resource =
713 static_cast<const XdsEndpointResource&>(**decode_result.resource);
714 ASSERT_EQ(resource.priorities.size(), 1);
715 const auto& priority = resource.priorities[0];
716 ASSERT_EQ(priority.localities.size(), 1);
717 const auto& p = *priority.localities.begin();
718 ASSERT_EQ(p.first, p.second.name.get());
719 EXPECT_EQ(p.first->region(), "myregion");
720 EXPECT_EQ(p.first->zone(), "myzone");
721 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
722 EXPECT_EQ(p.second.lb_weight, 1);
723 ASSERT_EQ(p.second.endpoints.size(), 1);
724 const auto& endpoint = p.second.endpoints.front();
725 ASSERT_EQ(endpoint.addresses().size(), 1);
726 auto addr =
727 grpc_sockaddr_to_string(&endpoint.addresses()[0], /*normalize=*/false);
728 ASSERT_TRUE(addr.ok()) << addr.status();
729 EXPECT_EQ(*addr, "127.0.0.1:443");
730 EXPECT_EQ(endpoint.args(), ChannelArgs()
731 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
732 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
733 XdsHealthStatus::HealthStatus::kUnknown));
734 EXPECT_EQ(resource.drop_config, nullptr);
735 }
736
TEST_F(XdsEndpointTest,MissingEndpoint)737 TEST_F(XdsEndpointTest, MissingEndpoint) {
738 ClusterLoadAssignment cla;
739 cla.set_cluster_name("foo");
740 auto* locality = cla.add_endpoints();
741 locality->mutable_load_balancing_weight()->set_value(1);
742 auto* locality_name = locality->mutable_locality();
743 locality_name->set_region("myregion");
744 locality_name->set_zone("myzone");
745 locality_name->set_sub_zone("mysubzone");
746 locality->add_lb_endpoints();
747 std::string serialized_resource;
748 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
749 auto* resource_type = XdsEndpointResourceType::Get();
750 auto decode_result =
751 resource_type->Decode(decode_context_, serialized_resource);
752 ASSERT_TRUE(decode_result.name.has_value());
753 EXPECT_EQ(*decode_result.name, "foo");
754 EXPECT_EQ(decode_result.resource.status().code(),
755 absl::StatusCode::kInvalidArgument);
756 EXPECT_EQ(decode_result.resource.status().message(),
757 "errors parsing EDS resource: ["
758 "field:endpoints[0].lb_endpoints[0].endpoint "
759 "error:field not present]")
760 << decode_result.resource.status();
761 }
762
TEST_F(XdsEndpointTest,EndpointWeightZero)763 TEST_F(XdsEndpointTest, EndpointWeightZero) {
764 ClusterLoadAssignment cla;
765 cla.set_cluster_name("foo");
766 auto* locality = cla.add_endpoints();
767 locality->mutable_load_balancing_weight()->set_value(1);
768 auto* locality_name = locality->mutable_locality();
769 locality_name->set_region("myregion");
770 locality_name->set_zone("myzone");
771 locality_name->set_sub_zone("mysubzone");
772 auto* endpoint = locality->add_lb_endpoints();
773 endpoint->mutable_load_balancing_weight()->set_value(0);
774 auto* socket_address =
775 endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
776 socket_address->set_address("127.0.0.1");
777 socket_address->set_port_value(443);
778 std::string serialized_resource;
779 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
780 auto* resource_type = XdsEndpointResourceType::Get();
781 auto decode_result =
782 resource_type->Decode(decode_context_, serialized_resource);
783 ASSERT_TRUE(decode_result.name.has_value());
784 EXPECT_EQ(*decode_result.name, "foo");
785 EXPECT_EQ(decode_result.resource.status().code(),
786 absl::StatusCode::kInvalidArgument);
787 EXPECT_EQ(decode_result.resource.status().message(),
788 "errors parsing EDS resource: ["
789 "field:endpoints[0].lb_endpoints[0].load_balancing_weight "
790 "error:must be greater than 0]")
791 << decode_result.resource.status();
792 }
793
TEST_F(XdsEndpointTest,DuplicateLocalityName)794 TEST_F(XdsEndpointTest, DuplicateLocalityName) {
795 ClusterLoadAssignment cla;
796 cla.set_cluster_name("foo");
797 auto* locality = cla.add_endpoints();
798 locality->mutable_load_balancing_weight()->set_value(1);
799 auto* locality_name = locality->mutable_locality();
800 locality_name->set_region("myregion");
801 locality_name->set_zone("myzone");
802 locality_name->set_sub_zone("mysubzone");
803 auto* socket_address = locality->add_lb_endpoints()
804 ->mutable_endpoint()
805 ->mutable_address()
806 ->mutable_socket_address();
807 socket_address->set_address("127.0.0.1");
808 socket_address->set_port_value(443);
809 locality = cla.add_endpoints();
810 locality->mutable_load_balancing_weight()->set_value(1);
811 locality_name = locality->mutable_locality();
812 locality_name->set_region("myregion");
813 locality_name->set_zone("myzone");
814 locality_name->set_sub_zone("mysubzone");
815 socket_address = locality->add_lb_endpoints()
816 ->mutable_endpoint()
817 ->mutable_address()
818 ->mutable_socket_address();
819 socket_address->set_address("127.0.0.2");
820 socket_address->set_port_value(443);
821 std::string serialized_resource;
822 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
823 auto* resource_type = XdsEndpointResourceType::Get();
824 auto decode_result =
825 resource_type->Decode(decode_context_, serialized_resource);
826 ASSERT_TRUE(decode_result.name.has_value());
827 EXPECT_EQ(*decode_result.name, "foo");
828 EXPECT_EQ(decode_result.resource.status().code(),
829 absl::StatusCode::kInvalidArgument);
830 EXPECT_EQ(decode_result.resource.status().message(),
831 "errors parsing EDS resource: ["
832 "field:endpoints[1] error:duplicate locality {region=\"myregion\", "
833 "zone=\"myzone\", sub_zone=\"mysubzone\"} found in priority 0]")
834 << decode_result.resource.status();
835 }
836
TEST_F(XdsEndpointTest,SparsePriorityList)837 TEST_F(XdsEndpointTest, SparsePriorityList) {
838 ClusterLoadAssignment cla;
839 cla.set_cluster_name("foo");
840 auto* locality = cla.add_endpoints();
841 locality->mutable_load_balancing_weight()->set_value(1);
842 auto* locality_name = locality->mutable_locality();
843 locality_name->set_region("myregion");
844 locality_name->set_zone("myzone");
845 locality_name->set_sub_zone("mysubzone");
846 auto* socket_address = locality->add_lb_endpoints()
847 ->mutable_endpoint()
848 ->mutable_address()
849 ->mutable_socket_address();
850 socket_address->set_address("127.0.0.1");
851 socket_address->set_port_value(443);
852 locality->set_priority(1);
853 locality = cla.add_endpoints();
854 locality->mutable_load_balancing_weight()->set_value(1);
855 locality_name = locality->mutable_locality();
856 locality_name->set_region("myregion2");
857 locality_name->set_zone("myzone");
858 locality_name->set_sub_zone("mysubzone");
859 socket_address = locality->add_lb_endpoints()
860 ->mutable_endpoint()
861 ->mutable_address()
862 ->mutable_socket_address();
863 socket_address->set_address("127.0.0.2");
864 socket_address->set_port_value(443);
865 locality->set_priority(3);
866 std::string serialized_resource;
867 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
868 auto* resource_type = XdsEndpointResourceType::Get();
869 auto decode_result =
870 resource_type->Decode(decode_context_, serialized_resource);
871 ASSERT_TRUE(decode_result.name.has_value());
872 EXPECT_EQ(*decode_result.name, "foo");
873 EXPECT_EQ(decode_result.resource.status().code(),
874 absl::StatusCode::kInvalidArgument);
875 EXPECT_EQ(decode_result.resource.status().message(),
876 "errors parsing EDS resource: ["
877 "field:endpoints errors:[priority 0 empty; priority 2 empty]]")
878 << decode_result.resource.status();
879 }
880
TEST_F(XdsEndpointTest,LocalityWeightsWithinPriorityExceedUint32Max)881 TEST_F(XdsEndpointTest, LocalityWeightsWithinPriorityExceedUint32Max) {
882 ClusterLoadAssignment cla;
883 cla.set_cluster_name("foo");
884 // First locality has weight of 1.
885 auto* locality = cla.add_endpoints();
886 locality->mutable_load_balancing_weight()->set_value(1);
887 auto* locality_name = locality->mutable_locality();
888 locality_name->set_region("myregion");
889 locality_name->set_zone("myzone");
890 locality_name->set_sub_zone("mysubzone");
891 auto* socket_address = locality->add_lb_endpoints()
892 ->mutable_endpoint()
893 ->mutable_address()
894 ->mutable_socket_address();
895 socket_address->set_address("127.0.0.1");
896 socket_address->set_port_value(443);
897 locality->set_priority(0);
898 // Second locality has weight of uint32 max.
899 locality = cla.add_endpoints();
900 locality->mutable_load_balancing_weight()->set_value(
901 std::numeric_limits<uint32_t>::max());
902 locality_name = locality->mutable_locality();
903 locality_name->set_region("myregion2");
904 locality_name->set_zone("myzone");
905 locality_name->set_sub_zone("mysubzone");
906 socket_address = locality->add_lb_endpoints()
907 ->mutable_endpoint()
908 ->mutable_address()
909 ->mutable_socket_address();
910 socket_address->set_address("127.0.0.2");
911 socket_address->set_port_value(443);
912 locality->set_priority(0);
913 std::string serialized_resource;
914 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
915 auto* resource_type = XdsEndpointResourceType::Get();
916 auto decode_result =
917 resource_type->Decode(decode_context_, serialized_resource);
918 ASSERT_TRUE(decode_result.name.has_value());
919 EXPECT_EQ(*decode_result.name, "foo");
920 EXPECT_EQ(decode_result.resource.status().code(),
921 absl::StatusCode::kInvalidArgument);
922 EXPECT_EQ(decode_result.resource.status().message(),
923 "errors parsing EDS resource: ["
924 "field:endpoints error:sum of locality weights for priority 0 "
925 "exceeds uint32 max]")
926 << decode_result.resource.status();
927 }
928
TEST_F(XdsEndpointTest,DuplicateAddresses)929 TEST_F(XdsEndpointTest, DuplicateAddresses) {
930 ClusterLoadAssignment cla;
931 cla.set_cluster_name("foo");
932 auto* locality = cla.add_endpoints();
933 locality->mutable_load_balancing_weight()->set_value(1);
934 auto* locality_name = locality->mutable_locality();
935 locality_name->set_region("myregion");
936 locality_name->set_zone("myzone");
937 locality_name->set_sub_zone("mysubzone");
938 auto* socket_address = locality->add_lb_endpoints()
939 ->mutable_endpoint()
940 ->mutable_address()
941 ->mutable_socket_address();
942 socket_address->set_address("127.0.0.1");
943 socket_address->set_port_value(443);
944 locality->set_priority(0);
945 locality = cla.add_endpoints();
946 locality->mutable_load_balancing_weight()->set_value(1);
947 locality_name = locality->mutable_locality();
948 locality_name->set_region("myregion2");
949 locality_name->set_zone("myzone");
950 locality_name->set_sub_zone("mysubzone");
951 socket_address = locality->add_lb_endpoints()
952 ->mutable_endpoint()
953 ->mutable_address()
954 ->mutable_socket_address();
955 socket_address->set_address("127.0.0.1");
956 socket_address->set_port_value(443);
957 locality->set_priority(0);
958 std::string serialized_resource;
959 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
960 auto* resource_type = XdsEndpointResourceType::Get();
961 auto decode_result =
962 resource_type->Decode(decode_context_, serialized_resource);
963 ASSERT_TRUE(decode_result.name.has_value());
964 EXPECT_EQ(*decode_result.name, "foo");
965 EXPECT_EQ(decode_result.resource.status().code(),
966 absl::StatusCode::kInvalidArgument);
967 EXPECT_EQ(decode_result.resource.status().message(),
968 "errors parsing EDS resource: ["
969 "field:endpoints[1].lb_endpoints[0] "
970 "error:duplicate endpoint address \"ipv4:127.0.0.1:443\"]")
971 << decode_result.resource.status();
972 }
973
TEST_F(XdsEndpointTest,DropConfig)974 TEST_F(XdsEndpointTest, DropConfig) {
975 ClusterLoadAssignment cla;
976 cla.set_cluster_name("foo");
977 auto* locality = cla.add_endpoints();
978 locality->mutable_load_balancing_weight()->set_value(1);
979 auto* locality_name = locality->mutable_locality();
980 locality_name->set_region("myregion");
981 locality_name->set_zone("myzone");
982 locality_name->set_sub_zone("mysubzone");
983 auto* socket_address = locality->add_lb_endpoints()
984 ->mutable_endpoint()
985 ->mutable_address()
986 ->mutable_socket_address();
987 socket_address->set_address("127.0.0.1");
988 socket_address->set_port_value(443);
989 auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
990 drop_overload->set_category("lb_drop");
991 drop_overload->mutable_drop_percentage()->set_numerator(50);
992 drop_overload = cla.mutable_policy()->add_drop_overloads();
993 drop_overload->set_category("lb_overload");
994 drop_overload->mutable_drop_percentage()->set_numerator(2500);
995 drop_overload->mutable_drop_percentage()->set_denominator(
996 envoy::type::v3::FractionalPercent::TEN_THOUSAND);
997 drop_overload = cla.mutable_policy()->add_drop_overloads();
998 drop_overload->set_category("why_not");
999 drop_overload->mutable_drop_percentage()->set_numerator(750000);
1000 drop_overload->mutable_drop_percentage()->set_denominator(
1001 envoy::type::v3::FractionalPercent::MILLION);
1002 std::string serialized_resource;
1003 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1004 auto* resource_type = XdsEndpointResourceType::Get();
1005 auto decode_result =
1006 resource_type->Decode(decode_context_, serialized_resource);
1007 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1008 ASSERT_TRUE(decode_result.name.has_value());
1009 EXPECT_EQ(*decode_result.name, "foo");
1010 auto& resource =
1011 static_cast<const XdsEndpointResource&>(**decode_result.resource);
1012 ASSERT_NE(resource.drop_config, nullptr);
1013 const auto& drop_list = resource.drop_config->drop_category_list();
1014 ASSERT_EQ(drop_list.size(), 3);
1015 EXPECT_EQ(drop_list[0].name, "lb_drop");
1016 EXPECT_EQ(drop_list[0].parts_per_million, 500000);
1017 EXPECT_EQ(drop_list[1].name, "lb_overload");
1018 EXPECT_EQ(drop_list[1].parts_per_million, 250000);
1019 EXPECT_EQ(drop_list[2].name, "why_not");
1020 EXPECT_EQ(drop_list[2].parts_per_million, 750000);
1021 }
1022
TEST_F(XdsEndpointTest,CapsDropPercentageAt100)1023 TEST_F(XdsEndpointTest, CapsDropPercentageAt100) {
1024 ClusterLoadAssignment cla;
1025 cla.set_cluster_name("foo");
1026 auto* locality = cla.add_endpoints();
1027 locality->mutable_load_balancing_weight()->set_value(1);
1028 auto* locality_name = locality->mutable_locality();
1029 locality_name->set_region("myregion");
1030 locality_name->set_zone("myzone");
1031 locality_name->set_sub_zone("mysubzone");
1032 auto* socket_address = locality->add_lb_endpoints()
1033 ->mutable_endpoint()
1034 ->mutable_address()
1035 ->mutable_socket_address();
1036 socket_address->set_address("127.0.0.1");
1037 socket_address->set_port_value(443);
1038 auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1039 drop_overload->set_category("lb_drop");
1040 drop_overload->mutable_drop_percentage()->set_numerator(10000001);
1041 std::string serialized_resource;
1042 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1043 auto* resource_type = XdsEndpointResourceType::Get();
1044 auto decode_result =
1045 resource_type->Decode(decode_context_, serialized_resource);
1046 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1047 ASSERT_TRUE(decode_result.name.has_value());
1048 EXPECT_EQ(*decode_result.name, "foo");
1049 auto& resource =
1050 static_cast<const XdsEndpointResource&>(**decode_result.resource);
1051 ASSERT_NE(resource.drop_config, nullptr);
1052 const auto& drop_list = resource.drop_config->drop_category_list();
1053 ASSERT_EQ(drop_list.size(), 1);
1054 EXPECT_EQ(drop_list[0].name, "lb_drop");
1055 EXPECT_EQ(drop_list[0].parts_per_million, 1000000);
1056 EXPECT_TRUE(resource.drop_config->drop_all());
1057 }
1058
TEST_F(XdsEndpointTest,MissingDropCategoryName)1059 TEST_F(XdsEndpointTest, MissingDropCategoryName) {
1060 ClusterLoadAssignment cla;
1061 cla.set_cluster_name("foo");
1062 auto* locality = cla.add_endpoints();
1063 locality->mutable_load_balancing_weight()->set_value(1);
1064 auto* locality_name = locality->mutable_locality();
1065 locality_name->set_region("myregion");
1066 locality_name->set_zone("myzone");
1067 locality_name->set_sub_zone("mysubzone");
1068 auto* socket_address = locality->add_lb_endpoints()
1069 ->mutable_endpoint()
1070 ->mutable_address()
1071 ->mutable_socket_address();
1072 socket_address->set_address("127.0.0.1");
1073 socket_address->set_port_value(443);
1074 auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1075 drop_overload->mutable_drop_percentage()->set_numerator(50);
1076 std::string serialized_resource;
1077 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1078 auto* resource_type = XdsEndpointResourceType::Get();
1079 auto decode_result =
1080 resource_type->Decode(decode_context_, serialized_resource);
1081 ASSERT_TRUE(decode_result.name.has_value());
1082 EXPECT_EQ(*decode_result.name, "foo");
1083 EXPECT_EQ(decode_result.resource.status().code(),
1084 absl::StatusCode::kInvalidArgument);
1085 EXPECT_EQ(decode_result.resource.status().message(),
1086 "errors parsing EDS resource: ["
1087 "field:policy.drop_overloads[0].category "
1088 "error:empty drop category name]")
1089 << decode_result.resource.status();
1090 }
1091
TEST_F(XdsEndpointTest,MissingDropPercentage)1092 TEST_F(XdsEndpointTest, MissingDropPercentage) {
1093 ClusterLoadAssignment cla;
1094 cla.set_cluster_name("foo");
1095 auto* locality = cla.add_endpoints();
1096 locality->mutable_load_balancing_weight()->set_value(1);
1097 auto* locality_name = locality->mutable_locality();
1098 locality_name->set_region("myregion");
1099 locality_name->set_zone("myzone");
1100 locality_name->set_sub_zone("mysubzone");
1101 auto* socket_address = locality->add_lb_endpoints()
1102 ->mutable_endpoint()
1103 ->mutable_address()
1104 ->mutable_socket_address();
1105 socket_address->set_address("127.0.0.1");
1106 socket_address->set_port_value(443);
1107 auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1108 drop_overload->set_category("lb_drop");
1109 std::string serialized_resource;
1110 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1111 auto* resource_type = XdsEndpointResourceType::Get();
1112 auto decode_result =
1113 resource_type->Decode(decode_context_, serialized_resource);
1114 ASSERT_TRUE(decode_result.name.has_value());
1115 EXPECT_EQ(*decode_result.name, "foo");
1116 EXPECT_EQ(decode_result.resource.status().code(),
1117 absl::StatusCode::kInvalidArgument);
1118 EXPECT_EQ(decode_result.resource.status().message(),
1119 "errors parsing EDS resource: ["
1120 "field:policy.drop_overloads[0].drop_percentage "
1121 "error:field not present]")
1122 << decode_result.resource.status();
1123 }
1124
TEST_F(XdsEndpointTest,DropPercentageInvalidDenominator)1125 TEST_F(XdsEndpointTest, DropPercentageInvalidDenominator) {
1126 ClusterLoadAssignment cla;
1127 cla.set_cluster_name("foo");
1128 auto* locality = cla.add_endpoints();
1129 locality->mutable_load_balancing_weight()->set_value(1);
1130 auto* locality_name = locality->mutable_locality();
1131 locality_name->set_region("myregion");
1132 locality_name->set_zone("myzone");
1133 locality_name->set_sub_zone("mysubzone");
1134 auto* socket_address = locality->add_lb_endpoints()
1135 ->mutable_endpoint()
1136 ->mutable_address()
1137 ->mutable_socket_address();
1138 socket_address->set_address("127.0.0.1");
1139 socket_address->set_port_value(443);
1140 auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1141 drop_overload->set_category("lb_drop");
1142 drop_overload->mutable_drop_percentage()->set_numerator(750000);
1143 drop_overload->mutable_drop_percentage()->set_denominator(
1144 static_cast<envoy::type::v3::FractionalPercent_DenominatorType>(100));
1145 std::string serialized_resource;
1146 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1147 auto* resource_type = XdsEndpointResourceType::Get();
1148 auto decode_result =
1149 resource_type->Decode(decode_context_, serialized_resource);
1150 ASSERT_TRUE(decode_result.name.has_value());
1151 EXPECT_EQ(*decode_result.name, "foo");
1152 EXPECT_EQ(decode_result.resource.status().code(),
1153 absl::StatusCode::kInvalidArgument);
1154 EXPECT_EQ(decode_result.resource.status().message(),
1155 "errors parsing EDS resource: ["
1156 "field:policy.drop_overloads[0].drop_percentage.denominator "
1157 "error:unknown denominator type]")
1158 << decode_result.resource.status();
1159 }
1160
TEST_F(XdsEndpointTest,EndpointHealthStatus)1161 TEST_F(XdsEndpointTest, EndpointHealthStatus) {
1162 ClusterLoadAssignment cla;
1163 cla.set_cluster_name("foo");
1164 auto* locality = cla.add_endpoints();
1165 locality->mutable_load_balancing_weight()->set_value(1);
1166 auto* locality_name = locality->mutable_locality();
1167 locality_name->set_region("myregion");
1168 locality_name->set_zone("myzone");
1169 locality_name->set_sub_zone("mysubzone");
1170 auto* endpoint = locality->add_lb_endpoints();
1171 auto* socket_address =
1172 endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
1173 socket_address->set_address("127.0.0.1");
1174 socket_address->set_port_value(443);
1175 endpoint = locality->add_lb_endpoints();
1176 endpoint->set_health_status(envoy::config::core::v3::HealthStatus::DRAINING);
1177 socket_address =
1178 endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
1179 socket_address->set_address("127.0.0.2");
1180 socket_address->set_port_value(443);
1181 endpoint = locality->add_lb_endpoints();
1182 endpoint->set_health_status(envoy::config::core::v3::HealthStatus::UNHEALTHY);
1183 socket_address =
1184 endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
1185 socket_address->set_address("127.0.0.3");
1186 socket_address->set_port_value(443);
1187 std::string serialized_resource;
1188 ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1189 auto* resource_type = XdsEndpointResourceType::Get();
1190 auto decode_result =
1191 resource_type->Decode(decode_context_, serialized_resource);
1192 ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1193 ASSERT_TRUE(decode_result.name.has_value());
1194 EXPECT_EQ(*decode_result.name, "foo");
1195 auto& resource =
1196 static_cast<const XdsEndpointResource&>(**decode_result.resource);
1197 ASSERT_EQ(resource.priorities.size(), 1);
1198 const auto& priority = resource.priorities[0];
1199 ASSERT_EQ(priority.localities.size(), 1);
1200 const auto& p = *priority.localities.begin();
1201 ASSERT_EQ(p.first, p.second.name.get());
1202 EXPECT_EQ(p.first->region(), "myregion");
1203 EXPECT_EQ(p.first->zone(), "myzone");
1204 EXPECT_EQ(p.first->sub_zone(), "mysubzone");
1205 EXPECT_EQ(p.second.lb_weight, 1);
1206 ASSERT_EQ(p.second.endpoints.size(), 2);
1207 const auto* address = &p.second.endpoints[0];
1208 auto addr = grpc_sockaddr_to_string(&address->address(), /*normalize=*/false);
1209 ASSERT_TRUE(addr.ok()) << addr.status();
1210 EXPECT_EQ(*addr, "127.0.0.1:443");
1211 EXPECT_EQ(address->args().GetInt(GRPC_ARG_XDS_HEALTH_STATUS),
1212 XdsHealthStatus::kUnknown);
1213 address = &p.second.endpoints[1];
1214 addr = grpc_sockaddr_to_string(&address->address(), /*normalize=*/false);
1215 ASSERT_TRUE(addr.ok()) << addr.status();
1216 EXPECT_EQ(*addr, "127.0.0.2:443");
1217 EXPECT_EQ(address->args().GetInt(GRPC_ARG_XDS_HEALTH_STATUS),
1218 XdsHealthStatus::kDraining);
1219 }
1220
1221 } // namespace
1222 } // namespace testing
1223 } // namespace grpc_core
1224
main(int argc,char ** argv)1225 int main(int argc, char** argv) {
1226 ::testing::InitGoogleTest(&argc, argv);
1227 grpc::testing::TestEnvironment env(&argc, argv);
1228 grpc_init();
1229 int ret = RUN_ALL_TESTS();
1230 grpc_shutdown();
1231 return ret;
1232 }
1233