xref: /aosp_15_r20/external/grpc-grpc/test/core/event_engine/test_suite/tests/dns_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 <cstdlib>
19 #include <cstring>
20 #include <memory>
21 #include <string>
22 #include <tuple>
23 #include <vector>
24 
25 #include "absl/status/status.h"
26 #include "absl/status/statusor.h"
27 #include "absl/strings/str_format.h"
28 #include "absl/strings/str_join.h"
29 #include "absl/strings/string_view.h"
30 #include "absl/types/optional.h"
31 #include "gmock/gmock.h"
32 #include "gtest/gtest.h"
33 
34 #include <grpc/event_engine/event_engine.h>
35 #include <grpc/support/port_platform.h>
36 
37 #include "src/core/lib/config/config_vars.h"
38 #include "src/core/lib/event_engine/tcp_socket_utils.h"
39 #include "src/core/lib/gprpp/crash.h"  // IWYU pragma: keep
40 #include "src/core/lib/gprpp/notification.h"
41 #include "src/core/lib/iomgr/sockaddr.h"
42 #include "test/core/event_engine/test_suite/event_engine_test_framework.h"
43 #include "test/core/util/fake_udp_and_tcp_server.h"
44 #include "test/core/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 #ifndef 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       gpr_log(GPR_ERROR,
132               "You are invoking the test locally with Bazel, you may need to "
133               "invoke Bazel with --enable_runfiles=yes.");
134 #endif  // GRPC_PORT_ISOLATED_RUNTIME
135       test_records_path = grpc::testing::NormalizeFilePath(test_records_path);
136       dns_server_path =
137           grpc::testing::NormalizeFilePath(dns_server_path + ".exe");
138       dns_resolver_path =
139           grpc::testing::NormalizeFilePath(dns_resolver_path + ".exe");
140       tcp_connect_path =
141           grpc::testing::NormalizeFilePath(tcp_connect_path + ".exe");
142       health_check_path =
143           grpc::testing::NormalizeFilePath(health_check_path + ".exe");
144 #endif  // GPR_WINDOWS
145     } else {
146 #ifdef GPR_WINDOWS
147       grpc_core::Crash(
148           "The EventEngineDNSTest does not support running without Bazel on "
149           "Windows for now.");
150 #endif  // GPR_WINDOWS
151       // Invoke the .py scripts directly where they are in source code if we are
152       // not running with bazel.
153       dns_server_path += ".py";
154       dns_resolver_path += ".py";
155       tcp_connect_path += ".py";
156       health_check_path += ".py";
157     }
158     // 1. launch dns_server
159     int port = grpc_pick_unused_port_or_die();
160     // <path to dns_server.py> -p <port> -r <path to records config>
161     dns_server_.server_process = new grpc::SubProcess(
162         {dns_server_path, "-p", std::to_string(port), "-r", test_records_path});
163     dns_server_.port = port;
164 
165     // 2. wait until dns_server is up (health check)
166     grpc::SubProcess health_check({
167         health_check_path,
168         "-p",
169         std::to_string(port),
170         "--dns_resolver_bin_path",
171         dns_resolver_path,
172         "--tcp_connect_bin_path",
173         tcp_connect_path,
174     });
175     int status = health_check.Join();
176 #ifdef GPR_WINDOWS
177     ASSERT_EQ(status, 0);
178 #else
179     ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
180 #endif  // GPR_WINDOWS
181 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
182   }
183 
TearDownTestSuite()184   static void TearDownTestSuite() {
185 #ifndef GRPC_IOS_EVENT_ENGINE_CLIENT
186     dns_server_.server_process->Interrupt();
187     dns_server_.server_process->Join();
188     delete dns_server_.server_process;
189 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
190   }
191 
CreateDefaultDNSResolver()192   std::unique_ptr<EventEngine::DNSResolver> CreateDefaultDNSResolver() {
193     std::shared_ptr<EventEngine> test_ee(this->NewEventEngine());
194     EventEngine::DNSResolver::ResolverOptions options;
195     options.dns_server = dns_server_.address();
196     return *test_ee->GetDNSResolver(options);
197   }
198 
199   std::unique_ptr<EventEngine::DNSResolver>
CreateDNSResolverWithNonResponsiveServer()200   CreateDNSResolverWithNonResponsiveServer() {
201     using FakeUdpAndTcpServer = grpc_core::testing::FakeUdpAndTcpServer;
202     // Start up fake non responsive DNS server
203     fake_dns_server_ = std::make_unique<FakeUdpAndTcpServer>(
204         FakeUdpAndTcpServer::AcceptMode::kWaitForClientToSendFirstBytes,
205         FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
206     const std::string dns_server =
207         absl::StrFormat("[::1]:%d", fake_dns_server_->port());
208     std::shared_ptr<EventEngine> test_ee(this->NewEventEngine());
209     EventEngine::DNSResolver::ResolverOptions options;
210     options.dns_server = dns_server;
211     return *test_ee->GetDNSResolver(options);
212   }
213 
214   std::unique_ptr<EventEngine::DNSResolver>
CreateDNSResolverWithoutSpecifyingServer()215   CreateDNSResolverWithoutSpecifyingServer() {
216     std::shared_ptr<EventEngine> test_ee(this->NewEventEngine());
217     EventEngine::DNSResolver::ResolverOptions options;
218     return *test_ee->GetDNSResolver(options);
219   }
220 
221   struct DNSServer {
addressEventEngineDNSTest::DNSServer222     std::string address() { return "127.0.0.1:" + std::to_string(port); }
223     int port;
224     grpc::SubProcess* server_process;
225   };
226   grpc_core::Notification dns_resolver_signal_;
227 
228  private:
229   static DNSServer dns_server_;
230   std::unique_ptr<grpc_core::testing::FakeUdpAndTcpServer> fake_dns_server_;
231 };
232 
233 EventEngineDNSTest::DNSServer EventEngineDNSTest::dns_server_;
234 
235 // TODO(hork): implement XFAIL for resolvers that don't support TXT or SRV
236 #ifndef GRPC_IOS_EVENT_ENGINE_CLIENT
237 
TEST_F(EventEngineDNSTest,QueryNXHostname)238 TEST_F(EventEngineDNSTest, QueryNXHostname) {
239   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
240   auto dns_resolver = CreateDefaultDNSResolver();
241   dns_resolver->LookupHostname(
242       [this](auto result) {
243         ASSERT_FALSE(result.ok());
244         EXPECT_EQ(result.status(),
245                   absl::NotFoundError("address lookup failed for "
246                                       "nonexisting-target.dns-test.event-"
247                                       "engine.: Domain name not found"));
248         dns_resolver_signal_.Notify();
249       },
250       "nonexisting-target.dns-test.event-engine.", /*default_port=*/"443");
251   dns_resolver_signal_.WaitForNotification();
252 }
253 
TEST_F(EventEngineDNSTest,QueryWithIPLiteral)254 TEST_F(EventEngineDNSTest, QueryWithIPLiteral) {
255   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
256   auto dns_resolver = CreateDefaultDNSResolver();
257   dns_resolver->LookupHostname(
258       [this](auto result) {
259         ASSERT_TRUE(result.ok());
260         EXPECT_THAT(*result,
261                     Pointwise(ResolvedAddressEq(),
262                               {*URIToResolvedAddress("ipv4:4.3.2.1:1234")}));
263         dns_resolver_signal_.Notify();
264       },
265       "4.3.2.1:1234",
266       /*default_port=*/"");
267   dns_resolver_signal_.WaitForNotification();
268 }
269 
TEST_F(EventEngineDNSTest,QueryARecord)270 TEST_F(EventEngineDNSTest, QueryARecord) {
271   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
272   auto dns_resolver = CreateDefaultDNSResolver();
273   dns_resolver->LookupHostname(
274       [this](auto result) {
275         ASSERT_TRUE(result.ok());
276         EXPECT_THAT(*result, UnorderedPointwise(
277                                  ResolvedAddressEq(),
278                                  {*URIToResolvedAddress("ipv4:1.2.3.4:443"),
279                                   *URIToResolvedAddress("ipv4:1.2.3.5:443"),
280                                   *URIToResolvedAddress("ipv4:1.2.3.6:443")}));
281         dns_resolver_signal_.Notify();
282       },
283       "ipv4-only-multi-target.dns-test.event-engine.",
284       /*default_port=*/"443");
285   dns_resolver_signal_.WaitForNotification();
286 }
287 
TEST_F(EventEngineDNSTest,QueryAAAARecord)288 TEST_F(EventEngineDNSTest, QueryAAAARecord) {
289   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
290   auto dns_resolver = CreateDefaultDNSResolver();
291   dns_resolver->LookupHostname(
292       [this](auto result) {
293         ASSERT_TRUE(result.ok());
294         EXPECT_THAT(
295             *result,
296             UnorderedPointwise(
297                 ResolvedAddressEq(),
298                 {*URIToResolvedAddress("ipv6:[2607:f8b0:400a:801::1002]:443"),
299                  *URIToResolvedAddress("ipv6:[2607:f8b0:400a:801::1003]:443"),
300                  *URIToResolvedAddress(
301                      "ipv6:[2607:f8b0:400a:801::1004]:443")}));
302         dns_resolver_signal_.Notify();
303       },
304       "ipv6-only-multi-target.dns-test.event-engine.:443",
305       /*default_port=*/"");
306   dns_resolver_signal_.WaitForNotification();
307 }
308 
TEST_F(EventEngineDNSTest,TestAddressSorting)309 TEST_F(EventEngineDNSTest, TestAddressSorting) {
310   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
311   auto dns_resolver = CreateDefaultDNSResolver();
312   dns_resolver->LookupHostname(
313       [this](auto result) {
314         ASSERT_TRUE(result.ok());
315         EXPECT_THAT(
316             *result,
317             Pointwise(ResolvedAddressEq(),
318                       {*URIToResolvedAddress("ipv6:[::1]:1234"),
319                        *URIToResolvedAddress("ipv6:[2002::1111]:1234")}));
320         dns_resolver_signal_.Notify();
321       },
322       "ipv6-loopback-preferred-target.dns-test.event-engine.:1234",
323       /*default_port=*/"");
324   dns_resolver_signal_.WaitForNotification();
325 }
326 
TEST_F(EventEngineDNSTest,QuerySRVRecord)327 TEST_F(EventEngineDNSTest, QuerySRVRecord) {
328   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
329   const SRVRecord kExpectedRecords[] = {
330       {/*host=*/"ipv4-only-multi-target.dns-test.event-engine", /*port=*/1234,
331        /*priority=*/0, /*weight=*/0},
332       {"ipv6-only-multi-target.dns-test.event-engine", 1234, 0, 0},
333   };
334 
335   auto dns_resolver = CreateDefaultDNSResolver();
336   dns_resolver->LookupSRV(
337       [&kExpectedRecords, this](auto result) {
338         ASSERT_TRUE(result.ok());
339         EXPECT_THAT(*result, Pointwise(SRVRecordEq(), kExpectedRecords));
340         dns_resolver_signal_.Notify();
341       },
342       "_grpclb._tcp.srv-multi-target.dns-test.event-engine.");
343   dns_resolver_signal_.WaitForNotification();
344 }
345 
TEST_F(EventEngineDNSTest,QuerySRVRecordWithLocalhost)346 TEST_F(EventEngineDNSTest, QuerySRVRecordWithLocalhost) {
347   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
348   auto dns_resolver = CreateDefaultDNSResolver();
349   dns_resolver->LookupSRV(
350       [this](auto result) {
351         ASSERT_TRUE(result.ok());
352         EXPECT_THAT(*result, SizeIs(0));
353         dns_resolver_signal_.Notify();
354       },
355       "localhost:1000");
356   dns_resolver_signal_.WaitForNotification();
357 }
358 
TEST_F(EventEngineDNSTest,QueryTXTRecord)359 TEST_F(EventEngineDNSTest, QueryTXTRecord) {
360   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
361   // clang-format off
362   const std::string kExpectedRecord =
363       "grpc_config=[{"
364         "\"serviceConfig\":{"
365           "\"loadBalancingPolicy\":\"round_robin\","
366           "\"methodConfig\":[{"
367             "\"name\":[{"
368               "\"method\":\"Foo\","
369               "\"service\":\"SimpleService\""
370             "}],"
371             "\"waitForReady\":true"
372           "}]"
373         "}"
374       "}]";
375   // clang-format on
376 
377   auto dns_resolver = CreateDefaultDNSResolver();
378   dns_resolver->LookupTXT(
379       [&kExpectedRecord, this](auto result) {
380         ASSERT_TRUE(result.ok());
381         EXPECT_THAT(*result,
382                     ElementsAre(kExpectedRecord, "other_config=other config"));
383         dns_resolver_signal_.Notify();
384       },
385       "_grpc_config.simple-service.dns-test.event-engine.");
386   dns_resolver_signal_.WaitForNotification();
387 }
388 
TEST_F(EventEngineDNSTest,QueryTXTRecordWithLocalhost)389 TEST_F(EventEngineDNSTest, QueryTXTRecordWithLocalhost) {
390   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
391   auto dns_resolver = CreateDefaultDNSResolver();
392   dns_resolver->LookupTXT(
393       [this](auto result) {
394         ASSERT_TRUE(result.ok());
395         EXPECT_THAT(*result, SizeIs(0));
396         dns_resolver_signal_.Notify();
397       },
398       "localhost:1000");
399   dns_resolver_signal_.WaitForNotification();
400 }
401 
TEST_F(EventEngineDNSTest,TestCancelActiveDNSQuery)402 TEST_F(EventEngineDNSTest, TestCancelActiveDNSQuery) {
403   SKIP_TEST_FOR_NATIVE_DNS_RESOLVER();
404   const std::string name = "dont-care-since-wont-be-resolved.test.com:1234";
405   auto dns_resolver = CreateDNSResolverWithNonResponsiveServer();
406   dns_resolver->LookupHostname(
407       [this](auto result) {
408         ASSERT_FALSE(result.ok());
409         EXPECT_EQ(result.status(),
410                   absl::CancelledError("address lookup failed for "
411                                        "dont-care-since-wont-be-resolved.test."
412                                        "com:1234: DNS query cancelled"));
413         dns_resolver_signal_.Notify();
414       },
415       name, "1234");
416   dns_resolver.reset();
417   dns_resolver_signal_.WaitForNotification();
418 }
419 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
420 
421 #define EXPECT_SUCCESS()           \
422   do {                             \
423     EXPECT_TRUE(result.ok());      \
424     EXPECT_FALSE(result->empty()); \
425   } while (0)
426 
427 // The following tests are almost 1-to-1 ported from
428 // test/core/iomgr/resolve_address_test.cc (except tests for the native DNS
429 // resolver and tests that would not make sense using the
430 // EventEngine::DNSResolver API).
431 
432 // START
TEST_F(EventEngineDNSTest,LocalHost)433 TEST_F(EventEngineDNSTest, LocalHost) {
434   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
435   dns_resolver->LookupHostname(
436       [this](auto result) {
437 #ifdef GRPC_IOS_EVENT_ENGINE_CLIENT
438         EXPECT_SUCCESS();
439 #else
440         EXPECT_TRUE(result.ok());
441         EXPECT_THAT(*result,
442                     Pointwise(ResolvedAddressEq(),
443                               {*URIToResolvedAddress("ipv6:[::1]:1"),
444                                *URIToResolvedAddress("ipv4:127.0.0.1:1")}));
445 #endif  // GRPC_IOS_EVENT_ENGINE_CLIENT
446         dns_resolver_signal_.Notify();
447       },
448       "localhost:1", "");
449   dns_resolver_signal_.WaitForNotification();
450 }
451 
TEST_F(EventEngineDNSTest,DefaultPort)452 TEST_F(EventEngineDNSTest, DefaultPort) {
453   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
454   dns_resolver->LookupHostname(
455       [this](auto result) {
456         EXPECT_SUCCESS();
457         dns_resolver_signal_.Notify();
458       },
459       "localhost", "1");
460   dns_resolver_signal_.WaitForNotification();
461 }
462 
463 // This test assumes the environment has an ipv6 loopback
TEST_F(EventEngineDNSTest,LocalhostResultHasIPv6First)464 TEST_F(EventEngineDNSTest, LocalhostResultHasIPv6First) {
465   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
466   dns_resolver->LookupHostname(
467       [this](auto result) {
468         EXPECT_TRUE(result.ok());
469         EXPECT_TRUE(!result->empty() &&
470                     (*result)[0].address()->sa_family == AF_INET6);
471         dns_resolver_signal_.Notify();
472       },
473       "localhost:1", "");
474   dns_resolver_signal_.WaitForNotification();
475 }
476 
TEST_F(EventEngineDNSTest,NonNumericDefaultPort)477 TEST_F(EventEngineDNSTest, NonNumericDefaultPort) {
478   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
479   dns_resolver->LookupHostname(
480       [this](auto result) {
481         EXPECT_SUCCESS();
482         dns_resolver_signal_.Notify();
483       },
484       "localhost", "http");
485   dns_resolver_signal_.WaitForNotification();
486 }
487 
TEST_F(EventEngineDNSTest,MissingDefaultPort)488 TEST_F(EventEngineDNSTest, MissingDefaultPort) {
489   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
490   dns_resolver->LookupHostname(
491       [this](auto result) {
492         EXPECT_FALSE(result.ok());
493         dns_resolver_signal_.Notify();
494       },
495       "localhost", "");
496   dns_resolver_signal_.WaitForNotification();
497 }
498 
TEST_F(EventEngineDNSTest,IPv6WithPort)499 TEST_F(EventEngineDNSTest, IPv6WithPort) {
500   auto dns_resolver = CreateDNSResolverWithoutSpecifyingServer();
501   dns_resolver->LookupHostname(
502       [this](auto result) {
503         EXPECT_SUCCESS();
504         dns_resolver_signal_.Notify();
505       },
506       "[2001:db8::1]:1", "");
507   dns_resolver_signal_.WaitForNotification();
508 }
509 
TestIPv6WithoutPort(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,grpc_core::Notification * barrier,absl::string_view target)510 void TestIPv6WithoutPort(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,
511                          grpc_core::Notification* barrier,
512                          absl::string_view target) {
513   dns_resolver->LookupHostname(
514       [barrier](auto result) {
515         EXPECT_TRUE(result.ok());
516         EXPECT_FALSE(result->empty());
517         barrier->Notify();
518       },
519       target, "80");
520   barrier->WaitForNotification();
521 }
522 
TEST_F(EventEngineDNSTest,IPv6WithoutPortNoBrackets)523 TEST_F(EventEngineDNSTest, IPv6WithoutPortNoBrackets) {
524   TestIPv6WithoutPort(CreateDNSResolverWithoutSpecifyingServer(),
525                       &dns_resolver_signal_, "2001:db8::1");
526 }
527 
TEST_F(EventEngineDNSTest,IPv6WithoutPortWithBrackets)528 TEST_F(EventEngineDNSTest, IPv6WithoutPortWithBrackets) {
529   TestIPv6WithoutPort(CreateDNSResolverWithoutSpecifyingServer(),
530                       &dns_resolver_signal_, "[2001:db8::1]");
531 }
532 
TEST_F(EventEngineDNSTest,IPv6WithoutPortV4MappedV6)533 TEST_F(EventEngineDNSTest, IPv6WithoutPortV4MappedV6) {
534   TestIPv6WithoutPort(CreateDNSResolverWithoutSpecifyingServer(),
535                       &dns_resolver_signal_, "2001:db8::1.2.3.4");
536 }
537 
TestInvalidIPAddress(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,grpc_core::Notification * barrier,absl::string_view target)538 void TestInvalidIPAddress(
539     std::unique_ptr<EventEngine::DNSResolver> dns_resolver,
540     grpc_core::Notification* barrier, absl::string_view target) {
541   dns_resolver->LookupHostname(
542       [barrier](auto result) {
543         EXPECT_FALSE(result.ok());
544         barrier->Notify();
545       },
546       target, "");
547   barrier->WaitForNotification();
548 }
549 
TEST_F(EventEngineDNSTest,InvalidIPv4Addresses)550 TEST_F(EventEngineDNSTest, InvalidIPv4Addresses) {
551   TestInvalidIPAddress(CreateDNSResolverWithoutSpecifyingServer(),
552                        &dns_resolver_signal_, "293.283.1238.3:1");
553 }
554 
TEST_F(EventEngineDNSTest,InvalidIPv6Addresses)555 TEST_F(EventEngineDNSTest, InvalidIPv6Addresses) {
556   TestInvalidIPAddress(CreateDNSResolverWithoutSpecifyingServer(),
557                        &dns_resolver_signal_, "[2001:db8::11111]:1");
558 }
559 
TestUnparseableHostPort(std::unique_ptr<EventEngine::DNSResolver> dns_resolver,grpc_core::Notification * barrier,absl::string_view target)560 void TestUnparseableHostPort(
561     std::unique_ptr<EventEngine::DNSResolver> dns_resolver,
562     grpc_core::Notification* barrier, absl::string_view target) {
563   dns_resolver->LookupHostname(
564       [barrier](auto result) {
565         EXPECT_FALSE(result.ok());
566         barrier->Notify();
567       },
568       target, "1");
569   barrier->WaitForNotification();
570 }
571 
TEST_F(EventEngineDNSTest,UnparseableHostPortsOnlyBracket)572 TEST_F(EventEngineDNSTest, UnparseableHostPortsOnlyBracket) {
573   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
574                           &dns_resolver_signal_, "[");
575 }
576 
TEST_F(EventEngineDNSTest,UnparseableHostPortsMissingRightBracket)577 TEST_F(EventEngineDNSTest, UnparseableHostPortsMissingRightBracket) {
578   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
579                           &dns_resolver_signal_, "[::1");
580 }
581 
TEST_F(EventEngineDNSTest,UnparseableHostPortsBadPort)582 TEST_F(EventEngineDNSTest, UnparseableHostPortsBadPort) {
583   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
584                           &dns_resolver_signal_, "[::1]bad");
585 }
586 
TEST_F(EventEngineDNSTest,UnparseableHostPortsBadIPv6)587 TEST_F(EventEngineDNSTest, UnparseableHostPortsBadIPv6) {
588   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
589                           &dns_resolver_signal_, "[1.2.3.4]");
590 }
591 
TEST_F(EventEngineDNSTest,UnparseableHostPortsBadLocalhost)592 TEST_F(EventEngineDNSTest, UnparseableHostPortsBadLocalhost) {
593   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
594                           &dns_resolver_signal_, "[localhost]");
595 }
596 
TEST_F(EventEngineDNSTest,UnparseableHostPortsBadLocalhostWithPort)597 TEST_F(EventEngineDNSTest, UnparseableHostPortsBadLocalhostWithPort) {
598   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
599                           &dns_resolver_signal_, "[localhost]:1");
600 }
601 
TEST_F(EventEngineDNSTest,UnparseableHostPortsEmptyHostname)602 TEST_F(EventEngineDNSTest, UnparseableHostPortsEmptyHostname) {
603   TestUnparseableHostPort(CreateDNSResolverWithoutSpecifyingServer(),
604                           &dns_resolver_signal_, ":443");
605 }
606 // END
607