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