xref: /aosp_15_r20/external/grpc-grpc/test/cpp/naming/address_sorting_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2017 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <string.h>
20 #include <sys/types.h>
21 
22 #include <vector>
23 
24 #include <address_sorting/address_sorting.h>
25 #include <gmock/gmock.h>
26 
27 #include <grpc/grpc.h>
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/log.h>
30 #include <grpc/support/string_util.h>
31 #include <grpc/support/sync.h>
32 #include <grpc/support/time.h>
33 
34 #include "src/core/client_channel/client_channel_filter.h"
35 #include "src/core/lib/address_utils/sockaddr_utils.h"
36 #include "src/core/lib/channel/channel_args.h"
37 #include "src/core/lib/config/config_vars.h"
38 #include "src/core/lib/gpr/string.h"
39 #include "src/core/lib/gprpp/crash.h"
40 #include "src/core/lib/gprpp/host_port.h"
41 #include "src/core/lib/iomgr/combiner.h"
42 #include "src/core/lib/iomgr/executor.h"
43 #include "src/core/lib/iomgr/iomgr.h"
44 #include "src/core/lib/iomgr/resolve_address.h"
45 #include "src/core/resolver/dns/c_ares/grpc_ares_wrapper.h"
46 #include "src/core/resolver/endpoint_addresses.h"
47 #include "src/core/resolver/resolver.h"
48 #include "src/core/resolver/resolver_registry.h"
49 #include "test/core/util/port.h"
50 #include "test/core/util/test_config.h"
51 #include "test/cpp/util/subprocess.h"
52 #include "test/cpp/util/test_config.h"
53 
54 #ifndef GPR_WINDOWS
55 #include <arpa/inet.h>
56 #include <netinet/in.h>
57 #include <sys/socket.h>
58 #endif
59 
60 namespace {
61 
62 struct TestAddress {
63   std::string dest_addr;
64   int family;
65 };
66 
TestAddressToGrpcResolvedAddress(TestAddress test_addr)67 grpc_resolved_address TestAddressToGrpcResolvedAddress(TestAddress test_addr) {
68   std::string host;
69   std::string port;
70   grpc_resolved_address resolved_addr;
71   grpc_core::SplitHostPort(test_addr.dest_addr.c_str(), &host, &port);
72   if (test_addr.family == AF_INET) {
73     sockaddr_in in_dest;
74     memset(&in_dest, 0, sizeof(sockaddr_in));
75     in_dest.sin_port = htons(atoi(port.c_str()));
76     in_dest.sin_family = AF_INET;
77     GPR_ASSERT(inet_pton(AF_INET, host.c_str(), &in_dest.sin_addr) == 1);
78     memcpy(&resolved_addr.addr, &in_dest, sizeof(sockaddr_in));
79     resolved_addr.len = sizeof(sockaddr_in);
80   } else {
81     GPR_ASSERT(test_addr.family == AF_INET6);
82     sockaddr_in6 in6_dest;
83     memset(&in6_dest, 0, sizeof(sockaddr_in6));
84     in6_dest.sin6_port = htons(atoi(port.c_str()));
85     in6_dest.sin6_family = AF_INET6;
86     GPR_ASSERT(inet_pton(AF_INET6, host.c_str(), &in6_dest.sin6_addr) == 1);
87     memcpy(&resolved_addr.addr, &in6_dest, sizeof(sockaddr_in6));
88     resolved_addr.len = sizeof(sockaddr_in6);
89   }
90   return resolved_addr;
91 }
92 
93 class MockSourceAddrFactory : public address_sorting_source_addr_factory {
94  public:
MockSourceAddrFactory(bool ipv4_supported,bool ipv6_supported,const std::map<std::string,TestAddress> & dest_addr_to_src_addr)95   MockSourceAddrFactory(
96       bool ipv4_supported, bool ipv6_supported,
97       const std::map<std::string, TestAddress>& dest_addr_to_src_addr)
98       : ipv4_supported_(ipv4_supported),
99         ipv6_supported_(ipv6_supported),
100         dest_addr_to_src_addr_(dest_addr_to_src_addr) {}
101 
GetSourceAddr(const address_sorting_address * dest_addr,address_sorting_address * source_addr)102   bool GetSourceAddr(const address_sorting_address* dest_addr,
103                      address_sorting_address* source_addr) {
104     if ((address_sorting_abstract_get_family(dest_addr) ==
105              ADDRESS_SORTING_AF_INET &&
106          !ipv4_supported_) ||
107         (address_sorting_abstract_get_family(dest_addr) ==
108              ADDRESS_SORTING_AF_INET6 &&
109          !ipv6_supported_)) {
110       return false;
111     }
112     grpc_resolved_address dest_addr_as_resolved_addr;
113     memcpy(&dest_addr_as_resolved_addr.addr, dest_addr, dest_addr->len);
114     dest_addr_as_resolved_addr.len = dest_addr->len;
115     std::string ip_addr_str =
116         grpc_sockaddr_to_string(&dest_addr_as_resolved_addr,
117                                 false /* normalize */)
118             .value();
119     auto it = dest_addr_to_src_addr_.find(ip_addr_str);
120     if (it == dest_addr_to_src_addr_.end()) {
121       gpr_log(GPR_DEBUG, "can't find |%s| in dest to src map",
122               ip_addr_str.c_str());
123       return false;
124     }
125     grpc_resolved_address source_addr_as_resolved_addr =
126         TestAddressToGrpcResolvedAddress(it->second);
127     memcpy(source_addr->addr, &source_addr_as_resolved_addr.addr,
128            source_addr_as_resolved_addr.len);
129     source_addr->len = source_addr_as_resolved_addr.len;
130     return true;
131   }
132 
133  private:
134   // user provided test config
135   bool ipv4_supported_;
136   bool ipv6_supported_;
137   std::map<std::string, TestAddress> dest_addr_to_src_addr_;
138 };
139 
mock_source_addr_factory_wrapper_get_source_addr(address_sorting_source_addr_factory * factory,const address_sorting_address * dest_addr,address_sorting_address * source_addr)140 bool mock_source_addr_factory_wrapper_get_source_addr(
141     address_sorting_source_addr_factory* factory,
142     const address_sorting_address* dest_addr,
143     address_sorting_address* source_addr) {
144   MockSourceAddrFactory* mock =
145       reinterpret_cast<MockSourceAddrFactory*>(factory);
146   return mock->GetSourceAddr(dest_addr, source_addr);
147 }
148 
mock_source_addr_factory_wrapper_destroy(address_sorting_source_addr_factory * factory)149 void mock_source_addr_factory_wrapper_destroy(
150     address_sorting_source_addr_factory* factory) {
151   MockSourceAddrFactory* mock =
152       reinterpret_cast<MockSourceAddrFactory*>(factory);
153   delete mock;
154 }
155 
156 const address_sorting_source_addr_factory_vtable kMockSourceAddrFactoryVtable =
157     {
158         mock_source_addr_factory_wrapper_get_source_addr,
159         mock_source_addr_factory_wrapper_destroy,
160 };
161 
OverrideAddressSortingSourceAddrFactory(bool ipv4_supported,bool ipv6_supported,const std::map<std::string,TestAddress> & dest_addr_to_src_addr)162 void OverrideAddressSortingSourceAddrFactory(
163     bool ipv4_supported, bool ipv6_supported,
164     const std::map<std::string, TestAddress>& dest_addr_to_src_addr) {
165   address_sorting_source_addr_factory* factory = new MockSourceAddrFactory(
166       ipv4_supported, ipv6_supported, dest_addr_to_src_addr);
167   factory->vtable = &kMockSourceAddrFactoryVtable;
168   address_sorting_override_source_addr_factory_for_testing(factory);
169 }
170 
BuildLbAddrInputs(const std::vector<TestAddress> & test_addrs)171 grpc_core::EndpointAddressesList BuildLbAddrInputs(
172     const std::vector<TestAddress>& test_addrs) {
173   grpc_core::EndpointAddressesList addresses;
174   for (const auto& addr : test_addrs) {
175     addresses.emplace_back(TestAddressToGrpcResolvedAddress(addr),
176                            grpc_core::ChannelArgs());
177   }
178   return addresses;
179 }
180 
VerifyLbAddrOutputs(const grpc_core::EndpointAddressesList & addresses,std::vector<std::string> expected_addrs)181 void VerifyLbAddrOutputs(const grpc_core::EndpointAddressesList& addresses,
182                          std::vector<std::string> expected_addrs) {
183   EXPECT_EQ(addresses.size(), expected_addrs.size());
184   for (size_t i = 0; i < addresses.size(); ++i) {
185     std::string ip_addr_str =
186         grpc_sockaddr_to_string(&addresses[i].address(), false /* normalize */)
187             .value();
188     EXPECT_EQ(expected_addrs[i], ip_addr_str);
189   }
190 }
191 
192 // We need to run each test case inside of its own
193 // isolated grpc_init/grpc_shutdown pair, so that
194 // the "address sorting source addr factory" can be
195 // restored to its default for each test case.
196 class AddressSortingTest : public ::testing::Test {
197  protected:
SetUp()198   void SetUp() override { grpc_init(); }
TearDown()199   void TearDown() override { grpc_shutdown(); }
200 };
201 
202 // Tests for rule 1
TEST_F(AddressSortingTest,TestDepriotizesUnreachableAddresses)203 TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) {
204   bool ipv4_supported = true;
205   bool ipv6_supported = true;
206   OverrideAddressSortingSourceAddrFactory(
207       ipv4_supported, ipv6_supported,
208       {
209           {"1.2.3.4:443", {"4.3.2.1:443", AF_INET}},
210       });
211   auto lb_addrs = BuildLbAddrInputs({
212       {"1.2.3.4:443", AF_INET},
213       {"5.6.7.8:443", AF_INET},
214   });
215   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
216   VerifyLbAddrOutputs(lb_addrs, {
217                                     "1.2.3.4:443",
218                                     "5.6.7.8:443",
219                                 });
220 }
221 
TEST_F(AddressSortingTest,TestDepriotizesUnsupportedDomainIpv6)222 TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) {
223   bool ipv4_supported = true;
224   bool ipv6_supported = false;
225   OverrideAddressSortingSourceAddrFactory(
226       ipv4_supported, ipv6_supported,
227       {
228           {"1.2.3.4:443", {"4.3.2.1:0", AF_INET}},
229       });
230   auto lb_addrs = BuildLbAddrInputs({
231       {"[2607:f8b0:400a:801::1002]:443", AF_INET6},
232       {"1.2.3.4:443", AF_INET},
233   });
234   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
235   VerifyLbAddrOutputs(lb_addrs, {
236                                     "1.2.3.4:443",
237                                     "[2607:f8b0:400a:801::1002]:443",
238                                 });
239 }
240 
TEST_F(AddressSortingTest,TestDepriotizesUnsupportedDomainIpv4)241 TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) {
242   bool ipv4_supported = false;
243   bool ipv6_supported = true;
244   OverrideAddressSortingSourceAddrFactory(
245       ipv4_supported, ipv6_supported,
246       {
247           {"1.2.3.4:443", {"4.3.2.1:0", AF_INET}},
248           {"[2607:f8b0:400a:801::1002]:443", {"[fec0::1234]:0", AF_INET6}},
249       });
250   auto lb_addrs = BuildLbAddrInputs({
251       {"[2607:f8b0:400a:801::1002]:443", AF_INET6},
252       {"1.2.3.4:443", AF_INET},
253   });
254   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
255   VerifyLbAddrOutputs(lb_addrs, {
256                                     "[2607:f8b0:400a:801::1002]:443",
257                                     "1.2.3.4:443",
258                                 });
259 }
260 
261 // Tests for rule 2
262 
TEST_F(AddressSortingTest,TestDepriotizesNonMatchingScope)263 TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) {
264   bool ipv4_supported = true;
265   bool ipv6_supported = true;
266   OverrideAddressSortingSourceAddrFactory(
267       ipv4_supported, ipv6_supported,
268       {
269           {"[2000:f8b0:400a:801::1002]:443",
270            {"[fec0::1000]:0", AF_INET6}},  // global and site-local scope
271           {"[fec0::5000]:443",
272            {"[fec0::5001]:0", AF_INET6}},  // site-local and site-local scope
273       });
274   auto lb_addrs = BuildLbAddrInputs({
275       {"[2000:f8b0:400a:801::1002]:443", AF_INET6},
276       {"[fec0::5000]:443", AF_INET6},
277   });
278   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
279   VerifyLbAddrOutputs(lb_addrs, {
280                                     "[fec0::5000]:443",
281                                     "[2000:f8b0:400a:801::1002]:443",
282                                 });
283 }
284 
285 // Tests for rule 5
286 
TEST_F(AddressSortingTest,TestUsesLabelFromDefaultTable)287 TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) {
288   bool ipv4_supported = true;
289   bool ipv6_supported = true;
290   OverrideAddressSortingSourceAddrFactory(
291       ipv4_supported, ipv6_supported,
292       {
293           {"[2002::5001]:443", {"[2001::5002]:0", AF_INET6}},
294           {"[2001::5001]:443",
295            {"[2001::5002]:0", AF_INET6}},  // matching labels
296       });
297   auto lb_addrs = BuildLbAddrInputs({
298       {"[2002::5001]:443", AF_INET6},
299       {"[2001::5001]:443", AF_INET6},
300   });
301   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
302   VerifyLbAddrOutputs(lb_addrs, {
303                                     "[2001::5001]:443",
304                                     "[2002::5001]:443",
305                                 });
306 }
307 
308 // Flip the input on the test above to reorder the sort function's
309 // comparator's inputs.
TEST_F(AddressSortingTest,TestUsesLabelFromDefaultTableInputFlipped)310 TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) {
311   bool ipv4_supported = true;
312   bool ipv6_supported = true;
313   OverrideAddressSortingSourceAddrFactory(
314       ipv4_supported, ipv6_supported,
315       {
316           {"[2002::5001]:443", {"[2001::5002]:0", AF_INET6}},
317           {"[2001::5001]:443",
318            {"[2001::5002]:0", AF_INET6}},  // matching labels
319       });
320   auto lb_addrs = BuildLbAddrInputs({
321       {"[2001::5001]:443", AF_INET6},
322       {"[2002::5001]:443", AF_INET6},
323   });
324   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
325   VerifyLbAddrOutputs(lb_addrs, {
326                                     "[2001::5001]:443",
327                                     "[2002::5001]:443",
328                                 });
329 }
330 
331 // Tests for rule 6
332 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address)333 TEST_F(AddressSortingTest,
334        TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) {
335   bool ipv4_supported = true;
336   bool ipv6_supported = true;
337   OverrideAddressSortingSourceAddrFactory(
338       ipv4_supported, ipv6_supported,
339       {
340           {"[3ffe::5001]:443", {"[3ffe::5002]:0", AF_INET6}},
341           {"1.2.3.4:443", {"5.6.7.8:0", AF_INET}},
342       });
343   auto lb_addrs = BuildLbAddrInputs({
344       {"[3ffe::5001]:443", AF_INET6},
345       {"1.2.3.4:443", AF_INET},
346   });
347   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
348   VerifyLbAddrOutputs(
349       lb_addrs, {
350                     // The AF_INET address should be IPv4-mapped by the sort,
351                     // and IPv4-mapped
352                     // addresses have higher precedence than 3ffe::/16 by spec.
353                     "1.2.3.4:443",
354                     "[3ffe::5001]:443",
355                 });
356 }
357 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress)358 TEST_F(AddressSortingTest,
359        TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) {
360   bool ipv4_supported = true;
361   bool ipv6_supported = true;
362   const char* v4_compat_dest = "[::2]:443";
363   const char* v4_compat_src = "[::2]:0";
364   OverrideAddressSortingSourceAddrFactory(
365       ipv4_supported, ipv6_supported,
366       {
367           {"[::1]:443", {"[::1]:0", AF_INET6}},
368           {v4_compat_dest, {v4_compat_src, AF_INET6}},
369       });
370   auto lb_addrs = BuildLbAddrInputs({
371       {v4_compat_dest, AF_INET6},
372       {"[::1]:443", AF_INET6},
373   });
374   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
375   ASSERT_EQ(lb_addrs.size(), 2);
376   EXPECT_EQ(
377       grpc_sockaddr_to_string(&lb_addrs[0].address(), false /* normalize */)
378           .value(),
379       "[::1]:443");
380   // We've observed some inet_ntop implementations have special representations
381   // of IPv4-compatible IPv6 addresses, and others represent them as normal
382   // IPv6 addresses. For the purposes of this test, we don't care which
383   // representation is used.
384   std::vector<std::string> acceptable_addresses = {
385       "[::0.0.0.2]:443",
386       "[::2]:443",
387   };
388   EXPECT_THAT(
389       acceptable_addresses,
390       ::testing::Contains(
391           grpc_sockaddr_to_string(&lb_addrs[1].address(), false /* normalize */)
392               .value()));
393 }
394 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress)395 TEST_F(AddressSortingTest,
396        TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) {
397   bool ipv4_supported = true;
398   bool ipv6_supported = true;
399   OverrideAddressSortingSourceAddrFactory(
400       ipv4_supported, ipv6_supported,
401       {
402           // 1234::2 for src and dest to make sure that prefix matching has no
403           // influence on this test.
404           {"[1234::2]:443", {"[1234::2]:0", AF_INET6}},
405           {"[::1]:443", {"[::1]:0", AF_INET6}},
406       });
407   auto lb_addrs = BuildLbAddrInputs({
408       {"[1234::2]:443", AF_INET6},
409       {"[::1]:443", AF_INET6},
410   });
411   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
412   VerifyLbAddrOutputs(
413       lb_addrs,
414       {
415           // ::1 should match the localhost precedence entry and be prioritized
416           "[::1]:443",
417           "[1234::2]:443",
418       });
419 }
420 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress)421 TEST_F(AddressSortingTest,
422        TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) {
423   bool ipv4_supported = true;
424   bool ipv6_supported = true;
425   OverrideAddressSortingSourceAddrFactory(
426       ipv4_supported, ipv6_supported,
427       {
428           {"[2001::1234]:443", {"[2001::5678]:0", AF_INET6}},
429           {"[2000::5001]:443", {"[2000::5002]:0", AF_INET6}},
430       });
431   auto lb_addrs = BuildLbAddrInputs({
432       {"[2001::1234]:443", AF_INET6},
433       {"[2000::5001]:443", AF_INET6},
434   });
435   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
436   VerifyLbAddrOutputs(
437       lb_addrs, {
438                     // The 2000::/16 address should match the ::/0 prefix rule
439                     "[2000::5001]:443",
440                     "[2001::1234]:443",
441                 });
442 }
443 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect)444 TEST_F(
445     AddressSortingTest,
446     TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect) {
447   bool ipv4_supported = true;
448   bool ipv6_supported = true;
449   OverrideAddressSortingSourceAddrFactory(
450       ipv4_supported, ipv6_supported,
451       {
452           {"[2001::1231]:443", {"[2001::1232]:0", AF_INET6}},
453           {"[2000::5001]:443", {"[2000::5002]:0", AF_INET6}},
454       });
455   auto lb_addrs = BuildLbAddrInputs({
456       {"[2001::1231]:443", AF_INET6},
457       {"[2000::5001]:443", AF_INET6},
458   });
459   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
460   VerifyLbAddrOutputs(lb_addrs, {
461                                     "[2000::5001]:443",
462                                     "[2001::1231]:443",
463                                 });
464 }
465 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses)466 TEST_F(AddressSortingTest,
467        TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) {
468   bool ipv4_supported = true;
469   bool ipv6_supported = true;
470   OverrideAddressSortingSourceAddrFactory(
471       ipv4_supported, ipv6_supported,
472       {
473           {"[fec0::1234]:443", {"[fec0::5678]:0", AF_INET6}},
474           {"[fc00::5001]:443", {"[fc00::5002]:0", AF_INET6}},
475       });
476   auto lb_addrs = BuildLbAddrInputs({
477       {"[fec0::1234]:443", AF_INET6},
478       {"[fc00::5001]:443", AF_INET6},
479   });
480   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
481   VerifyLbAddrOutputs(lb_addrs, {
482                                     "[fc00::5001]:443",
483                                     "[fec0::1234]:443",
484                                 });
485 }
486 
TEST_F(AddressSortingTest,TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses)487 TEST_F(
488     AddressSortingTest,
489     TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses) {
490   bool ipv4_supported = true;
491   bool ipv6_supported = true;
492   // Use embedded ipv4 addresses with leading 1's instead of zero's to be
493   // compatible with inet_ntop implementations that can display such
494   // addresses with leading zero's as e.g.: "::ffff:0:2", as on windows.
495   OverrideAddressSortingSourceAddrFactory(
496       ipv4_supported, ipv6_supported,
497       {
498           {"[::ffff:1.1.1.2]:443", {"[::ffff:1.1.1.3]:0", AF_INET6}},
499           {"[1234::2]:443", {"[1234::3]:0", AF_INET6}},
500       });
501   auto lb_addrs = BuildLbAddrInputs({
502       {"[::ffff:1.1.1.2]:443", AF_INET6},
503       {"[1234::2]:443", AF_INET6},
504   });
505   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
506   VerifyLbAddrOutputs(lb_addrs, {
507                                     // ::ffff:0:2 should match the v4-mapped
508                                     // precedence entry and be deprioritized.
509                                     "[1234::2]:443",
510                                     "[::ffff:1.1.1.2]:443",
511                                 });
512 }
513 
514 // Tests for rule 8
515 
TEST_F(AddressSortingTest,TestPrefersSmallerScope)516 TEST_F(AddressSortingTest, TestPrefersSmallerScope) {
517   bool ipv4_supported = true;
518   bool ipv6_supported = true;
519   OverrideAddressSortingSourceAddrFactory(
520       ipv4_supported, ipv6_supported,
521       {
522           // Both of these destinations have the same precedence in default
523           // policy
524           // table.
525           {"[fec0::1234]:443", {"[fec0::5678]:0", AF_INET6}},
526           {"[3ffe::5001]:443", {"[3ffe::5002]:0", AF_INET6}},
527       });
528   auto lb_addrs = BuildLbAddrInputs({
529       {"[3ffe::5001]:443", AF_INET6},
530       {"[fec0::1234]:443", AF_INET6},
531   });
532   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
533   VerifyLbAddrOutputs(lb_addrs, {
534                                     "[fec0::1234]:443",
535                                     "[3ffe::5001]:443",
536                                 });
537 }
538 
539 // Tests for rule 9
540 
TEST_F(AddressSortingTest,TestPrefersLongestMatchingSrcDstPrefix)541 TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) {
542   bool ipv4_supported = true;
543   bool ipv6_supported = true;
544   OverrideAddressSortingSourceAddrFactory(
545       ipv4_supported, ipv6_supported,
546       {
547           // Both of these destinations have the same precedence in default
548           // policy
549           // table.
550           {"[3ffe:1234::]:443", {"[3ffe:1235::]:0", AF_INET6}},
551           {"[3ffe:5001::]:443", {"[3ffe:4321::]:0", AF_INET6}},
552       });
553   auto lb_addrs = BuildLbAddrInputs({
554       {"[3ffe:5001::]:443", AF_INET6},
555       {"[3ffe:1234::]:443", AF_INET6},
556   });
557   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
558   VerifyLbAddrOutputs(lb_addrs, {
559                                     "[3ffe:1234::]:443",
560                                     "[3ffe:5001::]:443",
561                                 });
562 }
563 
TEST_F(AddressSortingTest,TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress)564 TEST_F(AddressSortingTest,
565        TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) {
566   bool ipv4_supported = true;
567   bool ipv6_supported = true;
568   OverrideAddressSortingSourceAddrFactory(
569       ipv4_supported, ipv6_supported,
570       {
571           {"[3ffe::1234]:443", {"[3ffe::1235]:0", AF_INET6}},
572           {"[3ffe::5001]:443", {"[3ffe::4321]:0", AF_INET6}},
573       });
574   auto lb_addrs = BuildLbAddrInputs({
575       {"[3ffe::5001]:443", AF_INET6},
576       {"[3ffe::1234]:443", AF_INET6},
577   });
578   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
579   VerifyLbAddrOutputs(lb_addrs, {
580                                     "[3ffe::1234]:443",
581                                     "[3ffe::5001]:443",
582                                 });
583 }
584 
TEST_F(AddressSortingTest,TestPrefersLongestPrefixStressInnerBytePrefix)585 TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) {
586   bool ipv4_supported = true;
587   bool ipv6_supported = true;
588   OverrideAddressSortingSourceAddrFactory(
589       ipv4_supported, ipv6_supported,
590       {
591           {"[3ffe:8000::]:443", {"[3ffe:C000::]:0", AF_INET6}},
592           {"[3ffe:2000::]:443", {"[3ffe:3000::]:0", AF_INET6}},
593       });
594   auto lb_addrs = BuildLbAddrInputs({
595       {"[3ffe:8000::]:443", AF_INET6},
596       {"[3ffe:2000::]:443", AF_INET6},
597   });
598   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
599   VerifyLbAddrOutputs(lb_addrs, {
600                                     "[3ffe:2000::]:443",
601                                     "[3ffe:8000::]:443",
602                                 });
603 }
604 
TEST_F(AddressSortingTest,TestPrefersLongestPrefixDiffersOnHighestBitOfByte)605 TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) {
606   bool ipv4_supported = true;
607   bool ipv6_supported = true;
608   OverrideAddressSortingSourceAddrFactory(
609       ipv4_supported, ipv6_supported,
610       {
611           {"[3ffe:6::]:443", {"[3ffe:8::]:0", AF_INET6}},
612           {"[3ffe:c::]:443", {"[3ffe:8::]:0", AF_INET6}},
613       });
614   auto lb_addrs = BuildLbAddrInputs({
615       {"[3ffe:6::]:443", AF_INET6},
616       {"[3ffe:c::]:443", AF_INET6},
617   });
618   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
619   VerifyLbAddrOutputs(lb_addrs, {
620                                     "[3ffe:c::]:443",
621                                     "[3ffe:6::]:443",
622                                 });
623 }
624 
TEST_F(AddressSortingTest,TestPrefersLongestPrefixDiffersByLastBit)625 TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) {
626   bool ipv4_supported = true;
627   bool ipv6_supported = true;
628   OverrideAddressSortingSourceAddrFactory(
629       ipv4_supported, ipv6_supported,
630       {
631           {"[3ffe:1111:1111:1111::]:443",
632            {"[3ffe:1111:1111:1111::]:0", AF_INET6}},
633           {"[3ffe:1111:1111:1110::]:443",
634            {"[3ffe:1111:1111:1111::]:0", AF_INET6}},
635       });
636   auto lb_addrs = BuildLbAddrInputs({
637       {"[3ffe:1111:1111:1110::]:443", AF_INET6},
638       {"[3ffe:1111:1111:1111::]:443", AF_INET6},
639   });
640   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
641   VerifyLbAddrOutputs(lb_addrs, {
642                                     "[3ffe:1111:1111:1111::]:443",
643                                     "[3ffe:1111:1111:1110::]:443",
644                                 });
645 }
646 
647 // Tests for rule 10
648 
TEST_F(AddressSortingTest,TestStableSort)649 TEST_F(AddressSortingTest, TestStableSort) {
650   bool ipv4_supported = true;
651   bool ipv6_supported = true;
652   OverrideAddressSortingSourceAddrFactory(
653       ipv4_supported, ipv6_supported,
654       {
655           {"[3ffe::1234]:443", {"[3ffe::1236]:0", AF_INET6}},
656           {"[3ffe::1235]:443", {"[3ffe::1237]:0", AF_INET6}},
657       });
658   auto lb_addrs = BuildLbAddrInputs({
659       {"[3ffe::1234]:443", AF_INET6},
660       {"[3ffe::1235]:443", AF_INET6},
661   });
662   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
663   VerifyLbAddrOutputs(lb_addrs, {
664                                     "[3ffe::1234]:443",
665                                     "[3ffe::1235]:443",
666                                 });
667 }
668 
TEST_F(AddressSortingTest,TestStableSortFiveElements)669 TEST_F(AddressSortingTest, TestStableSortFiveElements) {
670   bool ipv4_supported = true;
671   bool ipv6_supported = true;
672   OverrideAddressSortingSourceAddrFactory(
673       ipv4_supported, ipv6_supported,
674       {
675           {"[3ffe::1231]:443", {"[3ffe::1201]:0", AF_INET6}},
676           {"[3ffe::1232]:443", {"[3ffe::1202]:0", AF_INET6}},
677           {"[3ffe::1233]:443", {"[3ffe::1203]:0", AF_INET6}},
678           {"[3ffe::1234]:443", {"[3ffe::1204]:0", AF_INET6}},
679           {"[3ffe::1235]:443", {"[3ffe::1205]:0", AF_INET6}},
680       });
681   auto lb_addrs = BuildLbAddrInputs({
682       {"[3ffe::1231]:443", AF_INET6},
683       {"[3ffe::1232]:443", AF_INET6},
684       {"[3ffe::1233]:443", AF_INET6},
685       {"[3ffe::1234]:443", AF_INET6},
686       {"[3ffe::1235]:443", AF_INET6},
687   });
688   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
689   VerifyLbAddrOutputs(lb_addrs, {
690                                     "[3ffe::1231]:443",
691                                     "[3ffe::1232]:443",
692                                     "[3ffe::1233]:443",
693                                     "[3ffe::1234]:443",
694                                     "[3ffe::1235]:443",
695                                 });
696 }
697 
TEST_F(AddressSortingTest,TestStableSortNoSrcAddrsExist)698 TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) {
699   bool ipv4_supported = true;
700   bool ipv6_supported = true;
701   OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {});
702   auto lb_addrs = BuildLbAddrInputs({
703       {"[3ffe::1231]:443", AF_INET6},
704       {"[3ffe::1232]:443", AF_INET6},
705       {"[3ffe::1233]:443", AF_INET6},
706       {"[3ffe::1234]:443", AF_INET6},
707       {"[3ffe::1235]:443", AF_INET6},
708   });
709   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
710   VerifyLbAddrOutputs(lb_addrs, {
711                                     "[3ffe::1231]:443",
712                                     "[3ffe::1232]:443",
713                                     "[3ffe::1233]:443",
714                                     "[3ffe::1234]:443",
715                                     "[3ffe::1235]:443",
716                                 });
717 }
718 
TEST_F(AddressSortingTest,TestStableSortNoSrcAddrsExistWithIpv4)719 TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) {
720   bool ipv4_supported = true;
721   bool ipv6_supported = true;
722   OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {});
723   auto lb_addrs = BuildLbAddrInputs({
724       {"[::ffff:5.6.7.8]:443", AF_INET6},
725       {"1.2.3.4:443", AF_INET},
726   });
727   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
728   VerifyLbAddrOutputs(lb_addrs, {
729                                     "[::ffff:5.6.7.8]:443",
730                                     "1.2.3.4:443",
731                                 });
732 }
733 
TEST_F(AddressSortingTest,TestStableSortV4CompatAndSiteLocalAddresses)734 TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) {
735   bool ipv4_supported = true;
736   bool ipv6_supported = true;
737   const char* v4_compat_dest = "[::2]:443";
738   const char* v4_compat_src = "[::3]:0";
739   OverrideAddressSortingSourceAddrFactory(
740       ipv4_supported, ipv6_supported,
741       {
742           {"[fec0::2000]:443", {"[fec0::2001]:0", AF_INET6}},
743           {v4_compat_dest, {v4_compat_src, AF_INET6}},
744       });
745   auto lb_addrs = BuildLbAddrInputs({
746       {"[fec0::2000]:443", AF_INET6},
747       {v4_compat_dest, AF_INET6},
748   });
749   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
750   ASSERT_EQ(lb_addrs.size(), 2);
751   // The sort should be stable since
752   // v4-compatible has same precedence as site-local.
753   EXPECT_EQ(
754       grpc_sockaddr_to_string(&lb_addrs[0].address(), false /* normalize */)
755           .value(),
756       "[fec0::2000]:443");
757   // We've observed some inet_ntop implementations have special representations
758   // of IPv4-compatible IPv6 addresses, and others represent them as normal
759   // IPv6 addresses. For the purposes of this test, we don't care which
760   // representation is used.
761   std::vector<std::string> acceptable_addresses = {
762       "[::0.0.0.2]:443",
763       "[::2]:443",
764   };
765   EXPECT_THAT(
766       acceptable_addresses,
767       ::testing::Contains(
768           grpc_sockaddr_to_string(&lb_addrs[1].address(), false /* normalize */)
769               .value()));
770 }
771 
772 // TestPrefersIpv6Loopback tests the actual "address probing" code
773 // for the current platform, without any mocks.
774 // This test relies on the assumption that the ipv6 loopback address is
775 // available in the hosts/containers that grpc C/C++ tests run on
776 // (whether ipv4 loopback is available or not, an available ipv6
777 // loopback should be preferred).
TEST_F(AddressSortingTest,TestPrefersIpv6Loopback)778 TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) {
779   auto lb_addrs = BuildLbAddrInputs({
780       {"[::1]:443", AF_INET6},
781       {"127.0.0.1:443", AF_INET},
782   });
783   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
784   VerifyLbAddrOutputs(lb_addrs, {
785                                     "[::1]:443",
786                                     "127.0.0.1:443",
787                                 });
788 }
789 
790 // Flip the order of the inputs above and expect the same output order
791 // (try to rule out influence of arbitrary qsort ordering)
TEST_F(AddressSortingTest,TestPrefersIpv6LoopbackInputsFlipped)792 TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) {
793   auto lb_addrs = BuildLbAddrInputs({
794       {"127.0.0.1:443", AF_INET},
795       {"[::1]:443", AF_INET6},
796   });
797   grpc_cares_wrapper_address_sorting_sort(nullptr, &lb_addrs);
798   VerifyLbAddrOutputs(lb_addrs, {
799                                     "[::1]:443",
800                                     "127.0.0.1:443",
801                                 });
802 }
803 
804 // Try to rule out false positives in the above two tests in which
805 // the sorter might think that neither ipv6 or ipv4 loopback is
806 // available, but ipv6 loopback is still preferred only due
807 // to precedence table lookups.
TEST_F(AddressSortingTest,TestSorterKnowsIpv6LoopbackIsAvailable)808 TEST_F(AddressSortingTest, TestSorterKnowsIpv6LoopbackIsAvailable) {
809   sockaddr_in6 ipv6_loopback;
810   memset(&ipv6_loopback, 0, sizeof(ipv6_loopback));
811   ipv6_loopback.sin6_family = AF_INET6;
812   (reinterpret_cast<char*>(&ipv6_loopback.sin6_addr))[15] = 1;
813   ipv6_loopback.sin6_port = htons(443);
814   // Set up the source and destination parameters of
815   // address_sorting_get_source_addr
816   address_sorting_address sort_input_dest;
817   memcpy(&sort_input_dest.addr, &ipv6_loopback, sizeof(ipv6_loopback));
818   sort_input_dest.len = sizeof(ipv6_loopback);
819   address_sorting_address source_for_sort_input_dest;
820   memset(&source_for_sort_input_dest, 0, sizeof(source_for_sort_input_dest));
821   // address_sorting_get_source_addr returns true if a source address was found
822   // for the destination address, otherwise false.
823   EXPECT_TRUE(address_sorting_get_source_addr_for_testing(
824       &sort_input_dest, &source_for_sort_input_dest));
825   // Now also check that the source address was filled in correctly.
826   EXPECT_GT(source_for_sort_input_dest.len, 0u);
827   sockaddr_in6* source_addr_output =
828       reinterpret_cast<sockaddr_in6*>(source_for_sort_input_dest.addr);
829   EXPECT_EQ(source_addr_output->sin6_family, AF_INET6);
830   char* buf = static_cast<char*>(gpr_zalloc(100));
831   EXPECT_NE(inet_ntop(AF_INET6, &source_addr_output->sin6_addr, buf, 100),
832             nullptr)
833       << "inet_ntop failed. Errno: " + std::to_string(errno);
834   std::string source_addr_str(buf);
835   gpr_free(buf);
836   // This test
837   // assumes that the source address for any loopback destination is also the
838   // loopback address.
839   EXPECT_EQ(source_addr_str, "::1");
840 }
841 
842 }  // namespace
843 
main(int argc,char ** argv)844 int main(int argc, char** argv) {
845   grpc_core::ConfigVars::Overrides overrides;
846   overrides.dns_resolver = "ares";
847   grpc_core::ConfigVars::SetOverrides(overrides);
848   grpc::testing::TestEnvironment env(&argc, argv);
849   ::testing::InitGoogleTest(&argc, argv);
850   auto result = RUN_ALL_TESTS();
851   // Test sequential and nested inits and shutdowns.
852   grpc_init();
853   grpc_init();
854   grpc_shutdown();
855   grpc_shutdown();
856   grpc_init();
857   grpc_shutdown();
858   return result;
859 }
860