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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:40