1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/dns/dns_task_results_manager.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <optional>
10 #include <string_view>
11
12 #include "base/check.h"
13 #include "base/functional/callback_forward.h"
14 #include "base/test/task_environment.h"
15 #include "base/time/time.h"
16 #include "net/base/connection_endpoint_metadata.h"
17 #include "net/base/net_errors.h"
18 #include "net/dns/host_resolver_internal_result.h"
19 #include "net/dns/host_resolver_results_test_util.h"
20 #include "net/dns/https_record_rdata.h"
21 #include "net/test/test_with_task_environment.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "url/gurl.h"
25 #include "url/scheme_host_port.h"
26
27 using ::testing::ElementsAre;
28 using ::testing::IsEmpty;
29 using ::testing::UnorderedElementsAre;
30
31 namespace net {
32
33 namespace {
34
35 class FakeDelegate : public DnsTaskResultsManager::Delegate {
36 public:
37 FakeDelegate() = default;
38 ~FakeDelegate() override = default;
39
40 private:
OnServiceEndpointsUpdated()41 void OnServiceEndpointsUpdated() override {
42 // Do nothing for now.
43 }
44 };
45
MakeIPEndPoint(std::string_view ip_literal,uint16_t port=0)46 IPEndPoint MakeIPEndPoint(std::string_view ip_literal, uint16_t port = 0) {
47 std::optional<IPAddress> ip = IPAddress::FromIPLiteral(std::move(ip_literal));
48 return IPEndPoint(*ip, port);
49 }
50
CreateDataResult(std::string_view domain_name,std::vector<IPEndPoint> ip_endpoints,DnsQueryType query_type)51 std::unique_ptr<HostResolverInternalDataResult> CreateDataResult(
52 std::string_view domain_name,
53 std::vector<IPEndPoint> ip_endpoints,
54 DnsQueryType query_type) {
55 return std::make_unique<HostResolverInternalDataResult>(
56 std::string(domain_name), query_type, /*expiration=*/base::TimeTicks(),
57 /*timed_expiration=*/base::Time(),
58 HostResolverInternalResult::Source::kDns, std::move(ip_endpoints),
59 std::vector<std::string>(), std::vector<HostPortPair>());
60 }
61
CreateNoData(std::string_view domain_name,DnsQueryType query_type)62 std::unique_ptr<HostResolverInternalErrorResult> CreateNoData(
63 std::string_view domain_name,
64 DnsQueryType query_type) {
65 return std::make_unique<HostResolverInternalErrorResult>(
66 std::string(domain_name), query_type, /*expiration=*/base::TimeTicks(),
67 /*timed_expiration=*/base::Time(),
68 HostResolverInternalResult::Source::kDns, ERR_NAME_NOT_RESOLVED);
69 }
70
CreateMetadata(std::string_view domain_name,std::multimap<HttpsRecordPriority,ConnectionEndpointMetadata> metadatas)71 std::unique_ptr<HostResolverInternalMetadataResult> CreateMetadata(
72 std::string_view domain_name,
73 std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas) {
74 return std::make_unique<HostResolverInternalMetadataResult>(
75 std::string(domain_name), DnsQueryType::HTTPS,
76 /*expiration=*/base::TimeTicks(), /*timed_expiration=*/base::Time(),
77 HostResolverInternalResult::Source::kDns, std::move(metadatas));
78 }
79
CreateAlias(std::string_view domain_name,DnsQueryType query_type,std::string_view alias_target)80 std::unique_ptr<HostResolverInternalAliasResult> CreateAlias(
81 std::string_view domain_name,
82 DnsQueryType query_type,
83 std::string_view alias_target) {
84 return std::make_unique<HostResolverInternalAliasResult>(
85 std::string(domain_name), query_type, /*expiration=*/base::TimeTicks(),
86 /*timed_expiration=*/base::Time(),
87 HostResolverInternalResult::Source::kDns, std::string(alias_target));
88 }
89
WithPort(const std::vector<IPEndPoint> & endpoints,uint16_t port)90 std::vector<IPEndPoint> WithPort(const std::vector<IPEndPoint>& endpoints,
91 uint16_t port) {
92 std::vector<IPEndPoint> out_endpoints;
93 for (const auto& endpoint : endpoints) {
94 out_endpoints.emplace_back(endpoint.address(), port);
95 }
96 return out_endpoints;
97 }
98
99 static constexpr std::string_view kHostName = "www.example.com";
100 static constexpr std::string_view kAliasTarget1 = "alias1.example.net";
101 static constexpr std::string_view kAliasTarget2 = "alias2.example.net";
102
103 static const ConnectionEndpointMetadata kMetadata1(
104 /*supported_protocol_alpns=*/{"h3"},
105 /*ech_config_list=*/{},
106 std::string(kHostName));
107
108 static const ConnectionEndpointMetadata kMetadata2(
109 /*supported_protocol_alpns=*/{"h2", "http/1.1"},
110 /*ech_config_list=*/{},
111 std::string(kHostName));
112
113 static const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
114 kMetadatas{{1, kMetadata1}, {2, kMetadata2}};
115
116 // A helper class to create a DnsTaskResultsManager.
117 class ManagerFactory {
118 public:
ManagerFactory(DnsTaskResultsManager::Delegate * delegate)119 explicit ManagerFactory(DnsTaskResultsManager::Delegate* delegate)
120 : delegate_(delegate),
121 host_(
122 HostResolver::Host(url::SchemeHostPort("https", kHostName, 443))) {}
123
Create()124 std::unique_ptr<DnsTaskResultsManager> Create() {
125 return std::make_unique<DnsTaskResultsManager>(
126 delegate_, host_, query_types_, NetLogWithSource());
127 }
128
query_types(DnsQueryTypeSet query_types)129 ManagerFactory& query_types(DnsQueryTypeSet query_types) {
130 query_types_ = query_types;
131 return *this;
132 }
133
134 private:
135 raw_ptr<DnsTaskResultsManager::Delegate> delegate_;
136 HostResolver::Host host_;
137 DnsQueryTypeSet query_types_ = {DnsQueryType::A, DnsQueryType::AAAA,
138 DnsQueryType::HTTPS};
139 };
140
141 } // namespace
142
143 class DnsTaskResultsManagerTest : public TestWithTaskEnvironment {
144 public:
DnsTaskResultsManagerTest()145 DnsTaskResultsManagerTest()
146 : TestWithTaskEnvironment(
147 base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
148
SetUp()149 void SetUp() override { delegate_ = std::make_unique<FakeDelegate>(); }
150
151 protected:
factory()152 ManagerFactory factory() { return ManagerFactory(delegate_.get()); }
153
154 private:
155 std::unique_ptr<FakeDelegate> delegate_;
156 };
157
TEST_F(DnsTaskResultsManagerTest,IsMetadataReady)158 TEST_F(DnsTaskResultsManagerTest, IsMetadataReady) {
159 // HTTPS RR is not queried.
160 std::unique_ptr<DnsTaskResultsManager> manager =
161 factory().query_types({DnsQueryType::A, DnsQueryType::AAAA}).Create();
162 ASSERT_TRUE(manager->IsMetadataReady());
163
164 // HTTPS RR is queried.
165 manager = factory()
166 .query_types(
167 {DnsQueryType::A, DnsQueryType::AAAA, DnsQueryType::HTTPS})
168 .Create();
169 ASSERT_FALSE(manager->IsMetadataReady());
170
171 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, /*results=*/{});
172 ASSERT_TRUE(manager->IsMetadataReady());
173 }
174
TEST_F(DnsTaskResultsManagerTest,IPv6NotQueried)175 TEST_F(DnsTaskResultsManagerTest, IPv6NotQueried) {
176 std::unique_ptr<DnsTaskResultsManager> manager =
177 factory().query_types({DnsQueryType::A, DnsQueryType::HTTPS}).Create();
178
179 std::unique_ptr<HostResolverInternalResult> result = CreateDataResult(
180 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
181 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result.get()});
182
183 EXPECT_THAT(manager->GetCurrentEndpoints(),
184 ElementsAre(ExpectServiceEndpoint(
185 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
186 EXPECT_THAT(manager->GetAliases(), UnorderedElementsAre(kHostName));
187 }
188
TEST_F(DnsTaskResultsManagerTest,IPv4First)189 TEST_F(DnsTaskResultsManagerTest, IPv4First) {
190 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
191
192 // A comes first. Service endpoints creation should be delayed.
193 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
194 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
195 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result1.get()});
196
197 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
198
199 // AAAA is responded. Service endpoints should be available.
200 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
201 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
202 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result2.get()});
203
204 EXPECT_THAT(manager->GetCurrentEndpoints(),
205 ElementsAre(ExpectServiceEndpoint(
206 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
207 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
208 }
209
TEST_F(DnsTaskResultsManagerTest,IPv6First)210 TEST_F(DnsTaskResultsManagerTest, IPv6First) {
211 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
212
213 // AAAA comes first. Service endpoints should be available immediately.
214 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
215 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
216 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result1.get()});
217
218 EXPECT_THAT(manager->GetCurrentEndpoints(),
219 ElementsAre(ExpectServiceEndpoint(
220 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
221
222 // A is responded. Service endpoints should be updated.
223 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
224 kHostName, {MakeIPEndPoint("192.0.2.1"), MakeIPEndPoint("192.0.2.2")},
225 DnsQueryType::A);
226 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result2.get()});
227
228 EXPECT_THAT(manager->GetCurrentEndpoints(),
229 ElementsAre(ExpectServiceEndpoint(
230 ElementsAre(MakeIPEndPoint("192.0.2.1", 443),
231 MakeIPEndPoint("192.0.2.2", 443)),
232 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
233 }
234
TEST_F(DnsTaskResultsManagerTest,IPv6Timedout)235 TEST_F(DnsTaskResultsManagerTest, IPv6Timedout) {
236 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
237
238 // A comes first. Service endpoints creation should be delayed.
239 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
240 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
241 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result1.get()});
242
243 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
244
245 // AAAA is timed out. Service endpoints should be available after timeout.
246 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
247 base::Milliseconds(1));
248
249 EXPECT_THAT(manager->GetCurrentEndpoints(),
250 ElementsAre(ExpectServiceEndpoint(
251 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
252
253 // AAAA is responded after timeout. Service endpoints should be updated.
254 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
255 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
256 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result2.get()});
257
258 EXPECT_THAT(manager->GetCurrentEndpoints(),
259 ElementsAre(ExpectServiceEndpoint(
260 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
261 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
262 }
263
TEST_F(DnsTaskResultsManagerTest,IPv6NoDataBeforeIPv4)264 TEST_F(DnsTaskResultsManagerTest, IPv6NoDataBeforeIPv4) {
265 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
266
267 // AAAA is responded with no data. Service endpoints should not be available.
268 std::unique_ptr<HostResolverInternalResult> result1 =
269 CreateNoData(kHostName, DnsQueryType::AAAA);
270 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result1.get()});
271
272 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
273
274 // A is responded. Service endpoints creation should happen without resolution
275 // delay.
276 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
277 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
278 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result2.get()});
279
280 EXPECT_THAT(manager->GetCurrentEndpoints(),
281 ElementsAre(ExpectServiceEndpoint(
282 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
283 }
284
TEST_F(DnsTaskResultsManagerTest,IPv6NoDataAfterIPv4)285 TEST_F(DnsTaskResultsManagerTest, IPv6NoDataAfterIPv4) {
286 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
287
288 // A is responded. Service endpoints creation should be delayed.
289 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
290 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
291 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result1.get()});
292
293 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
294
295 // AAAA is responded with no data before the resolution delay timer. Service
296 // endpoints should be available without waiting for the timeout.
297 std::unique_ptr<HostResolverInternalResult> result2 =
298 CreateNoData(kHostName, DnsQueryType::AAAA);
299 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result2.get()});
300
301 EXPECT_THAT(manager->GetCurrentEndpoints(),
302 ElementsAre(ExpectServiceEndpoint(
303 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
304 }
305
TEST_F(DnsTaskResultsManagerTest,IPv6EmptyDataAfterIPv4)306 TEST_F(DnsTaskResultsManagerTest, IPv6EmptyDataAfterIPv4) {
307 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
308
309 // A is responded. Service endpoints creation should be delayed.
310 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
311 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
312 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result1.get()});
313
314 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
315
316 // AAAA is responded with a non-cacheable result (an empty result) before the
317 // resolution delay timer. Service endpoints should be available without
318 // waiting for the timeout.
319 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {});
320
321 EXPECT_THAT(manager->GetCurrentEndpoints(),
322 ElementsAre(ExpectServiceEndpoint(
323 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
324 }
325
TEST_F(DnsTaskResultsManagerTest,IPv4AndIPv6NoData)326 TEST_F(DnsTaskResultsManagerTest, IPv4AndIPv6NoData) {
327 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
328
329 // AAAA is responded with no data. Service endpoints should not be available.
330 std::unique_ptr<HostResolverInternalResult> result1 =
331 CreateNoData(kHostName, DnsQueryType::AAAA);
332 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result1.get()});
333
334 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
335
336 // A is responded with no data. Service endpoints should not be available.
337 std::unique_ptr<HostResolverInternalResult> result2 =
338 CreateNoData(kHostName, DnsQueryType::A);
339 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result2.get()});
340
341 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
342 }
343
TEST_F(DnsTaskResultsManagerTest,IPv4NoDataIPv6AfterResolutionDelay)344 TEST_F(DnsTaskResultsManagerTest, IPv4NoDataIPv6AfterResolutionDelay) {
345 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
346
347 // A comes first with no data. Service endpoints creation should be delayed
348 // and the resolution delay timer should not start.
349 std::unique_ptr<HostResolverInternalResult> result1 =
350 CreateNoData(kHostName, DnsQueryType::A);
351 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result1.get()});
352
353 ASSERT_FALSE(manager->IsResolutionDelayTimerRunningForTest());
354 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
355
356 // The resolution delay passed. Service endpoints should not be available yet.
357 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
358 base::Milliseconds(1));
359
360 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
361
362 // AAAA is responded. Service endpoints should be updated.
363 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
364 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
365 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result2.get()});
366
367 EXPECT_THAT(manager->GetCurrentEndpoints(),
368 ElementsAre(ExpectServiceEndpoint(
369 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
370 }
371
TEST_F(DnsTaskResultsManagerTest,MetadataFirst)372 TEST_F(DnsTaskResultsManagerTest, MetadataFirst) {
373 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
374
375 // HTTPS comes first. Service endpoints should not be available yet since
376 // Chrome doesn't support ipv{4,6}hint yet.
377 std::unique_ptr<HostResolverInternalResult> result1 =
378 CreateMetadata(kHostName, kMetadatas);
379 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, {result1.get()});
380
381 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
382 ASSERT_TRUE(manager->IsMetadataReady());
383
384 // A is responded. Service endpoints creation should be delayed.
385 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
386 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
387 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result2.get()});
388
389 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
390
391 // AAAA is responded. Service endpoints should be available with metadatas.
392 std::unique_ptr<HostResolverInternalResult> result3 = CreateDataResult(
393 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
394 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result3.get()});
395
396 EXPECT_THAT(
397 manager->GetCurrentEndpoints(),
398 ElementsAre(
399 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
400 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
401 kMetadata1),
402 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
403 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
404 kMetadata2)));
405 }
406
TEST_F(DnsTaskResultsManagerTest,MetadataDifferentTargetName)407 TEST_F(DnsTaskResultsManagerTest, MetadataDifferentTargetName) {
408 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
409
410 // HTTPS is responded and the target name is different from QNAME.
411 const ConnectionEndpointMetadata kMetadataDifferentTargetName(
412 /*supported_protocol_alpns=*/{"h2", "http/1.1"},
413 /*ech_config_list=*/{},
414 /*target_name=*/"other.example.net.");
415 std::unique_ptr<HostResolverInternalResult> result1 =
416 CreateMetadata(kHostName, {{1, kMetadataDifferentTargetName}});
417 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, {result1.get()});
418
419 ASSERT_TRUE(manager->IsMetadataReady());
420
421 // AAAA is responded. Service endpoints should be available without metadatas
422 // since the target name is different.
423 std::unique_ptr<HostResolverInternalResult> result2 = CreateDataResult(
424 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
425 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result2.get()});
426
427 ASSERT_TRUE(manager->IsMetadataReady());
428 EXPECT_THAT(manager->GetCurrentEndpoints(),
429 ElementsAre(ExpectServiceEndpoint(
430 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
431 }
432
TEST_F(DnsTaskResultsManagerTest,MetadataAfterIPv6)433 TEST_F(DnsTaskResultsManagerTest, MetadataAfterIPv6) {
434 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
435
436 // AAAA comes first. Service endpoints should be available without metadatas.
437 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
438 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
439 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result1.get()});
440
441 ASSERT_FALSE(manager->IsMetadataReady());
442 EXPECT_THAT(manager->GetCurrentEndpoints(),
443 ElementsAre(ExpectServiceEndpoint(
444 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
445
446 // HTTPS is responded. Metadata should be available.
447 std::unique_ptr<HostResolverInternalResult> result2 =
448 CreateMetadata(kHostName, kMetadatas);
449 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, {result2.get()});
450
451 ASSERT_TRUE(manager->IsMetadataReady());
452 EXPECT_THAT(
453 manager->GetCurrentEndpoints(),
454 ElementsAre(
455 ExpectServiceEndpoint(IsEmpty(),
456 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
457 kMetadata1),
458 ExpectServiceEndpoint(IsEmpty(),
459 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
460 kMetadata2)));
461 }
462
TEST_F(DnsTaskResultsManagerTest,IPv6TimedoutAfterMetadata)463 TEST_F(DnsTaskResultsManagerTest, IPv6TimedoutAfterMetadata) {
464 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
465
466 // A comes first. Service endpoints creation should be delayed.
467 std::unique_ptr<HostResolverInternalResult> result1 = CreateDataResult(
468 kHostName, {MakeIPEndPoint("192.0.2.1")}, DnsQueryType::A);
469 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result1.get()});
470
471 ASSERT_FALSE(manager->IsMetadataReady());
472 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
473
474 // HTTPS is responded. Service endpoints should not be available because
475 // the manager is waiting for the resolution delay and Chrome doesn't support
476 // ipv6hint yet.
477 std::unique_ptr<HostResolverInternalResult> result2 =
478 CreateMetadata(kHostName, kMetadatas);
479 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, {result2.get()});
480
481 ASSERT_TRUE(manager->IsMetadataReady());
482 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
483
484 // AAAA is timed out. Service endpoints should be available with metadatas.
485 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
486 base::Milliseconds(1));
487
488 ASSERT_TRUE(manager->IsMetadataReady());
489 EXPECT_THAT(
490 manager->GetCurrentEndpoints(),
491 ElementsAre(
492 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
493 IsEmpty(), kMetadata1),
494 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
495 IsEmpty(), kMetadata2)));
496 }
497
TEST_F(DnsTaskResultsManagerTest,IPv4NoDataIPv6TimedoutAfterMetadata)498 TEST_F(DnsTaskResultsManagerTest, IPv4NoDataIPv6TimedoutAfterMetadata) {
499 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
500
501 // HTTPS is responded. Service endpoints should not be available because
502 // the manager is waiting for the resolution delay and Chrome doesn't support
503 // address hints yet.
504 std::unique_ptr<HostResolverInternalResult> result1 =
505 CreateMetadata(kHostName, kMetadatas);
506 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, {result1.get()});
507
508 ASSERT_TRUE(manager->IsMetadataReady());
509 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
510
511 // A is responded with no address. Service endpoints should not be available
512 // since there are no addresses.
513 std::unique_ptr<HostResolverInternalResult> result2 =
514 CreateNoData(kHostName, DnsQueryType::A);
515 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result2.get()});
516
517 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
518
519 // AAAA is timed out. Service endpoints should not be available since there
520 // are no addresses.
521 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
522 base::Milliseconds(1));
523
524 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
525 }
526
TEST_F(DnsTaskResultsManagerTest,EndpointOrdering)527 TEST_F(DnsTaskResultsManagerTest, EndpointOrdering) {
528 // Has both IPv4/v6 addresses and metadata.
529 constexpr static const std::string_view kSvcbHost1 = "svc1.example.com";
530 // Has both IPv4/v6 addresses but no metadata.
531 constexpr static const std::string_view kSvcbHost2 = "svc2.example.com";
532 // Only has IPv4 addresses.
533 constexpr static const std::string_view kSvcbHost3 = "svc3.example.com";
534
535 const std::vector<IPEndPoint> kSvcbHost1IPv4s = {MakeIPEndPoint("192.0.2.1")};
536 const std::vector<IPEndPoint> kSvcbHost2IPv4s = {MakeIPEndPoint("192.0.2.2")};
537 const std::vector<IPEndPoint> kSvcbHost3IPv4s = {MakeIPEndPoint("192.0.2.3")};
538
539 const std::vector<IPEndPoint> kSvcbHost1IPv6s = {
540 MakeIPEndPoint("2001:db8::1")};
541 const std::vector<IPEndPoint> kSvcbHost2IPv6s = {
542 MakeIPEndPoint("2001:db8::2")};
543
544 const ConnectionEndpointMetadata kSvcbHost1Metadata1(
545 /*supported_protocol_alpns=*/{"h2", "http/1.1"},
546 /*ech_config_list=*/{},
547 /*target_name=*/std::string(kSvcbHost1));
548 const ConnectionEndpointMetadata kSvcbHost1Metadata2(
549 /*supported_protocol_alpns=*/{"h3"},
550 /*ech_config_list=*/{},
551 /*target_name=*/std::string(kSvcbHost1));
552
553 const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
554 kSvcbHost1Metadatas{{1, kSvcbHost1Metadata1}, {2, kSvcbHost1Metadata2}};
555
556 struct TestData {
557 std::string_view host;
558 std::vector<IPEndPoint> ipv4_endpoints;
559 std::vector<IPEndPoint> ipv6_endpoints;
560 std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas;
561 };
562 const TestData kTestDatas[] = {
563 {kSvcbHost1,
564 /*ipv4_addresses=*/kSvcbHost1IPv4s,
565 /*ipv6_addresses=*/kSvcbHost1IPv6s,
566 /*metadatas=*/kSvcbHost1Metadatas},
567 {kSvcbHost2,
568 /*ipv4_addresses=*/kSvcbHost2IPv4s,
569 /*ipv6_addresses=*/kSvcbHost2IPv6s,
570 /*metadatas=*/{}},
571 {kSvcbHost3, /*ipv4_addresses=*/kSvcbHost3IPv4s,
572 /*ipv6_addresses=*/{}, /*metadatas=*/{}},
573 };
574
575 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
576
577 for (const auto& testdata : kTestDatas) {
578 if (!testdata.ipv4_endpoints.empty()) {
579 std::unique_ptr<HostResolverInternalResult> result = CreateDataResult(
580 testdata.host, testdata.ipv4_endpoints, DnsQueryType::A);
581 manager->ProcessDnsTransactionResults(DnsQueryType::A, {result.get()});
582 }
583 if (!testdata.ipv6_endpoints.empty()) {
584 std::unique_ptr<HostResolverInternalResult> result = CreateDataResult(
585 testdata.host, testdata.ipv6_endpoints, DnsQueryType::AAAA);
586 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result.get()});
587 }
588 if (!testdata.metadatas.empty()) {
589 std::unique_ptr<HostResolverInternalResult> result =
590 CreateMetadata(testdata.host, testdata.metadatas);
591 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS,
592 {result.get()});
593 }
594 }
595
596 const std::vector<ServiceEndpoint> kExpects = {
597 ServiceEndpoint(WithPort(kSvcbHost1IPv4s, 443),
598 WithPort(kSvcbHost1IPv6s, 443), kSvcbHost1Metadata1),
599 ServiceEndpoint(WithPort(kSvcbHost1IPv4s, 443),
600 WithPort(kSvcbHost1IPv6s, 443), kSvcbHost1Metadata2),
601 ServiceEndpoint(WithPort(kSvcbHost2IPv4s, 443),
602 WithPort(kSvcbHost2IPv6s, 443),
603 ConnectionEndpointMetadata()),
604 ServiceEndpoint(WithPort(kSvcbHost3IPv4s, 443), {},
605 ConnectionEndpointMetadata()),
606 };
607
608 ASSERT_EQ(manager->GetCurrentEndpoints().size(), kExpects.size());
609 for (size_t i = 0; i < manager->GetCurrentEndpoints().size(); ++i) {
610 SCOPED_TRACE(i);
611 EXPECT_THAT(manager->GetCurrentEndpoints()[i], kExpects[i]);
612 }
613 }
614
TEST_F(DnsTaskResultsManagerTest,Aliases)615 TEST_F(DnsTaskResultsManagerTest, Aliases) {
616 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
617
618 // AAAA is responded with aliases.
619 std::unique_ptr<HostResolverInternalResult> result1 =
620 CreateAlias(kHostName, DnsQueryType::AAAA, kAliasTarget1);
621 std::unique_ptr<HostResolverInternalResult> result2 =
622 CreateAlias(kAliasTarget1, DnsQueryType::AAAA, kAliasTarget2);
623 std::unique_ptr<HostResolverInternalResult> result3 = CreateDataResult(
624 kHostName, {MakeIPEndPoint("2001:db8::1")}, DnsQueryType::AAAA);
625 manager->ProcessDnsTransactionResults(
626 DnsQueryType::AAAA, {result1.get(), result2.get(), result3.get()});
627
628 EXPECT_THAT(manager->GetCurrentEndpoints(),
629 ElementsAre(ExpectServiceEndpoint(
630 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
631 EXPECT_THAT(manager->GetAliases(),
632 UnorderedElementsAre(kHostName, kAliasTarget1, kAliasTarget2));
633 }
634
635 // Regression test for crbug.com/369232963. An IPv4 mapped IPv6 address should
636 // be handled without crashing.
TEST_F(DnsTaskResultsManagerTest,Ipv4MappedIpv6)637 TEST_F(DnsTaskResultsManagerTest, Ipv4MappedIpv6) {
638 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
639
640 auto ip_address = *IPAddress::FromIPLiteral("::ffff:192.0.2.1");
641 IPEndPoint endpoint(ConvertIPv4MappedIPv6ToIPv4(ip_address), /*port=*/0);
642 std::unique_ptr<HostResolverInternalResult> result =
643 CreateDataResult(kHostName, {endpoint}, DnsQueryType::AAAA);
644 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, {result.get()});
645 EXPECT_THAT(manager->GetCurrentEndpoints(),
646 ElementsAre(ExpectServiceEndpoint(
647 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)), IsEmpty())));
648 }
649
650 } // namespace net
651