• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <google/protobuf/wrappers.pb.h>
18 #include <grpc/grpc.h>
19 #include <stdint.h>
20 
21 #include <limits>
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 #include <vector>
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 "envoy/config/core/v3/address.pb.h"
33 #include "envoy/config/core/v3/base.pb.h"
34 #include "envoy/config/core/v3/health_check.pb.h"
35 #include "envoy/config/endpoint/v3/endpoint.pb.h"
36 #include "envoy/type/v3/percent.pb.h"
37 #include "gtest/gtest.h"
38 #include "src/core/lib/address_utils/sockaddr_utils.h"
39 #include "src/core/lib/channel/channel_args.h"
40 #include "src/core/lib/debug/trace.h"
41 #include "src/core/lib/iomgr/error.h"
42 #include "src/core/lib/iomgr/resolved_address.h"
43 #include "src/core/resolver/endpoint_addresses.h"
44 #include "src/core/util/crash.h"
45 #include "src/core/util/ref_counted_ptr.h"
46 #include "src/core/xds/grpc/xds_bootstrap_grpc.h"
47 #include "src/core/xds/grpc/xds_endpoint.h"
48 #include "src/core/xds/grpc/xds_endpoint_parser.h"
49 #include "src/core/xds/grpc/xds_health_status.h"
50 #include "src/core/xds/xds_client/xds_bootstrap.h"
51 #include "src/core/xds/xds_client/xds_client.h"
52 #include "src/core/xds/xds_client/xds_locality.h"
53 #include "src/core/xds/xds_client/xds_resource_type.h"
54 #include "test/core/test_util/scoped_env_var.h"
55 #include "test/core/test_util/test_config.h"
56 #include "upb/mem/arena.hpp"
57 #include "upb/reflection/def.hpp"
58 
59 using envoy::config::endpoint::v3::ClusterLoadAssignment;
60 
61 namespace grpc_core {
62 namespace testing {
63 namespace {
64 
65 class XdsEndpointTest : public ::testing::Test {
66  protected:
XdsEndpointTest()67   XdsEndpointTest()
68       : xds_client_(MakeXdsClient()),
69         decode_context_{
70             xds_client_.get(), *xds_client_->bootstrap().servers().front(),
71             &xds_unittest_trace, upb_def_pool_.ptr(), upb_arena_.ptr()} {}
72 
MakeXdsClient()73   static RefCountedPtr<XdsClient> MakeXdsClient() {
74     grpc_error_handle error;
75     auto bootstrap = GrpcXdsBootstrap::Create(
76         "{\n"
77         "  \"xds_servers\": [\n"
78         "    {\n"
79         "      \"server_uri\": \"xds.example.com\",\n"
80         "      \"channel_creds\": [\n"
81         "        {\"type\": \"google_default\"}\n"
82         "      ]\n"
83         "    }\n"
84         "  ]\n"
85         "}");
86     if (!bootstrap.ok()) {
87       Crash(absl::StrFormat("Error parsing bootstrap: %s",
88                             bootstrap.status().ToString().c_str()));
89     }
90     return MakeRefCounted<XdsClient>(std::move(*bootstrap),
91                                      /*transport_factory=*/nullptr,
92                                      /*event_engine=*/nullptr,
93                                      /*metrics_reporter=*/nullptr, "foo agent",
94                                      "foo version");
95   }
96 
97   RefCountedPtr<XdsClient> xds_client_;
98   upb::DefPool upb_def_pool_;
99   upb::Arena upb_arena_;
100   XdsResourceType::DecodeContext decode_context_;
101 };
102 
TEST_F(XdsEndpointTest,Definition)103 TEST_F(XdsEndpointTest, Definition) {
104   auto* resource_type = XdsEndpointResourceType::Get();
105   ASSERT_NE(resource_type, nullptr);
106   EXPECT_EQ(resource_type->type_url(),
107             "envoy.config.endpoint.v3.ClusterLoadAssignment");
108   EXPECT_FALSE(resource_type->AllResourcesRequiredInSotW());
109 }
110 
TEST_F(XdsEndpointTest,UnparsableProto)111 TEST_F(XdsEndpointTest, UnparsableProto) {
112   std::string serialized_resource("\0", 1);
113   auto* resource_type = XdsEndpointResourceType::Get();
114   auto decode_result =
115       resource_type->Decode(decode_context_, serialized_resource);
116   EXPECT_EQ(decode_result.resource.status().code(),
117             absl::StatusCode::kInvalidArgument);
118   EXPECT_EQ(decode_result.resource.status().message(),
119             "Can't parse ClusterLoadAssignment resource.")
120       << decode_result.resource.status();
121 }
122 
TEST_F(XdsEndpointTest,MinimumValidConfig)123 TEST_F(XdsEndpointTest, MinimumValidConfig) {
124   ClusterLoadAssignment cla;
125   cla.set_cluster_name("foo");
126   auto* locality = cla.add_endpoints();
127   locality->mutable_load_balancing_weight()->set_value(1);
128   auto* locality_name = locality->mutable_locality();
129   locality_name->set_region("myregion");
130   locality_name->set_zone("myzone");
131   locality_name->set_sub_zone("mysubzone");
132   auto* socket_address = locality->add_lb_endpoints()
133                              ->mutable_endpoint()
134                              ->mutable_address()
135                              ->mutable_socket_address();
136   socket_address->set_address("127.0.0.1");
137   socket_address->set_port_value(443);
138   std::string serialized_resource;
139   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
140   auto* resource_type = XdsEndpointResourceType::Get();
141   auto decode_result =
142       resource_type->Decode(decode_context_, serialized_resource);
143   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
144   ASSERT_TRUE(decode_result.name.has_value());
145   EXPECT_EQ(*decode_result.name, "foo");
146   auto& resource =
147       static_cast<const XdsEndpointResource&>(**decode_result.resource);
148   ASSERT_EQ(resource.priorities.size(), 1);
149   const auto& priority = resource.priorities[0];
150   ASSERT_EQ(priority.localities.size(), 1);
151   const auto& p = *priority.localities.begin();
152   ASSERT_EQ(p.first, p.second.name.get());
153   EXPECT_EQ(p.first->region(), "myregion");
154   EXPECT_EQ(p.first->zone(), "myzone");
155   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
156   EXPECT_EQ(p.second.lb_weight, 1);
157   ASSERT_EQ(p.second.endpoints.size(), 1);
158   const auto& address = p.second.endpoints.front();
159   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
160   ASSERT_TRUE(addr.ok()) << addr.status();
161   EXPECT_EQ(*addr, "127.0.0.1:443");
162   EXPECT_EQ(address.args(), ChannelArgs()
163                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
164                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
165                                      XdsHealthStatus::HealthStatus::kUnknown));
166   EXPECT_EQ(resource.drop_config, nullptr);
167 }
168 
TEST_F(XdsEndpointTest,EndpointWeight)169 TEST_F(XdsEndpointTest, EndpointWeight) {
170   ClusterLoadAssignment cla;
171   cla.set_cluster_name("foo");
172   auto* locality = cla.add_endpoints();
173   locality->mutable_load_balancing_weight()->set_value(1);
174   auto* locality_name = locality->mutable_locality();
175   locality_name->set_region("myregion");
176   locality_name->set_zone("myzone");
177   locality_name->set_sub_zone("mysubzone");
178   auto* endpoint = locality->add_lb_endpoints();
179   endpoint->mutable_load_balancing_weight()->set_value(3);
180   auto* socket_address =
181       endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
182   socket_address->set_address("127.0.0.1");
183   socket_address->set_port_value(443);
184   std::string serialized_resource;
185   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
186   auto* resource_type = XdsEndpointResourceType::Get();
187   auto decode_result =
188       resource_type->Decode(decode_context_, serialized_resource);
189   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
190   ASSERT_TRUE(decode_result.name.has_value());
191   EXPECT_EQ(*decode_result.name, "foo");
192   auto& resource =
193       static_cast<const XdsEndpointResource&>(**decode_result.resource);
194   ASSERT_EQ(resource.priorities.size(), 1);
195   const auto& priority = resource.priorities[0];
196   ASSERT_EQ(priority.localities.size(), 1);
197   const auto& p = *priority.localities.begin();
198   ASSERT_EQ(p.first, p.second.name.get());
199   EXPECT_EQ(p.first->region(), "myregion");
200   EXPECT_EQ(p.first->zone(), "myzone");
201   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
202   EXPECT_EQ(p.second.lb_weight, 1);
203   ASSERT_EQ(p.second.endpoints.size(), 1);
204   const auto& address = p.second.endpoints.front();
205   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
206   ASSERT_TRUE(addr.ok()) << addr.status();
207   EXPECT_EQ(*addr, "127.0.0.1:443");
208   EXPECT_EQ(address.args(), ChannelArgs()
209                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 3)
210                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
211                                      XdsHealthStatus::HealthStatus::kUnknown));
212   EXPECT_EQ(resource.drop_config, nullptr);
213 }
214 
TEST_F(XdsEndpointTest,IgnoresLocalityWithNoWeight)215 TEST_F(XdsEndpointTest, IgnoresLocalityWithNoWeight) {
216   ClusterLoadAssignment cla;
217   cla.set_cluster_name("foo");
218   auto* locality = cla.add_endpoints();
219   auto* locality_name = locality->mutable_locality();
220   locality_name->set_region("myregion");
221   locality_name->set_zone("myzone");
222   locality_name->set_sub_zone("mysubzone");
223   auto* socket_address = locality->add_lb_endpoints()
224                              ->mutable_endpoint()
225                              ->mutable_address()
226                              ->mutable_socket_address();
227   socket_address->set_address("127.0.0.1");
228   socket_address->set_port_value(443);
229   locality = cla.add_endpoints();
230   *locality = cla.endpoints(0);
231   locality->mutable_load_balancing_weight()->set_value(1);
232   std::string serialized_resource;
233   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
234   auto* resource_type = XdsEndpointResourceType::Get();
235   auto decode_result =
236       resource_type->Decode(decode_context_, serialized_resource);
237   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
238   ASSERT_TRUE(decode_result.name.has_value());
239   EXPECT_EQ(*decode_result.name, "foo");
240   auto& resource =
241       static_cast<const XdsEndpointResource&>(**decode_result.resource);
242   ASSERT_EQ(resource.priorities.size(), 1);
243   const auto& priority = resource.priorities[0];
244   ASSERT_EQ(priority.localities.size(), 1);
245   const auto& p = *priority.localities.begin();
246   ASSERT_EQ(p.first, p.second.name.get());
247   EXPECT_EQ(p.first->region(), "myregion");
248   EXPECT_EQ(p.first->zone(), "myzone");
249   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
250   EXPECT_EQ(p.second.lb_weight, 1);
251   ASSERT_EQ(p.second.endpoints.size(), 1);
252   const auto& address = p.second.endpoints.front();
253   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
254   ASSERT_TRUE(addr.ok()) << addr.status();
255   EXPECT_EQ(*addr, "127.0.0.1:443");
256   EXPECT_EQ(address.args(), ChannelArgs()
257                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
258                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
259                                      XdsHealthStatus::HealthStatus::kUnknown));
260   EXPECT_EQ(resource.drop_config, nullptr);
261 }
262 
TEST_F(XdsEndpointTest,IgnoresLocalityWithZeroWeight)263 TEST_F(XdsEndpointTest, IgnoresLocalityWithZeroWeight) {
264   ClusterLoadAssignment cla;
265   cla.set_cluster_name("foo");
266   auto* locality = cla.add_endpoints();
267   locality->mutable_load_balancing_weight()->set_value(0);
268   auto* locality_name = locality->mutable_locality();
269   locality_name->set_region("myregion");
270   locality_name->set_zone("myzone");
271   locality_name->set_sub_zone("mysubzone");
272   auto* socket_address = locality->add_lb_endpoints()
273                              ->mutable_endpoint()
274                              ->mutable_address()
275                              ->mutable_socket_address();
276   socket_address->set_address("127.0.0.1");
277   socket_address->set_port_value(443);
278   locality = cla.add_endpoints();
279   *locality = cla.endpoints(0);
280   locality->mutable_load_balancing_weight()->set_value(1);
281   std::string serialized_resource;
282   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
283   auto* resource_type = XdsEndpointResourceType::Get();
284   auto decode_result =
285       resource_type->Decode(decode_context_, serialized_resource);
286   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
287   ASSERT_TRUE(decode_result.name.has_value());
288   EXPECT_EQ(*decode_result.name, "foo");
289   auto& resource =
290       static_cast<const XdsEndpointResource&>(**decode_result.resource);
291   ASSERT_EQ(resource.priorities.size(), 1);
292   const auto& priority = resource.priorities[0];
293   ASSERT_EQ(priority.localities.size(), 1);
294   const auto& p = *priority.localities.begin();
295   ASSERT_EQ(p.first, p.second.name.get());
296   EXPECT_EQ(p.first->region(), "myregion");
297   EXPECT_EQ(p.first->zone(), "myzone");
298   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
299   EXPECT_EQ(p.second.lb_weight, 1);
300   ASSERT_EQ(p.second.endpoints.size(), 1);
301   const auto& address = p.second.endpoints.front();
302   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
303   ASSERT_TRUE(addr.ok()) << addr.status();
304   EXPECT_EQ(*addr, "127.0.0.1:443");
305   EXPECT_EQ(address.args(), ChannelArgs()
306                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
307                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
308                                      XdsHealthStatus::HealthStatus::kUnknown));
309   EXPECT_EQ(resource.drop_config, nullptr);
310 }
311 
TEST_F(XdsEndpointTest,LocalityWithNoEndpoints)312 TEST_F(XdsEndpointTest, LocalityWithNoEndpoints) {
313   ClusterLoadAssignment cla;
314   cla.set_cluster_name("foo");
315   auto* locality = cla.add_endpoints();
316   locality->mutable_load_balancing_weight()->set_value(1);
317   auto* locality_name = locality->mutable_locality();
318   locality_name->set_region("myregion");
319   locality_name->set_zone("myzone");
320   locality_name->set_sub_zone("mysubzone");
321   std::string serialized_resource;
322   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
323   auto* resource_type = XdsEndpointResourceType::Get();
324   auto decode_result =
325       resource_type->Decode(decode_context_, serialized_resource);
326   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
327   ASSERT_TRUE(decode_result.name.has_value());
328   EXPECT_EQ(*decode_result.name, "foo");
329   auto& resource =
330       static_cast<const XdsEndpointResource&>(**decode_result.resource);
331   ASSERT_EQ(resource.priorities.size(), 1);
332   const auto& priority = resource.priorities[0];
333   ASSERT_EQ(priority.localities.size(), 1);
334   const auto& p = *priority.localities.begin();
335   ASSERT_EQ(p.first, p.second.name.get());
336   EXPECT_EQ(p.first->region(), "myregion");
337   EXPECT_EQ(p.first->zone(), "myzone");
338   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
339   EXPECT_EQ(p.second.lb_weight, 1);
340   EXPECT_EQ(p.second.endpoints.size(), 0);
341   EXPECT_EQ(resource.drop_config, nullptr);
342 }
343 
TEST_F(XdsEndpointTest,NoLocality)344 TEST_F(XdsEndpointTest, NoLocality) {
345   ClusterLoadAssignment cla;
346   cla.set_cluster_name("foo");
347   auto* locality = cla.add_endpoints();
348   locality->mutable_load_balancing_weight()->set_value(1);
349   auto* socket_address = locality->add_lb_endpoints()
350                              ->mutable_endpoint()
351                              ->mutable_address()
352                              ->mutable_socket_address();
353   socket_address->set_address("127.0.0.1");
354   socket_address->set_port_value(443);
355   std::string serialized_resource;
356   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
357   auto* resource_type = XdsEndpointResourceType::Get();
358   auto decode_result =
359       resource_type->Decode(decode_context_, serialized_resource);
360   ASSERT_TRUE(decode_result.name.has_value());
361   EXPECT_EQ(*decode_result.name, "foo");
362   EXPECT_EQ(decode_result.resource.status().code(),
363             absl::StatusCode::kInvalidArgument);
364   EXPECT_EQ(decode_result.resource.status().message(),
365             "errors parsing EDS resource: ["
366             "field:endpoints[0].locality error:field not present]")
367       << decode_result.resource.status();
368 }
369 
TEST_F(XdsEndpointTest,InvalidPort)370 TEST_F(XdsEndpointTest, InvalidPort) {
371   ClusterLoadAssignment cla;
372   cla.set_cluster_name("foo");
373   auto* locality = cla.add_endpoints();
374   locality->mutable_load_balancing_weight()->set_value(1);
375   auto* locality_name = locality->mutable_locality();
376   locality_name->set_region("myregion");
377   locality_name->set_zone("myzone");
378   locality_name->set_sub_zone("mysubzone");
379   auto* socket_address = locality->add_lb_endpoints()
380                              ->mutable_endpoint()
381                              ->mutable_address()
382                              ->mutable_socket_address();
383   socket_address->set_address("127.0.0.1");
384   socket_address->set_port_value(65537);
385   std::string serialized_resource;
386   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
387   auto* resource_type = XdsEndpointResourceType::Get();
388   auto decode_result =
389       resource_type->Decode(decode_context_, serialized_resource);
390   ASSERT_TRUE(decode_result.name.has_value());
391   EXPECT_EQ(*decode_result.name, "foo");
392   EXPECT_EQ(decode_result.resource.status().code(),
393             absl::StatusCode::kInvalidArgument);
394   EXPECT_EQ(decode_result.resource.status().message(),
395             "errors parsing EDS resource: ["
396             "field:endpoints[0].lb_endpoints[0].endpoint.address"
397             ".socket_address.port_value error:invalid port]")
398       << decode_result.resource.status();
399 }
400 
TEST_F(XdsEndpointTest,InvalidAddress)401 TEST_F(XdsEndpointTest, InvalidAddress) {
402   ClusterLoadAssignment cla;
403   cla.set_cluster_name("foo");
404   auto* locality = cla.add_endpoints();
405   locality->mutable_load_balancing_weight()->set_value(1);
406   auto* locality_name = locality->mutable_locality();
407   locality_name->set_region("myregion");
408   locality_name->set_zone("myzone");
409   locality_name->set_sub_zone("mysubzone");
410   auto* socket_address = locality->add_lb_endpoints()
411                              ->mutable_endpoint()
412                              ->mutable_address()
413                              ->mutable_socket_address();
414   socket_address->set_address("not_an_ip_address");
415   socket_address->set_port_value(443);
416   std::string serialized_resource;
417   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
418   auto* resource_type = XdsEndpointResourceType::Get();
419   auto decode_result =
420       resource_type->Decode(decode_context_, serialized_resource);
421   ASSERT_TRUE(decode_result.name.has_value());
422   EXPECT_EQ(*decode_result.name, "foo");
423   EXPECT_EQ(decode_result.resource.status().code(),
424             absl::StatusCode::kInvalidArgument);
425   EXPECT_EQ(decode_result.resource.status().message(),
426             "errors parsing EDS resource: ["
427             "field:endpoints[0].lb_endpoints[0].endpoint.address"
428             ".socket_address error:"
429             "Failed to parse address:not_an_ip_address:443]")
430       << decode_result.resource.status();
431 }
432 
TEST_F(XdsEndpointTest,MissingSocketAddress)433 TEST_F(XdsEndpointTest, MissingSocketAddress) {
434   ClusterLoadAssignment cla;
435   cla.set_cluster_name("foo");
436   auto* locality = cla.add_endpoints();
437   locality->mutable_load_balancing_weight()->set_value(1);
438   auto* locality_name = locality->mutable_locality();
439   locality_name->set_region("myregion");
440   locality_name->set_zone("myzone");
441   locality_name->set_sub_zone("mysubzone");
442   locality->add_lb_endpoints()->mutable_endpoint()->mutable_address();
443   std::string serialized_resource;
444   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
445   auto* resource_type = XdsEndpointResourceType::Get();
446   auto decode_result =
447       resource_type->Decode(decode_context_, serialized_resource);
448   ASSERT_TRUE(decode_result.name.has_value());
449   EXPECT_EQ(*decode_result.name, "foo");
450   EXPECT_EQ(decode_result.resource.status().code(),
451             absl::StatusCode::kInvalidArgument);
452   EXPECT_EQ(decode_result.resource.status().message(),
453             "errors parsing EDS resource: ["
454             "field:endpoints[0].lb_endpoints[0].endpoint.address"
455             ".socket_address error:field not present]")
456       << decode_result.resource.status();
457 }
458 
TEST_F(XdsEndpointTest,MissingAddress)459 TEST_F(XdsEndpointTest, MissingAddress) {
460   ClusterLoadAssignment cla;
461   cla.set_cluster_name("foo");
462   auto* locality = cla.add_endpoints();
463   locality->mutable_load_balancing_weight()->set_value(1);
464   auto* locality_name = locality->mutable_locality();
465   locality_name->set_region("myregion");
466   locality_name->set_zone("myzone");
467   locality_name->set_sub_zone("mysubzone");
468   locality->add_lb_endpoints()->mutable_endpoint();
469   std::string serialized_resource;
470   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
471   auto* resource_type = XdsEndpointResourceType::Get();
472   auto decode_result =
473       resource_type->Decode(decode_context_, serialized_resource);
474   ASSERT_TRUE(decode_result.name.has_value());
475   EXPECT_EQ(*decode_result.name, "foo");
476   EXPECT_EQ(decode_result.resource.status().code(),
477             absl::StatusCode::kInvalidArgument);
478   EXPECT_EQ(decode_result.resource.status().message(),
479             "errors parsing EDS resource: ["
480             "field:endpoints[0].lb_endpoints[0].endpoint.address "
481             "error:field not present]")
482       << decode_result.resource.status();
483 }
484 
TEST_F(XdsEndpointTest,MultipleAddressesPerEndpoint)485 TEST_F(XdsEndpointTest, MultipleAddressesPerEndpoint) {
486   ClusterLoadAssignment cla;
487   cla.set_cluster_name("foo");
488   auto* locality = cla.add_endpoints();
489   locality->mutable_load_balancing_weight()->set_value(1);
490   auto* locality_name = locality->mutable_locality();
491   locality_name->set_region("myregion");
492   locality_name->set_zone("myzone");
493   locality_name->set_sub_zone("mysubzone");
494   auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
495   auto* socket_address = ep->mutable_address()->mutable_socket_address();
496   socket_address->set_address("127.0.0.1");
497   socket_address->set_port_value(443);
498   socket_address = ep->add_additional_addresses()
499                        ->mutable_address()
500                        ->mutable_socket_address();
501   socket_address->set_address("127.0.0.1");
502   socket_address->set_port_value(444);
503   std::string serialized_resource;
504   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
505   auto* resource_type = XdsEndpointResourceType::Get();
506   auto decode_result =
507       resource_type->Decode(decode_context_, serialized_resource);
508   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
509   ASSERT_TRUE(decode_result.name.has_value());
510   EXPECT_EQ(*decode_result.name, "foo");
511   auto& resource =
512       static_cast<const XdsEndpointResource&>(**decode_result.resource);
513   ASSERT_EQ(resource.priorities.size(), 1);
514   const auto& priority = resource.priorities[0];
515   ASSERT_EQ(priority.localities.size(), 1);
516   const auto& p = *priority.localities.begin();
517   ASSERT_EQ(p.first, p.second.name.get());
518   EXPECT_EQ(p.first->region(), "myregion");
519   EXPECT_EQ(p.first->zone(), "myzone");
520   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
521   EXPECT_EQ(p.second.lb_weight, 1);
522   ASSERT_EQ(p.second.endpoints.size(), 1);
523   const auto& endpoint = p.second.endpoints.front();
524   ASSERT_EQ(endpoint.addresses().size(), 2);
525   auto addr =
526       grpc_sockaddr_to_string(&endpoint.addresses()[0], /*normalize=*/false);
527   ASSERT_TRUE(addr.ok()) << addr.status();
528   EXPECT_EQ(*addr, "127.0.0.1:443");
529   addr = grpc_sockaddr_to_string(&endpoint.addresses()[1], /*normalize=*/false);
530   ASSERT_TRUE(addr.ok()) << addr.status();
531   EXPECT_EQ(*addr, "127.0.0.1:444");
532   EXPECT_EQ(endpoint.args(), ChannelArgs()
533                                  .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
534                                  .Set(GRPC_ARG_XDS_HEALTH_STATUS,
535                                       XdsHealthStatus::HealthStatus::kUnknown));
536   EXPECT_EQ(resource.drop_config, nullptr);
537 }
538 
TEST_F(XdsEndpointTest,AdditionalAddressesMissingAddress)539 TEST_F(XdsEndpointTest, AdditionalAddressesMissingAddress) {
540   ClusterLoadAssignment cla;
541   cla.set_cluster_name("foo");
542   auto* locality = cla.add_endpoints();
543   locality->mutable_load_balancing_weight()->set_value(1);
544   auto* locality_name = locality->mutable_locality();
545   locality_name->set_region("myregion");
546   locality_name->set_zone("myzone");
547   locality_name->set_sub_zone("mysubzone");
548   auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
549   auto* socket_address = ep->mutable_address()->mutable_socket_address();
550   socket_address->set_address("127.0.0.1");
551   socket_address->set_port_value(443);
552   ep->add_additional_addresses();
553   std::string serialized_resource;
554   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
555   auto* resource_type = XdsEndpointResourceType::Get();
556   auto decode_result =
557       resource_type->Decode(decode_context_, serialized_resource);
558   ASSERT_TRUE(decode_result.name.has_value());
559   EXPECT_EQ(*decode_result.name, "foo");
560   EXPECT_EQ(decode_result.resource.status().code(),
561             absl::StatusCode::kInvalidArgument);
562   EXPECT_EQ(decode_result.resource.status().message(),
563             "errors parsing EDS resource: ["
564             "field:endpoints[0].lb_endpoints[0].endpoint"
565             ".additional_addresses[0].address error:field not present]")
566       << decode_result.resource.status();
567 }
568 
TEST_F(XdsEndpointTest,AdditionalAddressesMissingSocketAddress)569 TEST_F(XdsEndpointTest, AdditionalAddressesMissingSocketAddress) {
570   ClusterLoadAssignment cla;
571   cla.set_cluster_name("foo");
572   auto* locality = cla.add_endpoints();
573   locality->mutable_load_balancing_weight()->set_value(1);
574   auto* locality_name = locality->mutable_locality();
575   locality_name->set_region("myregion");
576   locality_name->set_zone("myzone");
577   locality_name->set_sub_zone("mysubzone");
578   auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
579   auto* socket_address = ep->mutable_address()->mutable_socket_address();
580   socket_address->set_address("127.0.0.1");
581   socket_address->set_port_value(443);
582   ep->add_additional_addresses()->mutable_address();
583   std::string serialized_resource;
584   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
585   auto* resource_type = XdsEndpointResourceType::Get();
586   auto decode_result =
587       resource_type->Decode(decode_context_, serialized_resource);
588   ASSERT_TRUE(decode_result.name.has_value());
589   EXPECT_EQ(*decode_result.name, "foo");
590   EXPECT_EQ(decode_result.resource.status().code(),
591             absl::StatusCode::kInvalidArgument);
592   EXPECT_EQ(decode_result.resource.status().message(),
593             "errors parsing EDS resource: ["
594             "field:endpoints[0].lb_endpoints[0].endpoint"
595             ".additional_addresses[0].address.socket_address "
596             "error:field not present]")
597       << decode_result.resource.status();
598 }
599 
TEST_F(XdsEndpointTest,AdditionalAddressesInvalidPort)600 TEST_F(XdsEndpointTest, AdditionalAddressesInvalidPort) {
601   ClusterLoadAssignment cla;
602   cla.set_cluster_name("foo");
603   auto* locality = cla.add_endpoints();
604   locality->mutable_load_balancing_weight()->set_value(1);
605   auto* locality_name = locality->mutable_locality();
606   locality_name->set_region("myregion");
607   locality_name->set_zone("myzone");
608   locality_name->set_sub_zone("mysubzone");
609   auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
610   auto* socket_address = ep->mutable_address()->mutable_socket_address();
611   socket_address->set_address("127.0.0.1");
612   socket_address->set_port_value(443);
613   socket_address = ep->add_additional_addresses()
614                        ->mutable_address()
615                        ->mutable_socket_address();
616   socket_address->set_address("127.0.0.1");
617   socket_address->set_port_value(65537);
618   std::string serialized_resource;
619   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
620   auto* resource_type = XdsEndpointResourceType::Get();
621   auto decode_result =
622       resource_type->Decode(decode_context_, serialized_resource);
623   ASSERT_TRUE(decode_result.name.has_value());
624   EXPECT_EQ(*decode_result.name, "foo");
625   EXPECT_EQ(decode_result.resource.status().code(),
626             absl::StatusCode::kInvalidArgument);
627   EXPECT_EQ(decode_result.resource.status().message(),
628             "errors parsing EDS resource: ["
629             "field:endpoints[0].lb_endpoints[0].endpoint"
630             ".additional_addresses[0].address.socket_address.port_value "
631             "error:invalid port]")
632       << decode_result.resource.status();
633 }
634 
TEST_F(XdsEndpointTest,AdditionalAddressesInvalidAddress)635 TEST_F(XdsEndpointTest, AdditionalAddressesInvalidAddress) {
636   ClusterLoadAssignment cla;
637   cla.set_cluster_name("foo");
638   auto* locality = cla.add_endpoints();
639   locality->mutable_load_balancing_weight()->set_value(1);
640   auto* locality_name = locality->mutable_locality();
641   locality_name->set_region("myregion");
642   locality_name->set_zone("myzone");
643   locality_name->set_sub_zone("mysubzone");
644   auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
645   auto* socket_address = ep->mutable_address()->mutable_socket_address();
646   socket_address->set_address("127.0.0.1");
647   socket_address->set_port_value(443);
648   socket_address = ep->add_additional_addresses()
649                        ->mutable_address()
650                        ->mutable_socket_address();
651   socket_address->set_address("not_an_ip_address");
652   socket_address->set_port_value(444);
653   std::string serialized_resource;
654   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
655   auto* resource_type = XdsEndpointResourceType::Get();
656   auto decode_result =
657       resource_type->Decode(decode_context_, serialized_resource);
658   ASSERT_TRUE(decode_result.name.has_value());
659   EXPECT_EQ(*decode_result.name, "foo");
660   EXPECT_EQ(decode_result.resource.status().code(),
661             absl::StatusCode::kInvalidArgument);
662   EXPECT_EQ(decode_result.resource.status().message(),
663             "errors parsing EDS resource: ["
664             "field:endpoints[0].lb_endpoints[0].endpoint"
665             ".additional_addresses[0].address.socket_address error:"
666             "Failed to parse address:not_an_ip_address:444]")
667       << decode_result.resource.status();
668 }
669 
TEST_F(XdsEndpointTest,IgnoresMultipleAddressesPerEndpointWhenDisabled)670 TEST_F(XdsEndpointTest, IgnoresMultipleAddressesPerEndpointWhenDisabled) {
671   testing::ScopedEnvVar env("GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS",
672                             "false");
673   ClusterLoadAssignment cla;
674   cla.set_cluster_name("foo");
675   auto* locality = cla.add_endpoints();
676   locality->mutable_load_balancing_weight()->set_value(1);
677   auto* locality_name = locality->mutable_locality();
678   locality_name->set_region("myregion");
679   locality_name->set_zone("myzone");
680   locality_name->set_sub_zone("mysubzone");
681   auto* ep = locality->add_lb_endpoints()->mutable_endpoint();
682   auto* socket_address = ep->mutable_address()->mutable_socket_address();
683   socket_address->set_address("127.0.0.1");
684   socket_address->set_port_value(443);
685   socket_address = ep->add_additional_addresses()
686                        ->mutable_address()
687                        ->mutable_socket_address();
688   socket_address->set_address("127.0.0.1");
689   socket_address->set_port_value(444);
690   std::string serialized_resource;
691   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
692   auto* resource_type = XdsEndpointResourceType::Get();
693   auto decode_result =
694       resource_type->Decode(decode_context_, serialized_resource);
695   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
696   ASSERT_TRUE(decode_result.name.has_value());
697   EXPECT_EQ(*decode_result.name, "foo");
698   auto& resource =
699       static_cast<const XdsEndpointResource&>(**decode_result.resource);
700   ASSERT_EQ(resource.priorities.size(), 1);
701   const auto& priority = resource.priorities[0];
702   ASSERT_EQ(priority.localities.size(), 1);
703   const auto& p = *priority.localities.begin();
704   ASSERT_EQ(p.first, p.second.name.get());
705   EXPECT_EQ(p.first->region(), "myregion");
706   EXPECT_EQ(p.first->zone(), "myzone");
707   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
708   EXPECT_EQ(p.second.lb_weight, 1);
709   ASSERT_EQ(p.second.endpoints.size(), 1);
710   const auto& endpoint = p.second.endpoints.front();
711   ASSERT_EQ(endpoint.addresses().size(), 1);
712   auto addr =
713       grpc_sockaddr_to_string(&endpoint.addresses()[0], /*normalize=*/false);
714   ASSERT_TRUE(addr.ok()) << addr.status();
715   EXPECT_EQ(*addr, "127.0.0.1:443");
716   EXPECT_EQ(endpoint.args(), ChannelArgs()
717                                  .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
718                                  .Set(GRPC_ARG_XDS_HEALTH_STATUS,
719                                       XdsHealthStatus::HealthStatus::kUnknown));
720   EXPECT_EQ(resource.drop_config, nullptr);
721 }
722 
TEST_F(XdsEndpointTest,EndpointHostname)723 TEST_F(XdsEndpointTest, EndpointHostname) {
724   ClusterLoadAssignment cla;
725   cla.set_cluster_name("foo");
726   auto* locality = cla.add_endpoints();
727   locality->mutable_load_balancing_weight()->set_value(1);
728   auto* locality_name = locality->mutable_locality();
729   locality_name->set_region("myregion");
730   locality_name->set_zone("myzone");
731   locality_name->set_sub_zone("mysubzone");
732   auto* endpoint = locality->add_lb_endpoints()->mutable_endpoint();
733   endpoint->set_hostname("server.example.com");
734   auto* socket_address = endpoint->mutable_address()->mutable_socket_address();
735   socket_address->set_address("127.0.0.1");
736   socket_address->set_port_value(443);
737   std::string serialized_resource;
738   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
739   auto* resource_type = XdsEndpointResourceType::Get();
740   auto decode_result =
741       resource_type->Decode(decode_context_, serialized_resource);
742   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
743   ASSERT_TRUE(decode_result.name.has_value());
744   EXPECT_EQ(*decode_result.name, "foo");
745   auto& resource =
746       static_cast<const XdsEndpointResource&>(**decode_result.resource);
747   ASSERT_EQ(resource.priorities.size(), 1);
748   const auto& priority = resource.priorities[0];
749   ASSERT_EQ(priority.localities.size(), 1);
750   const auto& p = *priority.localities.begin();
751   ASSERT_EQ(p.first, p.second.name.get());
752   EXPECT_EQ(p.first->region(), "myregion");
753   EXPECT_EQ(p.first->zone(), "myzone");
754   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
755   EXPECT_EQ(p.second.lb_weight, 1);
756   ASSERT_EQ(p.second.endpoints.size(), 1);
757   const auto& address = p.second.endpoints.front();
758   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
759   ASSERT_TRUE(addr.ok()) << addr.status();
760   EXPECT_EQ(*addr, "127.0.0.1:443");
761   EXPECT_EQ(address.args(),
762             ChannelArgs()
763                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
764                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
765                      XdsHealthStatus::HealthStatus::kUnknown)
766                 .Set(GRPC_ARG_ADDRESS_NAME, "server.example.com"));
767   EXPECT_EQ(resource.drop_config, nullptr);
768 }
769 
TEST_F(XdsEndpointTest,MissingEndpoint)770 TEST_F(XdsEndpointTest, MissingEndpoint) {
771   ClusterLoadAssignment cla;
772   cla.set_cluster_name("foo");
773   auto* locality = cla.add_endpoints();
774   locality->mutable_load_balancing_weight()->set_value(1);
775   auto* locality_name = locality->mutable_locality();
776   locality_name->set_region("myregion");
777   locality_name->set_zone("myzone");
778   locality_name->set_sub_zone("mysubzone");
779   locality->add_lb_endpoints();
780   std::string serialized_resource;
781   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
782   auto* resource_type = XdsEndpointResourceType::Get();
783   auto decode_result =
784       resource_type->Decode(decode_context_, serialized_resource);
785   ASSERT_TRUE(decode_result.name.has_value());
786   EXPECT_EQ(*decode_result.name, "foo");
787   EXPECT_EQ(decode_result.resource.status().code(),
788             absl::StatusCode::kInvalidArgument);
789   EXPECT_EQ(decode_result.resource.status().message(),
790             "errors parsing EDS resource: ["
791             "field:endpoints[0].lb_endpoints[0].endpoint "
792             "error:field not present]")
793       << decode_result.resource.status();
794 }
795 
TEST_F(XdsEndpointTest,EndpointWeightZero)796 TEST_F(XdsEndpointTest, EndpointWeightZero) {
797   ClusterLoadAssignment cla;
798   cla.set_cluster_name("foo");
799   auto* locality = cla.add_endpoints();
800   locality->mutable_load_balancing_weight()->set_value(1);
801   auto* locality_name = locality->mutable_locality();
802   locality_name->set_region("myregion");
803   locality_name->set_zone("myzone");
804   locality_name->set_sub_zone("mysubzone");
805   auto* endpoint = locality->add_lb_endpoints();
806   endpoint->mutable_load_balancing_weight()->set_value(0);
807   auto* socket_address =
808       endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
809   socket_address->set_address("127.0.0.1");
810   socket_address->set_port_value(443);
811   std::string serialized_resource;
812   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
813   auto* resource_type = XdsEndpointResourceType::Get();
814   auto decode_result =
815       resource_type->Decode(decode_context_, serialized_resource);
816   ASSERT_TRUE(decode_result.name.has_value());
817   EXPECT_EQ(*decode_result.name, "foo");
818   EXPECT_EQ(decode_result.resource.status().code(),
819             absl::StatusCode::kInvalidArgument);
820   EXPECT_EQ(decode_result.resource.status().message(),
821             "errors parsing EDS resource: ["
822             "field:endpoints[0].lb_endpoints[0].load_balancing_weight "
823             "error:must be greater than 0]")
824       << decode_result.resource.status();
825 }
826 
TEST_F(XdsEndpointTest,DuplicateLocalityName)827 TEST_F(XdsEndpointTest, DuplicateLocalityName) {
828   ClusterLoadAssignment cla;
829   cla.set_cluster_name("foo");
830   auto* locality = cla.add_endpoints();
831   locality->mutable_load_balancing_weight()->set_value(1);
832   auto* locality_name = locality->mutable_locality();
833   locality_name->set_region("myregion");
834   locality_name->set_zone("myzone");
835   locality_name->set_sub_zone("mysubzone");
836   auto* socket_address = locality->add_lb_endpoints()
837                              ->mutable_endpoint()
838                              ->mutable_address()
839                              ->mutable_socket_address();
840   socket_address->set_address("127.0.0.1");
841   socket_address->set_port_value(443);
842   locality = cla.add_endpoints();
843   locality->mutable_load_balancing_weight()->set_value(1);
844   locality_name = locality->mutable_locality();
845   locality_name->set_region("myregion");
846   locality_name->set_zone("myzone");
847   locality_name->set_sub_zone("mysubzone");
848   socket_address = locality->add_lb_endpoints()
849                        ->mutable_endpoint()
850                        ->mutable_address()
851                        ->mutable_socket_address();
852   socket_address->set_address("127.0.0.2");
853   socket_address->set_port_value(443);
854   std::string serialized_resource;
855   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
856   auto* resource_type = XdsEndpointResourceType::Get();
857   auto decode_result =
858       resource_type->Decode(decode_context_, serialized_resource);
859   ASSERT_TRUE(decode_result.name.has_value());
860   EXPECT_EQ(*decode_result.name, "foo");
861   EXPECT_EQ(decode_result.resource.status().code(),
862             absl::StatusCode::kInvalidArgument);
863   EXPECT_EQ(decode_result.resource.status().message(),
864             "errors parsing EDS resource: ["
865             "field:endpoints[1] error:duplicate locality {region=\"myregion\", "
866             "zone=\"myzone\", sub_zone=\"mysubzone\"} found in priority 0]")
867       << decode_result.resource.status();
868 }
869 
TEST_F(XdsEndpointTest,SparsePriorityList)870 TEST_F(XdsEndpointTest, SparsePriorityList) {
871   ClusterLoadAssignment cla;
872   cla.set_cluster_name("foo");
873   auto* locality = cla.add_endpoints();
874   locality->mutable_load_balancing_weight()->set_value(1);
875   auto* locality_name = locality->mutable_locality();
876   locality_name->set_region("myregion");
877   locality_name->set_zone("myzone");
878   locality_name->set_sub_zone("mysubzone");
879   auto* socket_address = locality->add_lb_endpoints()
880                              ->mutable_endpoint()
881                              ->mutable_address()
882                              ->mutable_socket_address();
883   socket_address->set_address("127.0.0.1");
884   socket_address->set_port_value(443);
885   locality->set_priority(1);
886   locality = cla.add_endpoints();
887   locality->mutable_load_balancing_weight()->set_value(1);
888   locality_name = locality->mutable_locality();
889   locality_name->set_region("myregion2");
890   locality_name->set_zone("myzone");
891   locality_name->set_sub_zone("mysubzone");
892   socket_address = locality->add_lb_endpoints()
893                        ->mutable_endpoint()
894                        ->mutable_address()
895                        ->mutable_socket_address();
896   socket_address->set_address("127.0.0.2");
897   socket_address->set_port_value(443);
898   locality->set_priority(3);
899   std::string serialized_resource;
900   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
901   auto* resource_type = XdsEndpointResourceType::Get();
902   auto decode_result =
903       resource_type->Decode(decode_context_, serialized_resource);
904   ASSERT_TRUE(decode_result.name.has_value());
905   EXPECT_EQ(*decode_result.name, "foo");
906   EXPECT_EQ(decode_result.resource.status().code(),
907             absl::StatusCode::kInvalidArgument);
908   EXPECT_EQ(decode_result.resource.status().message(),
909             "errors parsing EDS resource: ["
910             "field:endpoints errors:[priority 0 empty; priority 2 empty]]")
911       << decode_result.resource.status();
912 }
913 
TEST_F(XdsEndpointTest,LocalityWeightsWithinPriorityExceedUint32Max)914 TEST_F(XdsEndpointTest, LocalityWeightsWithinPriorityExceedUint32Max) {
915   ClusterLoadAssignment cla;
916   cla.set_cluster_name("foo");
917   // First locality has weight of 1.
918   auto* locality = cla.add_endpoints();
919   locality->mutable_load_balancing_weight()->set_value(1);
920   auto* locality_name = locality->mutable_locality();
921   locality_name->set_region("myregion");
922   locality_name->set_zone("myzone");
923   locality_name->set_sub_zone("mysubzone");
924   auto* socket_address = locality->add_lb_endpoints()
925                              ->mutable_endpoint()
926                              ->mutable_address()
927                              ->mutable_socket_address();
928   socket_address->set_address("127.0.0.1");
929   socket_address->set_port_value(443);
930   locality->set_priority(0);
931   // Second locality has weight of uint32 max.
932   locality = cla.add_endpoints();
933   locality->mutable_load_balancing_weight()->set_value(
934       std::numeric_limits<uint32_t>::max());
935   locality_name = locality->mutable_locality();
936   locality_name->set_region("myregion2");
937   locality_name->set_zone("myzone");
938   locality_name->set_sub_zone("mysubzone");
939   socket_address = locality->add_lb_endpoints()
940                        ->mutable_endpoint()
941                        ->mutable_address()
942                        ->mutable_socket_address();
943   socket_address->set_address("127.0.0.2");
944   socket_address->set_port_value(443);
945   locality->set_priority(0);
946   std::string serialized_resource;
947   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
948   auto* resource_type = XdsEndpointResourceType::Get();
949   auto decode_result =
950       resource_type->Decode(decode_context_, serialized_resource);
951   ASSERT_TRUE(decode_result.name.has_value());
952   EXPECT_EQ(*decode_result.name, "foo");
953   EXPECT_EQ(decode_result.resource.status().code(),
954             absl::StatusCode::kInvalidArgument);
955   EXPECT_EQ(decode_result.resource.status().message(),
956             "errors parsing EDS resource: ["
957             "field:endpoints error:sum of locality weights for priority 0 "
958             "exceeds uint32 max]")
959       << decode_result.resource.status();
960 }
961 
TEST_F(XdsEndpointTest,DuplicateAddresses)962 TEST_F(XdsEndpointTest, DuplicateAddresses) {
963   ClusterLoadAssignment cla;
964   cla.set_cluster_name("foo");
965   auto* locality = cla.add_endpoints();
966   locality->mutable_load_balancing_weight()->set_value(1);
967   auto* locality_name = locality->mutable_locality();
968   locality_name->set_region("myregion");
969   locality_name->set_zone("myzone");
970   locality_name->set_sub_zone("mysubzone");
971   auto* socket_address = locality->add_lb_endpoints()
972                              ->mutable_endpoint()
973                              ->mutable_address()
974                              ->mutable_socket_address();
975   socket_address->set_address("127.0.0.1");
976   socket_address->set_port_value(443);
977   locality->set_priority(0);
978   locality = cla.add_endpoints();
979   locality->mutable_load_balancing_weight()->set_value(1);
980   locality_name = locality->mutable_locality();
981   locality_name->set_region("myregion2");
982   locality_name->set_zone("myzone");
983   locality_name->set_sub_zone("mysubzone");
984   socket_address = locality->add_lb_endpoints()
985                        ->mutable_endpoint()
986                        ->mutable_address()
987                        ->mutable_socket_address();
988   socket_address->set_address("127.0.0.1");
989   socket_address->set_port_value(443);
990   locality->set_priority(0);
991   std::string serialized_resource;
992   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
993   auto* resource_type = XdsEndpointResourceType::Get();
994   auto decode_result =
995       resource_type->Decode(decode_context_, serialized_resource);
996   ASSERT_TRUE(decode_result.name.has_value());
997   EXPECT_EQ(*decode_result.name, "foo");
998   EXPECT_EQ(decode_result.resource.status().code(),
999             absl::StatusCode::kInvalidArgument);
1000   EXPECT_EQ(decode_result.resource.status().message(),
1001             "errors parsing EDS resource: ["
1002             "field:endpoints[1].lb_endpoints[0] "
1003             "error:duplicate endpoint address \"ipv4:127.0.0.1:443\"]")
1004       << decode_result.resource.status();
1005 }
1006 
TEST_F(XdsEndpointTest,DropConfig)1007 TEST_F(XdsEndpointTest, DropConfig) {
1008   ClusterLoadAssignment cla;
1009   cla.set_cluster_name("foo");
1010   auto* locality = cla.add_endpoints();
1011   locality->mutable_load_balancing_weight()->set_value(1);
1012   auto* locality_name = locality->mutable_locality();
1013   locality_name->set_region("myregion");
1014   locality_name->set_zone("myzone");
1015   locality_name->set_sub_zone("mysubzone");
1016   auto* socket_address = locality->add_lb_endpoints()
1017                              ->mutable_endpoint()
1018                              ->mutable_address()
1019                              ->mutable_socket_address();
1020   socket_address->set_address("127.0.0.1");
1021   socket_address->set_port_value(443);
1022   auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1023   drop_overload->set_category("lb_drop");
1024   drop_overload->mutable_drop_percentage()->set_numerator(50);
1025   drop_overload = cla.mutable_policy()->add_drop_overloads();
1026   drop_overload->set_category("lb_overload");
1027   drop_overload->mutable_drop_percentage()->set_numerator(2500);
1028   drop_overload->mutable_drop_percentage()->set_denominator(
1029       envoy::type::v3::FractionalPercent::TEN_THOUSAND);
1030   drop_overload = cla.mutable_policy()->add_drop_overloads();
1031   drop_overload->set_category("why_not");
1032   drop_overload->mutable_drop_percentage()->set_numerator(750000);
1033   drop_overload->mutable_drop_percentage()->set_denominator(
1034       envoy::type::v3::FractionalPercent::MILLION);
1035   std::string serialized_resource;
1036   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1037   auto* resource_type = XdsEndpointResourceType::Get();
1038   auto decode_result =
1039       resource_type->Decode(decode_context_, serialized_resource);
1040   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1041   ASSERT_TRUE(decode_result.name.has_value());
1042   EXPECT_EQ(*decode_result.name, "foo");
1043   auto& resource =
1044       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1045   ASSERT_NE(resource.drop_config, nullptr);
1046   const auto& drop_list = resource.drop_config->drop_category_list();
1047   ASSERT_EQ(drop_list.size(), 3);
1048   EXPECT_EQ(drop_list[0].name, "lb_drop");
1049   EXPECT_EQ(drop_list[0].parts_per_million, 500000);
1050   EXPECT_EQ(drop_list[1].name, "lb_overload");
1051   EXPECT_EQ(drop_list[1].parts_per_million, 250000);
1052   EXPECT_EQ(drop_list[2].name, "why_not");
1053   EXPECT_EQ(drop_list[2].parts_per_million, 750000);
1054 }
1055 
TEST_F(XdsEndpointTest,CapsDropPercentageAt100)1056 TEST_F(XdsEndpointTest, CapsDropPercentageAt100) {
1057   ClusterLoadAssignment cla;
1058   cla.set_cluster_name("foo");
1059   auto* locality = cla.add_endpoints();
1060   locality->mutable_load_balancing_weight()->set_value(1);
1061   auto* locality_name = locality->mutable_locality();
1062   locality_name->set_region("myregion");
1063   locality_name->set_zone("myzone");
1064   locality_name->set_sub_zone("mysubzone");
1065   auto* socket_address = locality->add_lb_endpoints()
1066                              ->mutable_endpoint()
1067                              ->mutable_address()
1068                              ->mutable_socket_address();
1069   socket_address->set_address("127.0.0.1");
1070   socket_address->set_port_value(443);
1071   auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1072   drop_overload->set_category("lb_drop");
1073   drop_overload->mutable_drop_percentage()->set_numerator(10000001);
1074   std::string serialized_resource;
1075   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1076   auto* resource_type = XdsEndpointResourceType::Get();
1077   auto decode_result =
1078       resource_type->Decode(decode_context_, serialized_resource);
1079   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1080   ASSERT_TRUE(decode_result.name.has_value());
1081   EXPECT_EQ(*decode_result.name, "foo");
1082   auto& resource =
1083       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1084   ASSERT_NE(resource.drop_config, nullptr);
1085   const auto& drop_list = resource.drop_config->drop_category_list();
1086   ASSERT_EQ(drop_list.size(), 1);
1087   EXPECT_EQ(drop_list[0].name, "lb_drop");
1088   EXPECT_EQ(drop_list[0].parts_per_million, 1000000);
1089   EXPECT_TRUE(resource.drop_config->drop_all());
1090 }
1091 
TEST_F(XdsEndpointTest,MissingDropCategoryName)1092 TEST_F(XdsEndpointTest, MissingDropCategoryName) {
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->mutable_drop_percentage()->set_numerator(50);
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].category "
1121             "error:empty drop category name]")
1122       << decode_result.resource.status();
1123 }
1124 
TEST_F(XdsEndpointTest,MissingDropPercentage)1125 TEST_F(XdsEndpointTest, MissingDropPercentage) {
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   std::string serialized_resource;
1143   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1144   auto* resource_type = XdsEndpointResourceType::Get();
1145   auto decode_result =
1146       resource_type->Decode(decode_context_, serialized_resource);
1147   ASSERT_TRUE(decode_result.name.has_value());
1148   EXPECT_EQ(*decode_result.name, "foo");
1149   EXPECT_EQ(decode_result.resource.status().code(),
1150             absl::StatusCode::kInvalidArgument);
1151   EXPECT_EQ(decode_result.resource.status().message(),
1152             "errors parsing EDS resource: ["
1153             "field:policy.drop_overloads[0].drop_percentage "
1154             "error:field not present]")
1155       << decode_result.resource.status();
1156 }
1157 
TEST_F(XdsEndpointTest,DropPercentageInvalidDenominator)1158 TEST_F(XdsEndpointTest, DropPercentageInvalidDenominator) {
1159   ClusterLoadAssignment cla;
1160   cla.set_cluster_name("foo");
1161   auto* locality = cla.add_endpoints();
1162   locality->mutable_load_balancing_weight()->set_value(1);
1163   auto* locality_name = locality->mutable_locality();
1164   locality_name->set_region("myregion");
1165   locality_name->set_zone("myzone");
1166   locality_name->set_sub_zone("mysubzone");
1167   auto* socket_address = locality->add_lb_endpoints()
1168                              ->mutable_endpoint()
1169                              ->mutable_address()
1170                              ->mutable_socket_address();
1171   socket_address->set_address("127.0.0.1");
1172   socket_address->set_port_value(443);
1173   auto* drop_overload = cla.mutable_policy()->add_drop_overloads();
1174   drop_overload->set_category("lb_drop");
1175   drop_overload->mutable_drop_percentage()->set_numerator(750000);
1176   drop_overload->mutable_drop_percentage()->set_denominator(
1177       static_cast<envoy::type::v3::FractionalPercent_DenominatorType>(100));
1178   std::string serialized_resource;
1179   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1180   auto* resource_type = XdsEndpointResourceType::Get();
1181   auto decode_result =
1182       resource_type->Decode(decode_context_, serialized_resource);
1183   ASSERT_TRUE(decode_result.name.has_value());
1184   EXPECT_EQ(*decode_result.name, "foo");
1185   EXPECT_EQ(decode_result.resource.status().code(),
1186             absl::StatusCode::kInvalidArgument);
1187   EXPECT_EQ(decode_result.resource.status().message(),
1188             "errors parsing EDS resource: ["
1189             "field:policy.drop_overloads[0].drop_percentage.denominator "
1190             "error:unknown denominator type]")
1191       << decode_result.resource.status();
1192 }
1193 
TEST_F(XdsEndpointTest,EndpointHealthStatus)1194 TEST_F(XdsEndpointTest, EndpointHealthStatus) {
1195   ClusterLoadAssignment cla;
1196   cla.set_cluster_name("foo");
1197   auto* locality = cla.add_endpoints();
1198   locality->mutable_load_balancing_weight()->set_value(1);
1199   auto* locality_name = locality->mutable_locality();
1200   locality_name->set_region("myregion");
1201   locality_name->set_zone("myzone");
1202   locality_name->set_sub_zone("mysubzone");
1203   auto* endpoint = locality->add_lb_endpoints();
1204   auto* socket_address =
1205       endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
1206   socket_address->set_address("127.0.0.1");
1207   socket_address->set_port_value(443);
1208   endpoint = locality->add_lb_endpoints();
1209   endpoint->set_health_status(envoy::config::core::v3::HealthStatus::DRAINING);
1210   socket_address =
1211       endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
1212   socket_address->set_address("127.0.0.2");
1213   socket_address->set_port_value(443);
1214   endpoint = locality->add_lb_endpoints();
1215   endpoint->set_health_status(envoy::config::core::v3::HealthStatus::UNHEALTHY);
1216   socket_address =
1217       endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address();
1218   socket_address->set_address("127.0.0.3");
1219   socket_address->set_port_value(443);
1220   std::string serialized_resource;
1221   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1222   auto* resource_type = XdsEndpointResourceType::Get();
1223   auto decode_result =
1224       resource_type->Decode(decode_context_, serialized_resource);
1225   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1226   ASSERT_TRUE(decode_result.name.has_value());
1227   EXPECT_EQ(*decode_result.name, "foo");
1228   auto& resource =
1229       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1230   ASSERT_EQ(resource.priorities.size(), 1);
1231   const auto& priority = resource.priorities[0];
1232   ASSERT_EQ(priority.localities.size(), 1);
1233   const auto& p = *priority.localities.begin();
1234   ASSERT_EQ(p.first, p.second.name.get());
1235   EXPECT_EQ(p.first->region(), "myregion");
1236   EXPECT_EQ(p.first->zone(), "myzone");
1237   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
1238   EXPECT_EQ(p.second.lb_weight, 1);
1239   ASSERT_EQ(p.second.endpoints.size(), 2);
1240   const auto* address = &p.second.endpoints[0];
1241   auto addr = grpc_sockaddr_to_string(&address->address(), /*normalize=*/false);
1242   ASSERT_TRUE(addr.ok()) << addr.status();
1243   EXPECT_EQ(*addr, "127.0.0.1:443");
1244   EXPECT_EQ(address->args().GetInt(GRPC_ARG_XDS_HEALTH_STATUS),
1245             XdsHealthStatus::kUnknown);
1246   address = &p.second.endpoints[1];
1247   addr = grpc_sockaddr_to_string(&address->address(), /*normalize=*/false);
1248   ASSERT_TRUE(addr.ok()) << addr.status();
1249   EXPECT_EQ(*addr, "127.0.0.2:443");
1250   EXPECT_EQ(address->args().GetInt(GRPC_ARG_XDS_HEALTH_STATUS),
1251             XdsHealthStatus::kDraining);
1252 }
1253 
TEST_F(XdsEndpointTest,HttpProxyInEndpoint)1254 TEST_F(XdsEndpointTest, HttpProxyInEndpoint) {
1255   testing::ScopedExperimentalEnvVar env("GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT");
1256   ClusterLoadAssignment cla;
1257   cla.set_cluster_name("foo");
1258   auto* locality = cla.add_endpoints();
1259   locality->mutable_load_balancing_weight()->set_value(1);
1260   auto* locality_name = locality->mutable_locality();
1261   locality_name->set_region("myregion");
1262   locality_name->set_zone("myzone");
1263   locality_name->set_sub_zone("mysubzone");
1264   auto* lb_endpoint = locality->add_lb_endpoints();
1265   envoy::config::core::v3::Address address_proto;
1266   auto* socket_address = address_proto.mutable_socket_address();
1267   socket_address->set_address("1.2.3.4");
1268   socket_address->set_port_value(123);
1269   auto& typed_metadata_map =
1270       *lb_endpoint->mutable_metadata()->mutable_typed_filter_metadata();
1271   typed_metadata_map["envoy.http11_proxy_transport_socket.proxy_address"]
1272       .PackFrom(address_proto);
1273   socket_address = lb_endpoint->mutable_endpoint()
1274                        ->mutable_address()
1275                        ->mutable_socket_address();
1276   socket_address->set_address("127.0.0.1");
1277   socket_address->set_port_value(443);
1278   std::string serialized_resource;
1279   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1280   auto* resource_type = XdsEndpointResourceType::Get();
1281   auto decode_result =
1282       resource_type->Decode(decode_context_, serialized_resource);
1283   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1284   ASSERT_TRUE(decode_result.name.has_value());
1285   EXPECT_EQ(*decode_result.name, "foo");
1286   auto& resource =
1287       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1288   ASSERT_EQ(resource.priorities.size(), 1);
1289   const auto& priority = resource.priorities[0];
1290   ASSERT_EQ(priority.localities.size(), 1);
1291   const auto& p = *priority.localities.begin();
1292   ASSERT_EQ(p.first, p.second.name.get());
1293   EXPECT_EQ(p.first->region(), "myregion");
1294   EXPECT_EQ(p.first->zone(), "myzone");
1295   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
1296   EXPECT_EQ(p.second.lb_weight, 1);
1297   ASSERT_EQ(p.second.endpoints.size(), 1);
1298   const auto& address = p.second.endpoints.front();
1299   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
1300   ASSERT_TRUE(addr.ok()) << addr.status();
1301   EXPECT_EQ(*addr, "127.0.0.1:443");
1302   EXPECT_EQ(address.args(), ChannelArgs()
1303                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
1304                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
1305                                      XdsHealthStatus::HealthStatus::kUnknown)
1306                                 .Set(GRPC_ARG_XDS_HTTP_PROXY, "1.2.3.4:123"));
1307   EXPECT_EQ(resource.drop_config, nullptr);
1308 }
1309 
TEST_F(XdsEndpointTest,HttpProxyInLocality)1310 TEST_F(XdsEndpointTest, HttpProxyInLocality) {
1311   testing::ScopedExperimentalEnvVar env("GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT");
1312   ClusterLoadAssignment cla;
1313   cla.set_cluster_name("foo");
1314   auto* locality = cla.add_endpoints();
1315   envoy::config::core::v3::Address address_proto;
1316   auto* socket_address = address_proto.mutable_socket_address();
1317   socket_address->set_address("1.2.3.4");
1318   socket_address->set_port_value(123);
1319   auto& typed_metadata_map =
1320       *locality->mutable_metadata()->mutable_typed_filter_metadata();
1321   typed_metadata_map["envoy.http11_proxy_transport_socket.proxy_address"]
1322       .PackFrom(address_proto);
1323   locality->mutable_load_balancing_weight()->set_value(1);
1324   auto* locality_name = locality->mutable_locality();
1325   locality_name->set_region("myregion");
1326   locality_name->set_zone("myzone");
1327   locality_name->set_sub_zone("mysubzone");
1328   auto* lb_endpoint = locality->add_lb_endpoints();
1329   socket_address = lb_endpoint->mutable_endpoint()
1330                        ->mutable_address()
1331                        ->mutable_socket_address();
1332   socket_address->set_address("127.0.0.1");
1333   socket_address->set_port_value(443);
1334   std::string serialized_resource;
1335   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1336   auto* resource_type = XdsEndpointResourceType::Get();
1337   auto decode_result =
1338       resource_type->Decode(decode_context_, serialized_resource);
1339   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1340   ASSERT_TRUE(decode_result.name.has_value());
1341   EXPECT_EQ(*decode_result.name, "foo");
1342   auto& resource =
1343       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1344   ASSERT_EQ(resource.priorities.size(), 1);
1345   const auto& priority = resource.priorities[0];
1346   ASSERT_EQ(priority.localities.size(), 1);
1347   const auto& p = *priority.localities.begin();
1348   ASSERT_EQ(p.first, p.second.name.get());
1349   EXPECT_EQ(p.first->region(), "myregion");
1350   EXPECT_EQ(p.first->zone(), "myzone");
1351   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
1352   EXPECT_EQ(p.second.lb_weight, 1);
1353   ASSERT_EQ(p.second.endpoints.size(), 1);
1354   const auto& address = p.second.endpoints.front();
1355   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
1356   ASSERT_TRUE(addr.ok()) << addr.status();
1357   EXPECT_EQ(*addr, "127.0.0.1:443");
1358   EXPECT_EQ(address.args(), ChannelArgs()
1359                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
1360                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
1361                                      XdsHealthStatus::HealthStatus::kUnknown)
1362                                 .Set(GRPC_ARG_XDS_HTTP_PROXY, "1.2.3.4:123"));
1363   EXPECT_EQ(resource.drop_config, nullptr);
1364 }
1365 
TEST_F(XdsEndpointTest,HttpProxyEndpointSupercedesLocality)1366 TEST_F(XdsEndpointTest, HttpProxyEndpointSupercedesLocality) {
1367   testing::ScopedExperimentalEnvVar env("GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT");
1368   ClusterLoadAssignment cla;
1369   cla.set_cluster_name("foo");
1370   auto* locality = cla.add_endpoints();
1371   envoy::config::core::v3::Address address_proto;
1372   auto* socket_address = address_proto.mutable_socket_address();
1373   socket_address->set_address("1.2.3.4");
1374   socket_address->set_port_value(123);
1375   auto& typed_metadata_map =
1376       *locality->mutable_metadata()->mutable_typed_filter_metadata();
1377   typed_metadata_map["envoy.http11_proxy_transport_socket.proxy_address"]
1378       .PackFrom(address_proto);
1379   locality->mutable_load_balancing_weight()->set_value(1);
1380   auto* locality_name = locality->mutable_locality();
1381   locality_name->set_region("myregion");
1382   locality_name->set_zone("myzone");
1383   locality_name->set_sub_zone("mysubzone");
1384   auto* lb_endpoint = locality->add_lb_endpoints();
1385   socket_address->set_address("4.5.6.7");
1386   socket_address->set_port_value(456);
1387   auto& endpoint_typed_metadata_map =
1388       *lb_endpoint->mutable_metadata()->mutable_typed_filter_metadata();
1389   endpoint_typed_metadata_map
1390       ["envoy.http11_proxy_transport_socket.proxy_address"]
1391           .PackFrom(address_proto);
1392   socket_address = lb_endpoint->mutable_endpoint()
1393                        ->mutable_address()
1394                        ->mutable_socket_address();
1395   socket_address->set_address("127.0.0.1");
1396   socket_address->set_port_value(443);
1397   std::string serialized_resource;
1398   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1399   auto* resource_type = XdsEndpointResourceType::Get();
1400   auto decode_result =
1401       resource_type->Decode(decode_context_, serialized_resource);
1402   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1403   ASSERT_TRUE(decode_result.name.has_value());
1404   EXPECT_EQ(*decode_result.name, "foo");
1405   auto& resource =
1406       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1407   ASSERT_EQ(resource.priorities.size(), 1);
1408   const auto& priority = resource.priorities[0];
1409   ASSERT_EQ(priority.localities.size(), 1);
1410   const auto& p = *priority.localities.begin();
1411   ASSERT_EQ(p.first, p.second.name.get());
1412   EXPECT_EQ(p.first->region(), "myregion");
1413   EXPECT_EQ(p.first->zone(), "myzone");
1414   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
1415   EXPECT_EQ(p.second.lb_weight, 1);
1416   ASSERT_EQ(p.second.endpoints.size(), 1);
1417   const auto& address = p.second.endpoints.front();
1418   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
1419   ASSERT_TRUE(addr.ok()) << addr.status();
1420   EXPECT_EQ(*addr, "127.0.0.1:443");
1421   EXPECT_EQ(address.args(), ChannelArgs()
1422                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
1423                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
1424                                      XdsHealthStatus::HealthStatus::kUnknown)
1425                                 .Set(GRPC_ARG_XDS_HTTP_PROXY, "4.5.6.7:456"));
1426   EXPECT_EQ(resource.drop_config, nullptr);
1427 }
1428 
TEST_F(XdsEndpointTest,HttpProxyIgnoredIfNotEnabled)1429 TEST_F(XdsEndpointTest, HttpProxyIgnoredIfNotEnabled) {
1430   ClusterLoadAssignment cla;
1431   cla.set_cluster_name("foo");
1432   auto* locality = cla.add_endpoints();
1433   envoy::config::core::v3::Address address_proto;
1434   auto* socket_address = address_proto.mutable_socket_address();
1435   socket_address->set_address("1.2.3.4");
1436   socket_address->set_port_value(123);
1437   auto& typed_metadata_map =
1438       *locality->mutable_metadata()->mutable_typed_filter_metadata();
1439   typed_metadata_map["envoy.http11_proxy_transport_socket.proxy_address"]
1440       .PackFrom(address_proto);
1441   locality->mutable_load_balancing_weight()->set_value(1);
1442   auto* locality_name = locality->mutable_locality();
1443   locality_name->set_region("myregion");
1444   locality_name->set_zone("myzone");
1445   locality_name->set_sub_zone("mysubzone");
1446   auto* lb_endpoint = locality->add_lb_endpoints();
1447   socket_address->set_address("4.5.6.7");
1448   socket_address->set_port_value(456);
1449   auto& endpoint_typed_metadata_map =
1450       *lb_endpoint->mutable_metadata()->mutable_typed_filter_metadata();
1451   endpoint_typed_metadata_map
1452       ["envoy.http11_proxy_transport_socket.proxy_address"]
1453           .PackFrom(address_proto);
1454   socket_address = lb_endpoint->mutable_endpoint()
1455                        ->mutable_address()
1456                        ->mutable_socket_address();
1457   socket_address->set_address("127.0.0.1");
1458   socket_address->set_port_value(443);
1459   std::string serialized_resource;
1460   ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
1461   auto* resource_type = XdsEndpointResourceType::Get();
1462   auto decode_result =
1463       resource_type->Decode(decode_context_, serialized_resource);
1464   ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
1465   ASSERT_TRUE(decode_result.name.has_value());
1466   EXPECT_EQ(*decode_result.name, "foo");
1467   auto& resource =
1468       static_cast<const XdsEndpointResource&>(**decode_result.resource);
1469   ASSERT_EQ(resource.priorities.size(), 1);
1470   const auto& priority = resource.priorities[0];
1471   ASSERT_EQ(priority.localities.size(), 1);
1472   const auto& p = *priority.localities.begin();
1473   ASSERT_EQ(p.first, p.second.name.get());
1474   EXPECT_EQ(p.first->region(), "myregion");
1475   EXPECT_EQ(p.first->zone(), "myzone");
1476   EXPECT_EQ(p.first->sub_zone(), "mysubzone");
1477   EXPECT_EQ(p.second.lb_weight, 1);
1478   ASSERT_EQ(p.second.endpoints.size(), 1);
1479   const auto& address = p.second.endpoints.front();
1480   auto addr = grpc_sockaddr_to_string(&address.address(), /*normalize=*/false);
1481   ASSERT_TRUE(addr.ok()) << addr.status();
1482   EXPECT_EQ(*addr, "127.0.0.1:443");
1483   EXPECT_EQ(address.args(), ChannelArgs()
1484                                 .Set(GRPC_ARG_ADDRESS_WEIGHT, 1)
1485                                 .Set(GRPC_ARG_XDS_HEALTH_STATUS,
1486                                      XdsHealthStatus::HealthStatus::kUnknown));
1487   EXPECT_EQ(resource.drop_config, nullptr);
1488 }
1489 
1490 }  // namespace
1491 }  // namespace testing
1492 }  // namespace grpc_core
1493 
main(int argc,char ** argv)1494 int main(int argc, char** argv) {
1495   ::testing::InitGoogleTest(&argc, argv);
1496   grpc::testing::TestEnvironment env(&argc, argv);
1497   grpc_init();
1498   int ret = RUN_ALL_TESTS();
1499   grpc_shutdown();
1500   return ret;
1501 }
1502