xref: /aosp_15_r20/external/cronet/net/dns/dns_task_results_manager_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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