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