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::set<std::unique_ptr<HostResolverInternalResult>> results;
180 results.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
181 DnsQueryType::A));
182 manager->ProcessDnsTransactionResults(DnsQueryType::A, results);
183
184 EXPECT_THAT(manager->GetCurrentEndpoints(),
185 ElementsAre(ExpectServiceEndpoint(
186 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
187 EXPECT_THAT(manager->GetAliases(), UnorderedElementsAre(kHostName));
188 }
189
TEST_F(DnsTaskResultsManagerTest,IPv4First)190 TEST_F(DnsTaskResultsManagerTest, IPv4First) {
191 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
192
193 // A comes first. Service endpoints creation should be delayed.
194 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
195 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
196 DnsQueryType::A));
197 manager->ProcessDnsTransactionResults(DnsQueryType::A, results1);
198
199 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
200
201 // AAAA is responded. Service endpoints should be available.
202 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
203 results2.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
204 DnsQueryType::AAAA));
205 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results2);
206
207 EXPECT_THAT(manager->GetCurrentEndpoints(),
208 ElementsAre(ExpectServiceEndpoint(
209 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
210 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
211 }
212
TEST_F(DnsTaskResultsManagerTest,IPv6First)213 TEST_F(DnsTaskResultsManagerTest, IPv6First) {
214 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
215
216 // AAAA comes first. Service endpoints should be available immediately.
217 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
218 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
219 DnsQueryType::AAAA));
220 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results1);
221
222 EXPECT_THAT(manager->GetCurrentEndpoints(),
223 ElementsAre(ExpectServiceEndpoint(
224 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
225
226 // A is responded. Service endpoints should be updated.
227 std::set<std::unique_ptr<HostResolverInternalResult>> results;
228 results.insert(CreateDataResult(
229 kHostName, {MakeIPEndPoint("192.0.2.1"), MakeIPEndPoint("192.0.2.2")},
230 DnsQueryType::A));
231 manager->ProcessDnsTransactionResults(DnsQueryType::A, results);
232
233 EXPECT_THAT(manager->GetCurrentEndpoints(),
234 ElementsAre(ExpectServiceEndpoint(
235 ElementsAre(MakeIPEndPoint("192.0.2.1", 443),
236 MakeIPEndPoint("192.0.2.2", 443)),
237 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
238 }
239
TEST_F(DnsTaskResultsManagerTest,IPv6Timedout)240 TEST_F(DnsTaskResultsManagerTest, IPv6Timedout) {
241 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
242
243 // A comes first. Service endpoints creation should be delayed.
244 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
245 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
246 DnsQueryType::A));
247 manager->ProcessDnsTransactionResults(DnsQueryType::A, results1);
248
249 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
250
251 // AAAA is timed out. Service endpoints should be available after timeout.
252 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
253 base::Milliseconds(1));
254
255 EXPECT_THAT(manager->GetCurrentEndpoints(),
256 ElementsAre(ExpectServiceEndpoint(
257 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
258
259 // AAAA is responded after timeout. Service endpoints should be updated.
260 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
261 results2.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
262 DnsQueryType::AAAA));
263 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results2);
264
265 EXPECT_THAT(manager->GetCurrentEndpoints(),
266 ElementsAre(ExpectServiceEndpoint(
267 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
268 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
269 }
270
TEST_F(DnsTaskResultsManagerTest,IPv6NoDataBeforeIPv4)271 TEST_F(DnsTaskResultsManagerTest, IPv6NoDataBeforeIPv4) {
272 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
273
274 // AAAA is responded with no data. Service endpoints should not be available.
275 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
276 results1.insert(CreateNoData(kHostName, DnsQueryType::AAAA));
277 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results1);
278
279 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
280
281 // A is responded. Service endpoints creation should happen without resolution
282 // delay.
283 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
284 results2.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
285 DnsQueryType::A));
286 manager->ProcessDnsTransactionResults(DnsQueryType::A, results2);
287
288 EXPECT_THAT(manager->GetCurrentEndpoints(),
289 ElementsAre(ExpectServiceEndpoint(
290 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
291 }
292
TEST_F(DnsTaskResultsManagerTest,IPv6NoDataAfterIPv4)293 TEST_F(DnsTaskResultsManagerTest, IPv6NoDataAfterIPv4) {
294 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
295
296 // A is responded. Service endpoints creation should be delayed.
297 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
298 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
299 DnsQueryType::A));
300 manager->ProcessDnsTransactionResults(DnsQueryType::A, results1);
301
302 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
303
304 // AAAA is responded with no data before the resolution delay timer. Service
305 // endpoints should be available without waiting for the timeout.
306 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
307 results2.insert(CreateNoData(kHostName, DnsQueryType::AAAA));
308 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results2);
309
310 EXPECT_THAT(manager->GetCurrentEndpoints(),
311 ElementsAre(ExpectServiceEndpoint(
312 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
313 }
314
TEST_F(DnsTaskResultsManagerTest,IPv6EmptyDataAfterIPv4)315 TEST_F(DnsTaskResultsManagerTest, IPv6EmptyDataAfterIPv4) {
316 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
317
318 // A is responded. Service endpoints creation should be delayed.
319 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
320 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
321 DnsQueryType::A));
322 manager->ProcessDnsTransactionResults(DnsQueryType::A, results1);
323
324 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
325
326 // AAAA is responded with a non-cacheable result (an empty result) before the
327 // resolution delay timer. Service endpoints should be available without
328 // waiting for the timeout.
329 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
330 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results2);
331
332 EXPECT_THAT(manager->GetCurrentEndpoints(),
333 ElementsAre(ExpectServiceEndpoint(
334 ElementsAre(MakeIPEndPoint("192.0.2.1", 443)))));
335 }
336
TEST_F(DnsTaskResultsManagerTest,IPv4AndIPv6NoData)337 TEST_F(DnsTaskResultsManagerTest, IPv4AndIPv6NoData) {
338 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
339
340 // AAAA is responded with no data. Service endpoints should not be available.
341 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
342 results1.insert(CreateNoData(kHostName, DnsQueryType::AAAA));
343 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results1);
344
345 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
346
347 // A is responded with no data. Service endpoints should not be available.
348 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
349 results2.insert(CreateNoData(kHostName, DnsQueryType::A));
350 manager->ProcessDnsTransactionResults(DnsQueryType::A, results2);
351
352 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
353 }
354
TEST_F(DnsTaskResultsManagerTest,IPv4NoDataIPv6AfterResolutionDelay)355 TEST_F(DnsTaskResultsManagerTest, IPv4NoDataIPv6AfterResolutionDelay) {
356 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
357
358 // A comes first with no data. Service endpoints creation should be delayed
359 // and the resolution delay timer should not start.
360 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
361 results1.insert(CreateNoData(kHostName, DnsQueryType::A));
362 manager->ProcessDnsTransactionResults(DnsQueryType::A, results1);
363
364 ASSERT_FALSE(manager->IsResolutionDelayTimerRunningForTest());
365 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
366
367 // The resolution delay passed. Service endpoints should not be available yet.
368 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
369 base::Milliseconds(1));
370
371 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
372
373 // AAAA is responded. Service endpoints should be updated.
374 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
375 results2.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
376 DnsQueryType::AAAA));
377 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results2);
378
379 EXPECT_THAT(manager->GetCurrentEndpoints(),
380 ElementsAre(ExpectServiceEndpoint(
381 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
382 }
383
TEST_F(DnsTaskResultsManagerTest,MetadataFirst)384 TEST_F(DnsTaskResultsManagerTest, MetadataFirst) {
385 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
386
387 // HTTPS comes first. Service endpoints should not be available yet since
388 // Chrome doesn't support ipv{4,6}hint yet.
389 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
390 results1.insert(CreateMetadata(kHostName, kMetadatas));
391 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, results1);
392
393 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
394 ASSERT_TRUE(manager->IsMetadataReady());
395
396 // A is responded. Service endpoints creation should be delayed.
397 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
398 results2.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
399 DnsQueryType::A));
400 manager->ProcessDnsTransactionResults(DnsQueryType::A, results2);
401
402 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
403
404 // AAAA is responded. Service endpoints should be available with metadatas.
405 std::set<std::unique_ptr<HostResolverInternalResult>> results3;
406 results3.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
407 DnsQueryType::AAAA));
408 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results3);
409
410 EXPECT_THAT(
411 manager->GetCurrentEndpoints(),
412 ElementsAre(
413 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
414 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
415 kMetadata1),
416 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
417 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
418 kMetadata2)));
419 }
420
TEST_F(DnsTaskResultsManagerTest,MetadataDifferentTargetName)421 TEST_F(DnsTaskResultsManagerTest, MetadataDifferentTargetName) {
422 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
423
424 // HTTPS is responded and the target name is different from QNAME.
425 const ConnectionEndpointMetadata kMetadataDifferentTargetName(
426 /*supported_protocol_alpns=*/{"h2", "http/1.1"},
427 /*ech_config_list=*/{},
428 /*target_name=*/"other.example.net.");
429 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
430 results1.insert(
431 CreateMetadata(kHostName, {{1, kMetadataDifferentTargetName}}));
432 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, results1);
433
434 ASSERT_TRUE(manager->IsMetadataReady());
435
436 // AAAA is responded. Service endpoints should be available without metadatas
437 // since the target name is different.
438 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
439 results2.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
440 DnsQueryType::AAAA));
441 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results2);
442
443 ASSERT_TRUE(manager->IsMetadataReady());
444 EXPECT_THAT(manager->GetCurrentEndpoints(),
445 ElementsAre(ExpectServiceEndpoint(
446 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
447 }
448
TEST_F(DnsTaskResultsManagerTest,MetadataAfterIPv6)449 TEST_F(DnsTaskResultsManagerTest, MetadataAfterIPv6) {
450 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
451
452 // AAAA comes first. Service endpoints should be available without metadatas.
453 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
454 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
455 DnsQueryType::AAAA));
456 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results1);
457
458 ASSERT_FALSE(manager->IsMetadataReady());
459 EXPECT_THAT(manager->GetCurrentEndpoints(),
460 ElementsAre(ExpectServiceEndpoint(
461 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
462
463 // HTTPS is responded. Metadata should be available.
464 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
465 results2.insert(CreateMetadata(kHostName, kMetadatas));
466 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, results2);
467
468 ASSERT_TRUE(manager->IsMetadataReady());
469 EXPECT_THAT(
470 manager->GetCurrentEndpoints(),
471 ElementsAre(
472 ExpectServiceEndpoint(IsEmpty(),
473 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
474 kMetadata1),
475 ExpectServiceEndpoint(IsEmpty(),
476 ElementsAre(MakeIPEndPoint("2001:db8::1", 443)),
477 kMetadata2)));
478 }
479
TEST_F(DnsTaskResultsManagerTest,IPv6TimedoutAfterMetadata)480 TEST_F(DnsTaskResultsManagerTest, IPv6TimedoutAfterMetadata) {
481 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
482
483 // A comes first. Service endpoints creation should be delayed.
484 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
485 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("192.0.2.1")},
486 DnsQueryType::A));
487 manager->ProcessDnsTransactionResults(DnsQueryType::A, results1);
488
489 ASSERT_FALSE(manager->IsMetadataReady());
490 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
491
492 // HTTPS is responded. Service endpoints should not be available because
493 // the manager is waiting for the resolution delay and Chrome doesn't support
494 // ipv6hint yet.
495 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
496 results2.insert(CreateMetadata(kHostName, kMetadatas));
497 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, results2);
498
499 ASSERT_TRUE(manager->IsMetadataReady());
500 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
501
502 // AAAA is timed out. Service endpoints should be available with metadatas.
503 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
504 base::Milliseconds(1));
505
506 ASSERT_TRUE(manager->IsMetadataReady());
507 EXPECT_THAT(
508 manager->GetCurrentEndpoints(),
509 ElementsAre(
510 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
511 IsEmpty(), kMetadata1),
512 ExpectServiceEndpoint(ElementsAre(MakeIPEndPoint("192.0.2.1", 443)),
513 IsEmpty(), kMetadata2)));
514 }
515
TEST_F(DnsTaskResultsManagerTest,IPv4NoDataIPv6TimedoutAfterMetadata)516 TEST_F(DnsTaskResultsManagerTest, IPv4NoDataIPv6TimedoutAfterMetadata) {
517 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
518
519 // HTTPS is responded. Service endpoints should not be available because
520 // the manager is waiting for the resolution delay and Chrome doesn't support
521 // address hints yet.
522 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
523 results1.insert(CreateMetadata(kHostName, kMetadatas));
524 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, results1);
525
526 ASSERT_TRUE(manager->IsMetadataReady());
527 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
528
529 // A is responded with no address. Service endpoints should not be available
530 // since there are no addresses.
531 std::set<std::unique_ptr<HostResolverInternalResult>> results2;
532 results2.insert(CreateNoData(kHostName, DnsQueryType::A));
533 manager->ProcessDnsTransactionResults(DnsQueryType::A, results2);
534
535 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
536
537 // AAAA is timed out. Service endpoints should not be available since there
538 // are no addresses.
539 FastForwardBy(DnsTaskResultsManager::kResolutionDelay +
540 base::Milliseconds(1));
541
542 ASSERT_TRUE(manager->GetCurrentEndpoints().empty());
543 }
544
TEST_F(DnsTaskResultsManagerTest,EndpointOrdering)545 TEST_F(DnsTaskResultsManagerTest, EndpointOrdering) {
546 // Has both IPv4/v6 addresses and metadata.
547 constexpr static const std::string_view kSvcbHost1 = "svc1.example.com";
548 // Has both IPv4/v6 addresses but no metadata.
549 constexpr static const std::string_view kSvcbHost2 = "svc2.example.com";
550 // Only has IPv4 addresses.
551 constexpr static const std::string_view kSvcbHost3 = "svc3.example.com";
552
553 const std::vector<IPEndPoint> kSvcbHost1IPv4s = {MakeIPEndPoint("192.0.2.1")};
554 const std::vector<IPEndPoint> kSvcbHost2IPv4s = {MakeIPEndPoint("192.0.2.2")};
555 const std::vector<IPEndPoint> kSvcbHost3IPv4s = {MakeIPEndPoint("192.0.2.3")};
556
557 const std::vector<IPEndPoint> kSvcbHost1IPv6s = {
558 MakeIPEndPoint("2001:db8::1")};
559 const std::vector<IPEndPoint> kSvcbHost2IPv6s = {
560 MakeIPEndPoint("2001:db8::2")};
561
562 const ConnectionEndpointMetadata kSvcbHost1Metadata1(
563 /*supported_protocol_alpns=*/{"h2", "http/1.1"},
564 /*ech_config_list=*/{},
565 /*target_name=*/std::string(kSvcbHost1));
566 const ConnectionEndpointMetadata kSvcbHost1Metadata2(
567 /*supported_protocol_alpns=*/{"h3"},
568 /*ech_config_list=*/{},
569 /*target_name=*/std::string(kSvcbHost1));
570
571 const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
572 kSvcbHost1Metadatas{{1, kSvcbHost1Metadata1}, {2, kSvcbHost1Metadata2}};
573
574 struct TestData {
575 std::string_view host;
576 std::vector<IPEndPoint> ipv4_endpoints;
577 std::vector<IPEndPoint> ipv6_endpoints;
578 std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas;
579 };
580 const TestData kTestDatas[] = {
581 {kSvcbHost1,
582 /*ipv4_addresses=*/kSvcbHost1IPv4s,
583 /*ipv6_addresses=*/kSvcbHost1IPv6s,
584 /*metadatas=*/kSvcbHost1Metadatas},
585 {kSvcbHost2,
586 /*ipv4_addresses=*/kSvcbHost2IPv4s,
587 /*ipv6_addresses=*/kSvcbHost2IPv6s,
588 /*metadatas=*/{}},
589 {kSvcbHost3, /*ipv4_addresses=*/kSvcbHost3IPv4s,
590 /*ipv6_addresses=*/{}, /*metadatas=*/{}},
591 };
592
593 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
594
595 for (const auto& testdata : kTestDatas) {
596 if (!testdata.ipv4_endpoints.empty()) {
597 std::set<std::unique_ptr<HostResolverInternalResult>> results;
598 results.insert(CreateDataResult(testdata.host, testdata.ipv4_endpoints,
599 DnsQueryType::A));
600 manager->ProcessDnsTransactionResults(DnsQueryType::A, results);
601 }
602 if (!testdata.ipv6_endpoints.empty()) {
603 std::set<std::unique_ptr<HostResolverInternalResult>> results;
604 results.insert(CreateDataResult(testdata.host, testdata.ipv6_endpoints,
605 DnsQueryType::AAAA));
606 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results);
607 }
608 if (!testdata.metadatas.empty()) {
609 std::set<std::unique_ptr<HostResolverInternalResult>> results;
610 results.insert(CreateMetadata(testdata.host, testdata.metadatas));
611 manager->ProcessDnsTransactionResults(DnsQueryType::HTTPS, results);
612 }
613 }
614
615 const std::vector<ServiceEndpoint> kExpects = {
616 ServiceEndpoint(WithPort(kSvcbHost1IPv4s, 443),
617 WithPort(kSvcbHost1IPv6s, 443), kSvcbHost1Metadata1),
618 ServiceEndpoint(WithPort(kSvcbHost1IPv4s, 443),
619 WithPort(kSvcbHost1IPv6s, 443), kSvcbHost1Metadata2),
620 ServiceEndpoint(WithPort(kSvcbHost2IPv4s, 443),
621 WithPort(kSvcbHost2IPv6s, 443),
622 ConnectionEndpointMetadata()),
623 ServiceEndpoint(WithPort(kSvcbHost3IPv4s, 443), {},
624 ConnectionEndpointMetadata()),
625 };
626
627 ASSERT_EQ(manager->GetCurrentEndpoints().size(), kExpects.size());
628 for (size_t i = 0; i < manager->GetCurrentEndpoints().size(); ++i) {
629 SCOPED_TRACE(i);
630 EXPECT_THAT(manager->GetCurrentEndpoints()[i], kExpects[i]);
631 }
632 }
633
TEST_F(DnsTaskResultsManagerTest,Aliases)634 TEST_F(DnsTaskResultsManagerTest, Aliases) {
635 std::unique_ptr<DnsTaskResultsManager> manager = factory().Create();
636
637 // AAAA is responded with aliases.
638 std::set<std::unique_ptr<HostResolverInternalResult>> results1;
639 results1.insert(CreateAlias(kHostName, DnsQueryType::AAAA, kAliasTarget1));
640 results1.insert(
641 CreateAlias(kAliasTarget1, DnsQueryType::AAAA, kAliasTarget2));
642 results1.insert(CreateDataResult(kHostName, {MakeIPEndPoint("2001:db8::1")},
643 DnsQueryType::AAAA));
644 manager->ProcessDnsTransactionResults(DnsQueryType::AAAA, results1);
645
646 EXPECT_THAT(manager->GetCurrentEndpoints(),
647 ElementsAre(ExpectServiceEndpoint(
648 IsEmpty(), ElementsAre(MakeIPEndPoint("2001:db8::1", 443)))));
649 EXPECT_THAT(manager->GetAliases(),
650 UnorderedElementsAre(kHostName, kAliasTarget1, kAliasTarget2));
651 }
652
653 } // namespace net
654