• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // IWYU pragma: no_include <ratio>
16 // IWYU pragma: no_include <arpa/inet.h>
17 
18 #include <grpc/event_engine/event_engine.h>
19 #include <grpc/support/port_platform.h>
20 
21 #include <cstdlib>
22 #include <cstring>
23 #include <memory>
24 #include <string>
25 #include <tuple>
26 #include <vector>
27 
28 #include "absl/log/log.h"
29 #include "absl/status/status.h"
30 #include "absl/status/statusor.h"
31 #include "absl/strings/str_format.h"
32 #include "absl/strings/str_join.h"
33 #include "absl/strings/string_view.h"
34 #include "absl/types/optional.h"
35 #include "gmock/gmock.h"
36 #include "gtest/gtest.h"
37 #include "src/core/config/config_vars.h"
38 #include "src/core/lib/event_engine/tcp_socket_utils.h"
39 #include "src/core/lib/iomgr/sockaddr.h"
40 #include "src/core/util/crash.h"  // IWYU pragma: keep
41 #include "src/core/util/notification.h"
42 #include "test/core/event_engine/test_suite/event_engine_test_framework.h"
43 #include "test/core/test_util/fake_udp_and_tcp_server.h"
44 #include "test/core/test_util/port.h"
45 #include "test/cpp/util/get_grpc_test_runfile_dir.h"
46 #include "test/cpp/util/subprocess.h"
47 
48 #ifdef GPR_WINDOWS
49 #include "test/cpp/util/windows/manifest_file.h"
50 #endif  // GPR_WINDOWS
51 
52 namespace grpc_event_engine {
53 namespace experimental {
54 
InitDNSTests()55 void InitDNSTests() {}
56 
57 }  // namespace experimental
58 }  // namespace grpc_event_engine
59 
60 namespace {
61 
62 using grpc_event_engine::experimental::EventEngine;
63 using grpc_event_engine::experimental::URIToResolvedAddress;
64 using SRVRecord = EventEngine::DNSResolver::SRVRecord;
65 using testing::ElementsAre;
66 using testing::Pointwise;
67 using testing::SizeIs;
68 using testing::UnorderedPointwise;
69 
70 // TODO(yijiem): make this portable for Windows
71 constexpr char kDNSTestRecordGroupsYamlPath[] =
72     "test/core/event_engine/test_suite/tests/dns_test_record_groups.yaml";
73 // Invoke bazel's executable links to the .sh and .py scripts (don't use
74 // the .sh and .py suffixes) to make sure that we're using bazel's test
75 // environment.
76 constexpr char kDNSServerRelPath[] = "test/cpp/naming/utils/dns_server";
77 constexpr char kDNSResolverRelPath[] = "test/cpp/naming/utils/dns_resolver";
78 constexpr char kTCPConnectRelPath[] = "test/cpp/naming/utils/tcp_connect";
79 constexpr char kHealthCheckRelPath[] = "test/cpp/naming/utils/health_check";
80 
81 MATCHER(ResolvedAddressEq, "") {
82   const auto& addr0 = std::get<0>(arg);
83   const auto& addr1 = std::get<1>(arg);
84   return addr0.size() == addr1.size() &&
85          memcmp(addr0.address(), addr1.address(), addr0.size()) == 0;
86 }
87 
88 MATCHER(SRVRecordEq, "") {
89   const auto& arg0 = std::get<0>(arg);
90   const auto& arg1 = std::get<1>(arg);
91   return arg0.host == arg1.host && arg0.port == arg1.port &&
92          arg0.priority == arg1.priority && arg0.weight == arg1.weight;
93 }
94 
95 MATCHER(StatusCodeEq, "") {
96   return std::get<0>(arg).code() == std::get<1>(arg);
97 }
98 
99 #define SKIP_TEST_FOR_NATIVE_DNS_RESOLVER()                              \
100   do {                                                                   \
101     if (grpc_core::ConfigVars::Get().DnsResolver() == "native") {        \
102       GTEST_SKIP()                                                       \
103           << "This test specifies a target DNS server which the native " \
104              "DNS resolver does not support.";                           \
105     }                                                                    \
106   } while (0)
107 
108 }  // namespace
109 
110 class EventEngineDNSTest : public EventEngineTest {
111  protected:
SetUpTestSuite()112   static void SetUpTestSuite() {
113 #if !GRPC_IOS_EVENT_ENGINE_CLIENT
114     std::string test_records_path = kDNSTestRecordGroupsYamlPath;
115     std::string dns_server_path = kDNSServerRelPath;
116     std::string dns_resolver_path = kDNSResolverRelPath;
117     std::string tcp_connect_path = kTCPConnectRelPath;
118     std::string health_check_path = kHealthCheckRelPath;
119     absl::optional<std::string> runfile_dir = grpc::GetGrpcTestRunFileDir();
120     if (runfile_dir.has_value()) {
121       test_records_path = absl::StrJoin({*runfile_dir, test_records_path}, "/");
122       dns_server_path = absl::StrJoin({*runfile_dir, dns_server_path}, "/");
123       dns_resolver_path = absl::StrJoin({*runfile_dir, dns_resolver_path}, "/");
124       tcp_connect_path = absl::StrJoin({*runfile_dir, tcp_connect_path}, "/");
125       health_check_path = absl::StrJoin({*runfile_dir, health_check_path}, "/");
126 #ifdef GPR_WINDOWS
127 // TODO(yijiem): Misusing the GRPC_PORT_ISOLATED_RUNTIME preprocessor symbol as
128 // an indication whether the test is running on RBE or not. Find a better way of
129 // doing this.
130 #ifndef GRPC_PORT_ISOLATED_RUNTIME
131       LOG(ERROR) << "You are invoking the test locally with Bazel, you may "
132                     "need to invoke Bazel with --enable_runfiles=yes.";
133 #endif  // GRPC_PORT_ISOLATED_RUNTIME
134       test_records_path = grpc::testing::NormalizeFilePath(test_records_path);
135       dns_server_path =
136           grpc::testing::NormalizeFilePath(dns_server_path + ".exe");
137       dns_resolver_path =
138           grpc::testing::NormalizeFilePath(dns_resolver_path + ".exe");
139       tcp_connect_path =
140           grpc::testing::NormalizeFilePath(tcp_connect_path + ".exe");
141       health_check_path =
142           grpc::testing::NormalizeFilePath(health_check_path + ".exe");
143 #endif  // GPR_WINDOWS
144     } else {
145 #ifdef GPR_WINDOWS
146       grpc_core::Crash(
147           "The EventEngineDNSTest does not support running without Bazel on "
148           "Windows for now.");
149 #endif  // GPR_WINDOWS
150       // Invoke the .py scripts directly where they are in source code if we are
151       // not running with bazel.
152       dns_server_path += ".py";
153       dns_resolver_path += ".py";
154       tcp_connect_path += ".py";
155       health_check_path += ".py";
156     }
157     // 1. launch dns_server
158     int port = grpc_pick_unused_port_or_die();
159     // <path to dns_server.py> -p <port> -r <path to records config>
160     dns_server_.server_process = new grpc::SubProcess(
161         {dns_server_path, "-p", std::to_string(port), "-r", test_records_path});
162     dns_server_.port = port;
163 
164     // 2. wait until dns_server is up (health check)
165     grpc::SubProcess health_check({
166         health_check_path,
167         "-p",
168         std::to_string(port),
169         "--dns_resolver_bin_path",
170         dns_resolver_path,
171         "--tcp_connect_bin_path",
172         tcp_connect_path,
173     });
174     int status = health_check.Join();
175 #ifdef GPR_WINDOWS
176     ASSERT_EQ(status, 0);
177 #else
178     ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
179 #endif  // GPR_WINDOWS
180 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
181   }
182 
TearDownTestSuite()183   static void TearDownTestSuite() {
184 #if !GRPC_IOS_EVENT_ENGINE_CLIENT
185     dns_server_.server_process->Interrupt();
186     dns_server_.server_process->Join();
187     delete dns_server_.server_process;
188 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
189   }
190 
CreateDefaultDNSResolver()191   std::unique_ptr<EventEngine::DNSResolver> CreateDefaultDNSResolver() {
192     std::shared_ptr<EventEngine> test_ee(this->NewEventEngine());
193     EventEngine::DNSResolver::ResolverOptions options;
194     options.dns_server = dns_server_.address();
195     return *test_ee->GetDNSResolver(options);
196   }
197 
198   std::unique_ptr<EventEngine::DNSResolver>
CreateDNSResolverWithNonResponsiveServer()199   CreateDNSResolverWithNonResponsiveServer() {
200     using FakeUdpAndTcpServer = grpc_core::testing::FakeUdpAndTcpServer;
201     // Start up fake non responsive DNS server
202     fake_dns_server_ = std::make_unique<FakeUdpAndTcpServer>(
203         FakeUdpAndTcpServer::AcceptMode::kWaitForClientToSendFirstBytes,
204         FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
205     const std::string dns_server =
206         absl::StrFormat("[::1]:%d", fake_dns_server_->port());
207     std::shared_ptr<EventEngine> test_ee(this->NewEventEngine());
208     EventEngine::DNSResolver::ResolverOptions options;
209     options.dns_server = dns_server;
210     return *test_ee->GetDNSResolver(options);
211   }
212 
213   std::unique_ptr<EventEngine::DNSResolver>
CreateDNSResolverWithoutSpecifyingServer()214   CreateDNSResolverWithoutSpecifyingServer() {
215     std::shared_ptr<EventEngine> test_ee(this->NewEventEngine());
216     EventEngine::DNSResolver::ResolverOptions options;
217     return *test_ee->GetDNSResolver(options);
218   }
219 
220   struct DNSServer {
addressEventEngineDNSTest::DNSServer221     std::string address() { return "127.0.0.1:" + std::to_string(port); }
222     int port;
223     grpc::SubProcess* server_process;
224   };
225   grpc_core::Notification dns_resolver_signal_;
226 
227  private:
228   static DNSServer dns_server_;
229   std::unique_ptr<grpc_core::testing::FakeUdpAndTcpServer> fake_dns_server_;
230 };
231 
232 EventEngineDNSTest::DNSServer EventEngineDNSTest::dns_server_;
233 
234 // TODO(hork): implement XFAIL for resolvers that don't support TXT or SRV
235 #if !GRPC_IOS_EVENT_ENGINE_CLIENT
236 
TEST_F(EventEngineDNSTest,QueryNXHostname)237 TEST_F(EventEngineDNSTest, QueryNXHostname) {
238   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
239   auto dns_resolver = CreateDefaultDNSResolver();
240   dns_resolver->LookupHostname(
241       [this](auto result) {
242         ASSERT_FALSE(result.ok());
243         EXPECT_EQ(result.status(),
244                   absl::NotFoundError("address lookup failed for "
245                                       "nonexisting-target.dns-test.event-"
246                                       "engine.: Domain name not found"));
247         dns_resolver_signal_.Notify();
248       },
249       "nonexisting-target.dns-test.event-engine.", /*default_port=*/"443");
250   dns_resolver_signal_.WaitForNotification();
251 }
252 
TEST_F(EventEngineDNSTest,QueryWithIPLiteral)253 TEST_F(EventEngineDNSTest, QueryWithIPLiteral) {
254   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
255   auto dns_resolver = CreateDefaultDNSResolver();
256   dns_resolver->LookupHostname(
257       [this](auto result) {
258         ASSERT_TRUE(result.ok());
259         EXPECT_THAT(*result,
260                     Pointwise(ResolvedAddressEq(),
261                               {*URIToResolvedAddress("ipv4:4.3.2.1:1234")}));
262         dns_resolver_signal_.Notify();
263       },
264       "4.3.2.1:1234",
265       /*default_port=*/"");
266   dns_resolver_signal_.WaitForNotification();
267 }
268 
TEST_F(EventEngineDNSTest,QueryARecord)269 TEST_F(EventEngineDNSTest, QueryARecord) {
270   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
271   auto dns_resolver = CreateDefaultDNSResolver();
272   dns_resolver->LookupHostname(
273       [this](auto result) {
274         ASSERT_TRUE(result.ok());
275         EXPECT_THAT(*result, UnorderedPointwise(
276                                  ResolvedAddressEq(),
277                                  {*URIToResolvedAddress("ipv4:1.2.3.4:443"),
278                                   *URIToResolvedAddress("ipv4:1.2.3.5:443"),
279                                   *URIToResolvedAddress("ipv4:1.2.3.6:443")}));
280         dns_resolver_signal_.Notify();
281       },
282       "ipv4-only-multi-target.dns-test.event-engine.",
283       /*default_port=*/"443");
284   dns_resolver_signal_.WaitForNotification();
285 }
286 
TEST_F(EventEngineDNSTest,QueryAAAARecord)287 TEST_F(EventEngineDNSTest, QueryAAAARecord) {
288   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
289   auto dns_resolver = CreateDefaultDNSResolver();
290   dns_resolver->LookupHostname(
291       [this](auto result) {
292         ASSERT_TRUE(result.ok());
293         EXPECT_THAT(
294             *result,
295             UnorderedPointwise(
296                 ResolvedAddressEq(),
297                 {*URIToResolvedAddress("ipv6:[2607:f8b0:400a:801::1002]:443"),
298                  *URIToResolvedAddress("ipv6:[2607:f8b0:400a:801::1003]:443"),
299                  *URIToResolvedAddress(
300                      "ipv6:[2607:f8b0:400a:801::1004]:443")}));
301         dns_resolver_signal_.Notify();
302       },
303       "ipv6-only-multi-target.dns-test.event-engine.:443",
304       /*default_port=*/"");
305   dns_resolver_signal_.WaitForNotification();
306 }
307 
TEST_F(EventEngineDNSTest,TestAddressSorting)308 TEST_F(EventEngineDNSTest, TestAddressSorting) {
309   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
310   auto dns_resolver = CreateDefaultDNSResolver();
311   dns_resolver->LookupHostname(
312       [this](auto result) {
313         ASSERT_TRUE(result.ok());
314         EXPECT_THAT(
315             *result,
316             Pointwise(ResolvedAddressEq(),
317                       {*URIToResolvedAddress("ipv6:[::1]:1234"),
318                        *URIToResolvedAddress("ipv6:[2002::1111]:1234")}));
319         dns_resolver_signal_.Notify();
320       },
321       "ipv6-loopback-preferred-target.dns-test.event-engine.:1234",
322       /*default_port=*/"");
323   dns_resolver_signal_.WaitForNotification();
324 }
325 
TEST_F(EventEngineDNSTest,QuerySRVRecord)326 TEST_F(EventEngineDNSTest, QuerySRVRecord) {
327   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
328   const SRVRecord kExpectedRecords[] = {
329       {/*host=*/"ipv4-only-multi-target.dns-test.event-engine", /*port=*/1234,
330        /*priority=*/0, /*weight=*/0},
331       {"ipv6-only-multi-target.dns-test.event-engine", 1234, 0, 0},
332   };
333 
334   auto dns_resolver = CreateDefaultDNSResolver();
335   dns_resolver->LookupSRV(
336       [&kExpectedRecords, this](auto result) {
337         ASSERT_TRUE(result.ok());
338         EXPECT_THAT(*result, Pointwise(SRVRecordEq(), kExpectedRecords));
339         dns_resolver_signal_.Notify();
340       },
341       "_grpclb._tcp.srv-multi-target.dns-test.event-engine.");
342   dns_resolver_signal_.WaitForNotification();
343 }
344 
TEST_F(EventEngineDNSTest,QuerySRVRecordWithLocalhost)345 TEST_F(EventEngineDNSTest, QuerySRVRecordWithLocalhost) {
346   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
347   auto dns_resolver = CreateDefaultDNSResolver();
348   dns_resolver->LookupSRV(
349       [this](auto result) {
350         ASSERT_TRUE(result.ok());
351         EXPECT_THAT(*result, SizeIs(0));
352         dns_resolver_signal_.Notify();
353       },
354       "localhost:1000");
355   dns_resolver_signal_.WaitForNotification();
356 }
357 
TEST_F(EventEngineDNSTest,QueryTXTRecord)358 TEST_F(EventEngineDNSTest, QueryTXTRecord) {
359   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
360   // clang-format off
361   const std::string kExpectedRecord =
362       "grpc_config=[{"
363         "\"serviceConfig\":{"
364           "\"loadBalancingPolicy\":\"round_robin\","
365           "\"methodConfig\":[{"
366             "\"name\":[{"
367               "\"method\":\"Foo\","
368               "\"service\":\"SimpleService\""
369             "}],"
370             "\"waitForReady\":true"
371           "}]"
372         "}"
373       "}]";
374   // clang-format on
375 
376   auto dns_resolver = CreateDefaultDNSResolver();
377   dns_resolver->LookupTXT(
378       [&kExpectedRecord, this](auto result) {
379         ASSERT_TRUE(result.ok());
380         EXPECT_THAT(*result,
381                     ElementsAre(kExpectedRecord, "other_config=other config"));
382         dns_resolver_signal_.Notify();
383       },
384       "_grpc_config.simple-service.dns-test.event-engine.");
385   dns_resolver_signal_.WaitForNotification();
386 }
387 
TEST_F(EventEngineDNSTest,QueryTXTRecordWithLocalhost)388 TEST_F(EventEngineDNSTest, QueryTXTRecordWithLocalhost) {
389   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
390   auto dns_resolver = CreateDefaultDNSResolver();
391   dns_resolver->LookupTXT(
392       [this](auto result) {
393         ASSERT_TRUE(result.ok());
394         EXPECT_THAT(*result, SizeIs(0));
395         dns_resolver_signal_.Notify();
396       },
397       "localhost:1000");
398   dns_resolver_signal_.WaitForNotification();
399 }
400 
TEST_F(EventEngineDNSTest,TestCancelActiveDNSQuery)401 TEST_F(EventEngineDNSTest, TestCancelActiveDNSQuery) {
402   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
403   const std::string name = "dont-care-since-wont-be-resolved.test.com:1234";
404   auto dns_resolver = CreateDNSResolverWithNonResponsiveServer();
405   dns_resolver->LookupHostname(
406       [this](auto result) {
407         ASSERT_FALSE(result.ok());
408         EXPECT_EQ(result.status(),
409                   absl::CancelledError("address lookup failed for "
410                                        "dont-care-since-wont-be-resolved.test."
411                                        "com:1234: DNS query cancelled"));
412         dns_resolver_signal_.Notify();
413       },
414       name, "1234");
415   dns_resolver.reset();
416   dns_resolver_signal_.WaitForNotification();
417 }
418 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
419 
420 #define EXPECT_SUCCESS()           \
421   do {                             \
422     EXPECT_TRUE(result.ok());      \
423     EXPECT_FALSE(result->empty()); \
424   } while (0)
425 
426 // The following tests are almost 1-to-1 ported from
427 // test/core/iomgr/resolve_address_test.cc (except tests for the native DNS
428 // resolver and tests that would not make sense using the
429 // EventEngine::DNSResolver API).
430 
431 // START
TEST_F(EventEngineDNSTest,LocalHost)432 TEST_F(EventEngineDNSTest, LocalHost) {
433   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
434   dns_resolver->LookupHostname(
435       [this](auto result) {
436 #if GRPC_IOS_EVENT_ENGINE_CLIENT
437         EXPECT_SUCCESS();
438 #else
439         EXPECT_TRUE(result.ok());
440         EXPECT_THAT(*result,
441                     Pointwise(ResolvedAddressEq(),
442                               {*URIToResolvedAddress("ipv6:[::1]:1"),
443                                *URIToResolvedAddress("ipv4:127.0.0.1:1")}));
444 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
445         dns_resolver_signal_.Notify();
446       },
447       "localhost:1", "");
448   dns_resolver_signal_.WaitForNotification();
449 }
450 
TEST_F(EventEngineDNSTest,DefaultPort)451 TEST_F(EventEngineDNSTest, DefaultPort) {
452   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
453   dns_resolver->LookupHostname(
454       [this](auto result) {
455         EXPECT_SUCCESS();
456         dns_resolver_signal_.Notify();
457       },
458       "localhost", "1");
459   dns_resolver_signal_.WaitForNotification();
460 }
461 
462 // This test assumes the environment has an ipv6 loopback
TEST_F(EventEngineDNSTest,LocalhostResultHasIPv6First)463 TEST_F(EventEngineDNSTest, LocalhostResultHasIPv6First) {
464   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
465   dns_resolver->LookupHostname(
466       [this](auto result) {
467         EXPECT_TRUE(result.ok());
468         EXPECT_TRUE(!result->empty() &&
469                     (*result)[0].address()->sa_family == AF_INET6);
470         dns_resolver_signal_.Notify();
471       },
472       "localhost:1", "");
473   dns_resolver_signal_.WaitForNotification();
474 }
475 
TEST_F(EventEngineDNSTest,NonNumericDefaultPort)476 TEST_F(EventEngineDNSTest, NonNumericDefaultPort) {
477   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
478   dns_resolver->LookupHostname(
479       [this](auto result) {
480         EXPECT_SUCCESS();
481         dns_resolver_signal_.Notify();
482       },
483       "localhost", "http");
484   dns_resolver_signal_.WaitForNotification();
485 }
486 
TEST_F(EventEngineDNSTest,MissingDefaultPort)487 TEST_F(EventEngineDNSTest, MissingDefaultPort) {
488   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
489   dns_resolver->LookupHostname(
490       [this](auto result) {
491         EXPECT_FALSE(result.ok());
492         dns_resolver_signal_.Notify();
493       },
494       "localhost", "");
495   dns_resolver_signal_.WaitForNotification();
496 }
497 
TEST_F(EventEngineDNSTest,IPv6WithPort)498 TEST_F(EventEngineDNSTest, IPv6WithPort) {
499   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
500   dns_resolver->LookupHostname(
501       [this](auto result) {
502         EXPECT_SUCCESS();
503         dns_resolver_signal_.Notify();
504       },
505       "[2001:db8::1]:1", "");
506   dns_resolver_signal_.WaitForNotification();
507 }
508 
TestIPv6WithoutPort(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,grpc_core::Notification * barrier,absl::string_view target)509 void TestIPv6WithoutPort(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,
510                          grpc_core::Notification* barrier,
511                          absl::string_view target) {
512   dns_resolver->LookupHostname(
513       [barrier](auto result) {
514         EXPECT_TRUE(result.ok());
515         EXPECT_FALSE(result->empty());
516         barrier->Notify();
517       },
518       target, "80");
519   barrier->WaitForNotification();
520 }
521 
TEST_F(EventEngineDNSTest,IPv6WithoutPortNoBrackets)522 TEST_F(EventEngineDNSTest, IPv6WithoutPortNoBrackets) {
523   TestIPv6WithoutPort(CreateDNSResolverWithoutSpecifyingServer(),
524                       &dns_resolver_signal_, "2001:db8::1");
525 }
526 
TEST_F(EventEngineDNSTest,IPv6WithoutPortWithBrackets)527 TEST_F(EventEngineDNSTest, IPv6WithoutPortWithBrackets) {
528   TestIPv6WithoutPort(CreateDNSResolverWithoutSpecifyingServer(),
529                       &dns_resolver_signal_, "[2001:db8::1]");
530 }
531 
TEST_F(EventEngineDNSTest,IPv6WithoutPortV4MappedV6)532 TEST_F(EventEngineDNSTest, IPv6WithoutPortV4MappedV6) {
533   TestIPv6WithoutPort(CreateDNSResolverWithoutSpecifyingServer(),
534                       &dns_resolver_signal_, "2001:db8::1.2.3.4");
535 }
536 
TestInvalidIPAddress(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,grpc_core::Notification * barrier,absl::string_view target)537 void TestInvalidIPAddress(
538     std::unique_ptr<EventEngine::DNSResolver> dns_resolver,
539     grpc_core::Notification* barrier, absl::string_view target) {
540   dns_resolver->LookupHostname(
541       [barrier](auto result) {
542         EXPECT_FALSE(result.ok());
543         barrier->Notify();
544       },
545       target, "");
546   barrier->WaitForNotification();
547 }
548 
TEST_F(EventEngineDNSTest,InvalidIPv4Addresses)549 TEST_F(EventEngineDNSTest, InvalidIPv4Addresses) {
550   TestInvalidIPAddress(CreateDNSResolverWithoutSpecifyingServer(),
551                        &dns_resolver_signal_, "293.283.1238.3:1");
552 }
553 
TEST_F(EventEngineDNSTest,InvalidIPv6Addresses)554 TEST_F(EventEngineDNSTest, InvalidIPv6Addresses) {
555   TestInvalidIPAddress(CreateDNSResolverWithoutSpecifyingServer(),
556                        &dns_resolver_signal_, "[2001:db8::11111]:1");
557 }
558 
TestUnparsableHostPort(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,grpc_core::Notification * barrier,absl::string_view target)559 void TestUnparsableHostPort(
560     std::unique_ptr<EventEngine::DNSResolver> dns_resolver,
561     grpc_core::Notification* barrier, absl::string_view target) {
562   dns_resolver->LookupHostname(
563       [barrier](auto result) {
564         EXPECT_FALSE(result.ok());
565         barrier->Notify();
566       },
567       target, "1");
568   barrier->WaitForNotification();
569 }
570 
TEST_F(EventEngineDNSTest,UnparsableHostPortsOnlyBracket)571 TEST_F(EventEngineDNSTest, UnparsableHostPortsOnlyBracket) {
572   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
573                          &dns_resolver_signal_, "[");
574 }
575 
TEST_F(EventEngineDNSTest,UnparsableHostPortsMissingRightBracket)576 TEST_F(EventEngineDNSTest, UnparsableHostPortsMissingRightBracket) {
577   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
578                          &dns_resolver_signal_, "[::1");
579 }
580 
TEST_F(EventEngineDNSTest,UnparsableHostPortsBadPort)581 TEST_F(EventEngineDNSTest, UnparsableHostPortsBadPort) {
582   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
583                          &dns_resolver_signal_, "[::1]bad");
584 }
585 
TEST_F(EventEngineDNSTest,UnparsableHostPortsBadIPv6)586 TEST_F(EventEngineDNSTest, UnparsableHostPortsBadIPv6) {
587   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
588                          &dns_resolver_signal_, "[1.2.3.4]");
589 }
590 
TEST_F(EventEngineDNSTest,UnparsableHostPortsBadLocalhost)591 TEST_F(EventEngineDNSTest, UnparsableHostPortsBadLocalhost) {
592   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
593                          &dns_resolver_signal_, "[localhost]");
594 }
595 
TEST_F(EventEngineDNSTest,UnparsableHostPortsBadLocalhostWithPort)596 TEST_F(EventEngineDNSTest, UnparsableHostPortsBadLocalhostWithPort) {
597   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
598                          &dns_resolver_signal_, "[localhost]:1");
599 }
600 
TEST_F(EventEngineDNSTest,UnparsableHostPortsEmptyHostname)601 TEST_F(EventEngineDNSTest, UnparsableHostPortsEmptyHostname) {
602   TestUnparsableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
603                          &dns_resolver_signal_, ":443");
604 }
605 // END
606