1 // Copyright 2018 The Chromium Authors. All rights reserved.
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 "services/network/host_resolver.h"
6
7 #include <map>
8 #include <utility>
9 #include <vector>
10
11 #include "base/check.h"
12 #include "base/optional.h"
13 #include "base/run_loop.h"
14 #include "base/test/bind.h"
15 #include "base/test/task_environment.h"
16 #include "base/time/time.h"
17 #include "mojo/public/cpp/bindings/pending_remote.h"
18 #include "mojo/public/cpp/bindings/receiver.h"
19 #include "mojo/public/cpp/bindings/remote.h"
20 #include "net/base/address_list.h"
21 #include "net/base/host_port_pair.h"
22 #include "net/base/ip_address.h"
23 #include "net/base/ip_endpoint.h"
24 #include "net/base/net_errors.h"
25 #include "net/base/network_isolation_key.h"
26 #include "net/dns/context_host_resolver.h"
27 #include "net/dns/dns_config.h"
28 #include "net/dns/dns_test_util.h"
29 #include "net/dns/host_resolver.h"
30 #include "net/dns/host_resolver_manager.h"
31 #include "net/dns/mock_host_resolver.h"
32 #include "net/dns/public/dns_protocol.h"
33 #include "net/dns/public/secure_dns_mode.h"
34 #include "net/log/net_log.h"
35 #include "net/net_buildflags.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 namespace network {
40 namespace {
41
42 class HostResolverTest : public testing::Test {
43 public:
44 HostResolverTest() = default;
45
46 protected:
47 base::test::TaskEnvironment task_environment_{
48 base::test::TaskEnvironment::TimeSource::MOCK_TIME,
49 base::test::TaskEnvironment::MainThreadType::IO};
50 };
51
CreateExpectedEndPoint(const std::string & address,uint16_t port)52 net::IPEndPoint CreateExpectedEndPoint(const std::string& address,
53 uint16_t port) {
54 net::IPAddress ip_address;
55 CHECK(ip_address.AssignFromIPLiteral(address));
56 return net::IPEndPoint(ip_address, port);
57 }
58
59 class TestResolveHostClient : public mojom::ResolveHostClient {
60 public:
61 // If |run_loop| is non-null, will call RunLoop::Quit() on completion.
TestResolveHostClient(mojo::PendingRemote<mojom::ResolveHostClient> * remote,base::RunLoop * run_loop)62 TestResolveHostClient(mojo::PendingRemote<mojom::ResolveHostClient>* remote,
63 base::RunLoop* run_loop)
64 : receiver_(this, remote->InitWithNewPipeAndPassReceiver()),
65 complete_(false),
66 top_level_result_error_(net::ERR_IO_PENDING),
67 result_error_(net::ERR_UNEXPECTED),
68 run_loop_(run_loop) {}
69
CloseReceiver()70 void CloseReceiver() { receiver_.reset(); }
71
OnComplete(int error,const net::ResolveErrorInfo & resolve_error_info,const base::Optional<net::AddressList> & addresses)72 void OnComplete(int error,
73 const net::ResolveErrorInfo& resolve_error_info,
74 const base::Optional<net::AddressList>& addresses) override {
75 DCHECK(!complete_);
76
77 complete_ = true;
78 top_level_result_error_ = error;
79 result_error_ = resolve_error_info.error;
80 result_addresses_ = addresses;
81 if (run_loop_)
82 run_loop_->Quit();
83 }
84
OnTextResults(const std::vector<std::string> & text_results)85 void OnTextResults(const std::vector<std::string>& text_results) override {
86 DCHECK(!complete_);
87 result_text_ = text_results;
88 }
89
OnHostnameResults(const std::vector<net::HostPortPair> & hosts)90 void OnHostnameResults(const std::vector<net::HostPortPair>& hosts) override {
91 DCHECK(!complete_);
92 result_hosts_ = hosts;
93 }
94
complete() const95 bool complete() const { return complete_; }
96
top_level_result_error() const97 int top_level_result_error() const {
98 DCHECK(complete_);
99 return top_level_result_error_;
100 }
101
result_error() const102 int result_error() const {
103 DCHECK(complete_);
104 return result_error_;
105 }
106
result_addresses() const107 const base::Optional<net::AddressList>& result_addresses() const {
108 DCHECK(complete_);
109 return result_addresses_;
110 }
111
result_text() const112 const base::Optional<std::vector<std::string>>& result_text() const {
113 DCHECK(complete_);
114 return result_text_;
115 }
116
result_hosts() const117 const base::Optional<std::vector<net::HostPortPair>>& result_hosts() const {
118 DCHECK(complete_);
119 return result_hosts_;
120 }
121
122 private:
123 mojo::Receiver<mojom::ResolveHostClient> receiver_{this};
124
125 bool complete_;
126 int top_level_result_error_;
127 int result_error_;
128 base::Optional<net::AddressList> result_addresses_;
129 base::Optional<std::vector<std::string>> result_text_;
130 base::Optional<std::vector<net::HostPortPair>> result_hosts_;
131 base::RunLoop* const run_loop_;
132 };
133
134 class TestMdnsListenClient : public mojom::MdnsListenClient {
135 public:
136 using UpdateType = net::HostResolver::MdnsListener::Delegate::UpdateType;
137 using UpdateKey = std::pair<UpdateType, net::DnsQueryType>;
138
TestMdnsListenClient(mojo::PendingRemote<mojom::MdnsListenClient> * remote)139 explicit TestMdnsListenClient(
140 mojo::PendingRemote<mojom::MdnsListenClient>* remote)
141 : receiver_(this, remote->InitWithNewPipeAndPassReceiver()) {}
142
OnAddressResult(UpdateType update_type,net::DnsQueryType result_type,const net::IPEndPoint & address)143 void OnAddressResult(UpdateType update_type,
144 net::DnsQueryType result_type,
145 const net::IPEndPoint& address) override {
146 address_results_.insert({{update_type, result_type}, address});
147 }
148
OnTextResult(UpdateType update_type,net::DnsQueryType result_type,const std::vector<std::string> & text_records)149 void OnTextResult(UpdateType update_type,
150 net::DnsQueryType result_type,
151 const std::vector<std::string>& text_records) override {
152 for (auto& text_record : text_records) {
153 text_results_.insert({{update_type, result_type}, text_record});
154 }
155 }
156
OnHostnameResult(UpdateType update_type,net::DnsQueryType result_type,const net::HostPortPair & host)157 void OnHostnameResult(UpdateType update_type,
158 net::DnsQueryType result_type,
159 const net::HostPortPair& host) override {
160 hostname_results_.insert({{update_type, result_type}, host});
161 }
162
OnUnhandledResult(UpdateType update_type,net::DnsQueryType result_type)163 void OnUnhandledResult(UpdateType update_type,
164 net::DnsQueryType result_type) override {
165 unhandled_results_.insert({update_type, result_type});
166 }
167
address_results()168 const std::multimap<UpdateKey, net::IPEndPoint>& address_results() {
169 return address_results_;
170 }
171
text_results()172 const std::multimap<UpdateKey, std::string>& text_results() {
173 return text_results_;
174 }
175
hostname_results()176 const std::multimap<UpdateKey, net::HostPortPair>& hostname_results() {
177 return hostname_results_;
178 }
179
unhandled_results()180 const std::multiset<UpdateKey>& unhandled_results() {
181 return unhandled_results_;
182 }
183
184 template <typename T>
CreateExpectedResult(UpdateType update_type,net::DnsQueryType query_type,T result)185 static std::pair<UpdateKey, T> CreateExpectedResult(
186 UpdateType update_type,
187 net::DnsQueryType query_type,
188 T result) {
189 return std::make_pair(std::make_pair(update_type, query_type), result);
190 }
191
192 private:
193 mojo::Receiver<mojom::MdnsListenClient> receiver_;
194
195 std::multimap<UpdateKey, net::IPEndPoint> address_results_;
196 std::multimap<UpdateKey, std::string> text_results_;
197 std::multimap<UpdateKey, net::HostPortPair> hostname_results_;
198 std::multiset<UpdateKey> unhandled_results_;
199 };
200
TEST_F(HostResolverTest,Sync)201 TEST_F(HostResolverTest, Sync) {
202 auto inner_resolver = std::make_unique<net::MockHostResolver>();
203 inner_resolver->set_synchronous_mode(true);
204
205 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
206
207 base::RunLoop run_loop;
208 mojo::Remote<mojom::ResolveHostHandle> control_handle;
209 mojom::ResolveHostParametersPtr optional_parameters =
210 mojom::ResolveHostParameters::New();
211 optional_parameters->control_handle =
212 control_handle.BindNewPipeAndPassReceiver();
213 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
214 TestResolveHostClient response_client(&pending_response_client, &run_loop);
215
216 resolver.ResolveHost(
217 net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
218 std::move(optional_parameters), std::move(pending_response_client));
219 run_loop.Run();
220
221 EXPECT_EQ(net::OK, response_client.top_level_result_error());
222 EXPECT_EQ(net::OK, response_client.result_error());
223 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
224 testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
225 EXPECT_FALSE(response_client.result_text());
226 EXPECT_FALSE(response_client.result_hosts());
227 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
228 EXPECT_EQ(net::DEFAULT_PRIORITY, inner_resolver->last_request_priority());
229 }
230
TEST_F(HostResolverTest,Async)231 TEST_F(HostResolverTest, Async) {
232 auto inner_resolver = std::make_unique<net::MockHostResolver>();
233 inner_resolver->set_synchronous_mode(false);
234
235 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
236
237 base::RunLoop run_loop;
238 mojo::Remote<mojom::ResolveHostHandle> control_handle;
239 mojom::ResolveHostParametersPtr optional_parameters =
240 mojom::ResolveHostParameters::New();
241 optional_parameters->control_handle =
242 control_handle.BindNewPipeAndPassReceiver();
243 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
244 TestResolveHostClient response_client(&pending_response_client, &run_loop);
245
246 resolver.ResolveHost(
247 net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
248 std::move(optional_parameters), std::move(pending_response_client));
249
250 bool control_handle_closed = false;
251 auto connection_error_callback =
252 base::BindLambdaForTesting([&]() { control_handle_closed = true; });
253 control_handle.set_disconnect_handler(connection_error_callback);
254 run_loop.Run();
255
256 EXPECT_EQ(net::OK, response_client.result_error());
257 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
258 testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
259 EXPECT_FALSE(response_client.result_text());
260 EXPECT_FALSE(response_client.result_hosts());
261 EXPECT_TRUE(control_handle_closed);
262 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
263 EXPECT_EQ(net::DEFAULT_PRIORITY, inner_resolver->last_request_priority());
264 }
265
TEST_F(HostResolverTest,DnsQueryType)266 TEST_F(HostResolverTest, DnsQueryType) {
267 std::unique_ptr<net::HostResolver> inner_resolver =
268 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
269
270 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
271
272 mojom::ResolveHostParametersPtr optional_parameters =
273 mojom::ResolveHostParameters::New();
274 optional_parameters->dns_query_type = net::DnsQueryType::AAAA;
275
276 base::RunLoop run_loop;
277 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
278 TestResolveHostClient response_client(&pending_response_client, &run_loop);
279
280 resolver.ResolveHost(
281 net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
282 std::move(optional_parameters), std::move(pending_response_client));
283 run_loop.Run();
284
285 EXPECT_EQ(net::OK, response_client.result_error());
286 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
287 testing::ElementsAre(CreateExpectedEndPoint("::1", 160)));
288 }
289
TEST_F(HostResolverTest,InitialPriority)290 TEST_F(HostResolverTest, InitialPriority) {
291 auto inner_resolver = std::make_unique<net::MockHostResolver>();
292
293 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
294
295 mojom::ResolveHostParametersPtr optional_parameters =
296 mojom::ResolveHostParameters::New();
297 optional_parameters->initial_priority = net::HIGHEST;
298
299 base::RunLoop run_loop;
300 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
301 TestResolveHostClient response_client(&pending_response_client, &run_loop);
302
303 resolver.ResolveHost(
304 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
305 std::move(optional_parameters), std::move(pending_response_client));
306 run_loop.Run();
307
308 EXPECT_EQ(net::OK, response_client.result_error());
309 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
310 testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 80)));
311 EXPECT_EQ(net::HIGHEST, inner_resolver->last_request_priority());
312 }
313
314 // Make requests specifying a source for host resolution and ensure the correct
315 // source is requested from the inner resolver.
TEST_F(HostResolverTest,Source)316 TEST_F(HostResolverTest, Source) {
317 constexpr char kDomain[] = "example.com";
318 constexpr char kAnyResult[] = "1.2.3.4";
319 constexpr char kSystemResult[] = "127.0.0.1";
320 constexpr char kDnsResult[] = "168.100.12.23";
321 constexpr char kMdnsResult[] = "200.1.2.3";
322 auto inner_resolver = std::make_unique<net::MockHostResolver>();
323 inner_resolver->rules_map()[net::HostResolverSource::ANY]->AddRule(
324 kDomain, kAnyResult);
325 inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->AddRule(
326 kDomain, kSystemResult);
327 inner_resolver->rules_map()[net::HostResolverSource::DNS]->AddRule(
328 kDomain, kDnsResult);
329 inner_resolver->rules_map()[net::HostResolverSource::MULTICAST_DNS]->AddRule(
330 kDomain, kMdnsResult);
331
332 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
333
334 base::RunLoop any_run_loop;
335 mojo::PendingRemote<mojom::ResolveHostClient> pending_any_client;
336 TestResolveHostClient any_client(&pending_any_client, &any_run_loop);
337 mojom::ResolveHostParametersPtr any_parameters =
338 mojom::ResolveHostParameters::New();
339 any_parameters->source = net::HostResolverSource::ANY;
340 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
341 net::NetworkIsolationKey(), std::move(any_parameters),
342 std::move(pending_any_client));
343
344 base::RunLoop system_run_loop;
345 mojo::PendingRemote<mojom::ResolveHostClient> pending_system_client;
346 TestResolveHostClient system_client(&pending_system_client, &system_run_loop);
347 mojom::ResolveHostParametersPtr system_parameters =
348 mojom::ResolveHostParameters::New();
349 system_parameters->source = net::HostResolverSource::SYSTEM;
350 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
351 net::NetworkIsolationKey(), std::move(system_parameters),
352 std::move(pending_system_client));
353
354 base::RunLoop dns_run_loop;
355 mojo::PendingRemote<mojom::ResolveHostClient> pending_dns_client;
356 TestResolveHostClient dns_client(&pending_dns_client, &dns_run_loop);
357 mojom::ResolveHostParametersPtr dns_parameters =
358 mojom::ResolveHostParameters::New();
359 dns_parameters->source = net::HostResolverSource::DNS;
360 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
361 net::NetworkIsolationKey(), std::move(dns_parameters),
362 std::move(pending_dns_client));
363
364 any_run_loop.Run();
365 system_run_loop.Run();
366 dns_run_loop.Run();
367
368 EXPECT_EQ(net::OK, any_client.result_error());
369 EXPECT_THAT(any_client.result_addresses().value().endpoints(),
370 testing::ElementsAre(CreateExpectedEndPoint(kAnyResult, 80)));
371 EXPECT_EQ(net::OK, system_client.result_error());
372 EXPECT_THAT(system_client.result_addresses().value().endpoints(),
373 testing::ElementsAre(CreateExpectedEndPoint(kSystemResult, 80)));
374 EXPECT_EQ(net::OK, dns_client.result_error());
375 EXPECT_THAT(dns_client.result_addresses().value().endpoints(),
376 testing::ElementsAre(CreateExpectedEndPoint(kDnsResult, 80)));
377
378 #if BUILDFLAG(ENABLE_MDNS)
379 base::RunLoop mdns_run_loop;
380 mojo::PendingRemote<mojom::ResolveHostClient> pending_mdns_client;
381 TestResolveHostClient mdns_client(&pending_mdns_client, &mdns_run_loop);
382 mojom::ResolveHostParametersPtr mdns_parameters =
383 mojom::ResolveHostParameters::New();
384 mdns_parameters->source = net::HostResolverSource::MULTICAST_DNS;
385 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
386 net::NetworkIsolationKey(), std::move(mdns_parameters),
387 std::move(pending_mdns_client));
388
389 mdns_run_loop.Run();
390
391 EXPECT_EQ(net::OK, mdns_client.result_error());
392 EXPECT_THAT(mdns_client.result_addresses().value().endpoints(),
393 testing::ElementsAre(CreateExpectedEndPoint(kMdnsResult, 80)));
394 #endif // BUILDFLAG(ENABLE_MDNS)
395 }
396
397 // Test that cached results are properly keyed by requested source.
TEST_F(HostResolverTest,SeparateCacheBySource)398 TEST_F(HostResolverTest, SeparateCacheBySource) {
399 constexpr char kDomain[] = "example.com";
400 constexpr char kAnyResultOriginal[] = "1.2.3.4";
401 constexpr char kSystemResultOriginal[] = "127.0.0.1";
402 auto inner_resolver = std::make_unique<net::MockCachingHostResolver>();
403 inner_resolver->rules_map()[net::HostResolverSource::ANY]->AddRule(
404 kDomain, kAnyResultOriginal);
405 inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->AddRule(
406 kDomain, kSystemResultOriginal);
407
408 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
409
410 // Load SYSTEM result into cache.
411 base::RunLoop system_run_loop;
412 mojo::PendingRemote<mojom::ResolveHostClient> pending_system_client_ptr;
413 TestResolveHostClient system_client(&pending_system_client_ptr,
414 &system_run_loop);
415 mojom::ResolveHostParametersPtr system_parameters =
416 mojom::ResolveHostParameters::New();
417 system_parameters->source = net::HostResolverSource::SYSTEM;
418 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
419 net::NetworkIsolationKey(), std::move(system_parameters),
420 std::move(pending_system_client_ptr));
421 system_run_loop.Run();
422 ASSERT_EQ(net::OK, system_client.result_error());
423 EXPECT_THAT(
424 system_client.result_addresses().value().endpoints(),
425 testing::ElementsAre(CreateExpectedEndPoint(kSystemResultOriginal, 80)));
426
427 // Change |inner_resolver| rules to ensure results are coming from cache or
428 // not based on whether they resolve to the old or new value.
429 constexpr char kAnyResultFresh[] = "111.222.1.1";
430 constexpr char kSystemResultFresh[] = "111.222.1.2";
431 inner_resolver->rules_map()[net::HostResolverSource::ANY]->ClearRules();
432 inner_resolver->rules_map()[net::HostResolverSource::ANY]->AddRule(
433 kDomain, kAnyResultFresh);
434 inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->ClearRules();
435 inner_resolver->rules_map()[net::HostResolverSource::SYSTEM]->AddRule(
436 kDomain, kSystemResultFresh);
437
438 base::RunLoop cached_run_loop;
439 mojo::PendingRemote<mojom::ResolveHostClient> pending_cached_client;
440 TestResolveHostClient cached_client(&pending_cached_client, &cached_run_loop);
441 mojom::ResolveHostParametersPtr cached_parameters =
442 mojom::ResolveHostParameters::New();
443 cached_parameters->source = net::HostResolverSource::SYSTEM;
444 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
445 net::NetworkIsolationKey(), std::move(cached_parameters),
446 std::move(pending_cached_client));
447
448 base::RunLoop uncached_run_loop;
449 mojo::PendingRemote<mojom::ResolveHostClient> pending_uncached_client;
450 TestResolveHostClient uncached_client(&pending_uncached_client,
451 &uncached_run_loop);
452 mojom::ResolveHostParametersPtr uncached_parameters =
453 mojom::ResolveHostParameters::New();
454 uncached_parameters->source = net::HostResolverSource::ANY;
455 resolver.ResolveHost(
456 net::HostPortPair(kDomain, 80), net::NetworkIsolationKey(),
457 std::move(uncached_parameters), std::move(pending_uncached_client));
458
459 cached_run_loop.Run();
460 uncached_run_loop.Run();
461
462 EXPECT_EQ(net::OK, cached_client.result_error());
463 EXPECT_THAT(
464 cached_client.result_addresses().value().endpoints(),
465 testing::ElementsAre(CreateExpectedEndPoint(kSystemResultOriginal, 80)));
466 EXPECT_EQ(net::OK, uncached_client.result_error());
467 EXPECT_THAT(
468 uncached_client.result_addresses().value().endpoints(),
469 testing::ElementsAre(CreateExpectedEndPoint(kAnyResultFresh, 80)));
470 }
471
TEST_F(HostResolverTest,CacheDisabled)472 TEST_F(HostResolverTest, CacheDisabled) {
473 constexpr char kDomain[] = "example.com";
474 constexpr char kResultOriginal[] = "1.2.3.4";
475 auto inner_resolver = std::make_unique<net::MockCachingHostResolver>();
476 inner_resolver->rules()->AddRule(kDomain, kResultOriginal);
477
478 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
479
480 // Load result into cache.
481 base::RunLoop run_loop;
482 mojo::PendingRemote<mojom::ResolveHostClient> pending_client;
483 TestResolveHostClient client(&pending_client, &run_loop);
484 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
485 net::NetworkIsolationKey(), nullptr,
486 std::move(pending_client));
487 run_loop.Run();
488 ASSERT_EQ(net::OK, client.result_error());
489 EXPECT_THAT(
490 client.result_addresses().value().endpoints(),
491 testing::ElementsAre(CreateExpectedEndPoint(kResultOriginal, 80)));
492
493 // Change |inner_resolver| rules to ensure results are coming from cache or
494 // not based on whether they resolve to the old or new value.
495 constexpr char kResultFresh[] = "111.222.1.1";
496 inner_resolver->rules()->ClearRules();
497 inner_resolver->rules()->AddRule(kDomain, kResultFresh);
498
499 base::RunLoop cached_run_loop;
500 mojo::PendingRemote<mojom::ResolveHostClient> pending_cached_client;
501 TestResolveHostClient cached_client(&pending_cached_client, &cached_run_loop);
502 mojom::ResolveHostParametersPtr cached_parameters =
503 mojom::ResolveHostParameters::New();
504 cached_parameters->cache_usage =
505 mojom::ResolveHostParameters::CacheUsage::ALLOWED;
506 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
507 net::NetworkIsolationKey(), std::move(cached_parameters),
508 std::move(pending_cached_client));
509 cached_run_loop.Run();
510
511 EXPECT_EQ(net::OK, cached_client.result_error());
512 EXPECT_THAT(
513 cached_client.result_addresses().value().endpoints(),
514 testing::ElementsAre(CreateExpectedEndPoint(kResultOriginal, 80)));
515
516 base::RunLoop uncached_run_loop;
517 mojo::PendingRemote<mojom::ResolveHostClient> pending_uncached_client;
518 TestResolveHostClient uncached_client(&pending_uncached_client,
519 &uncached_run_loop);
520 mojom::ResolveHostParametersPtr uncached_parameters =
521 mojom::ResolveHostParameters::New();
522 uncached_parameters->cache_usage =
523 mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
524 resolver.ResolveHost(
525 net::HostPortPair(kDomain, 80), net::NetworkIsolationKey(),
526 std::move(uncached_parameters), std::move(pending_uncached_client));
527 uncached_run_loop.Run();
528
529 EXPECT_EQ(net::OK, uncached_client.result_error());
530 EXPECT_THAT(uncached_client.result_addresses().value().endpoints(),
531 testing::ElementsAre(CreateExpectedEndPoint(kResultFresh, 80)));
532 }
533
TEST_F(HostResolverTest,CacheStaleAllowed)534 TEST_F(HostResolverTest, CacheStaleAllowed) {
535 constexpr char kDomain[] = "example.com";
536 constexpr char kResultOriginal[] = "1.2.3.4";
537 auto inner_resolver = std::make_unique<net::MockCachingHostResolver>();
538 inner_resolver->rules()->AddRule(kDomain, kResultOriginal);
539
540 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
541
542 // Load result into cache.
543 base::RunLoop run_loop;
544 mojo::PendingRemote<mojom::ResolveHostClient> pending_client;
545 TestResolveHostClient client(&pending_client, &run_loop);
546 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
547 net::NetworkIsolationKey(), nullptr,
548 std::move(pending_client));
549 run_loop.Run();
550 ASSERT_EQ(net::OK, client.result_error());
551 EXPECT_THAT(
552 client.result_addresses().value().endpoints(),
553 testing::ElementsAre(CreateExpectedEndPoint(kResultOriginal, 80)));
554
555 // Change |inner_resolver| rules to ensure results are coming from cache or
556 // not based on whether they resolve to the old or new value.
557 constexpr char kResultFresh[] = "111.222.1.1";
558 inner_resolver->rules()->ClearRules();
559 inner_resolver->rules()->AddRule(kDomain, kResultFresh);
560
561 // MockHostResolver gives cache entries a 1 min TTL, so simulate a day
562 // passing, which is more than long enough for the cached results to become
563 // stale.
564 task_environment_.FastForwardBy(base::TimeDelta::FromDays(1));
565
566 // Fetching stale results returns the original cached value.
567 base::RunLoop cached_run_loop;
568 mojo::PendingRemote<mojom::ResolveHostClient> pending_cached_client;
569 TestResolveHostClient cached_client(&pending_cached_client, &cached_run_loop);
570 mojom::ResolveHostParametersPtr cached_parameters =
571 mojom::ResolveHostParameters::New();
572 cached_parameters->cache_usage =
573 mojom::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
574 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
575 net::NetworkIsolationKey(), std::move(cached_parameters),
576 std::move(pending_cached_client));
577 cached_run_loop.Run();
578
579 EXPECT_EQ(net::OK, cached_client.result_error());
580 EXPECT_THAT(
581 cached_client.result_addresses().value().endpoints(),
582 testing::ElementsAre(CreateExpectedEndPoint(kResultOriginal, 80)));
583
584 // Resolution where only non-stale cache usage is allowed returns the new
585 // value.
586 base::RunLoop uncached_run_loop;
587 mojo::PendingRemote<mojom::ResolveHostClient> pending_uncached_client;
588 TestResolveHostClient uncached_client(&pending_uncached_client,
589 &uncached_run_loop);
590 mojom::ResolveHostParametersPtr uncached_parameters =
591 mojom::ResolveHostParameters::New();
592 uncached_parameters->cache_usage =
593 mojom::ResolveHostParameters::CacheUsage::ALLOWED;
594 resolver.ResolveHost(
595 net::HostPortPair(kDomain, 80), net::NetworkIsolationKey(),
596 std::move(uncached_parameters), std::move(pending_uncached_client));
597 uncached_run_loop.Run();
598
599 EXPECT_EQ(net::OK, uncached_client.result_error());
600 EXPECT_THAT(uncached_client.result_addresses().value().endpoints(),
601 testing::ElementsAre(CreateExpectedEndPoint(kResultFresh, 80)));
602 }
603
604 // Test for a resolve with a result only in the cache and error if the cache is
605 // disabled.
TEST_F(HostResolverTest,CacheDisabled_ErrorResults)606 TEST_F(HostResolverTest, CacheDisabled_ErrorResults) {
607 constexpr char kDomain[] = "example.com";
608 constexpr char kResult[] = "1.2.3.4";
609 auto inner_resolver = std::make_unique<net::MockCachingHostResolver>();
610 inner_resolver->rules()->AddRule(kDomain, kResult);
611
612 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
613
614 // Load initial result into cache.
615 base::RunLoop run_loop;
616 mojo::PendingRemote<mojom::ResolveHostClient> pending_client;
617 TestResolveHostClient client(&pending_client, &run_loop);
618 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
619 net::NetworkIsolationKey(), nullptr,
620 std::move(pending_client));
621 run_loop.Run();
622 ASSERT_EQ(net::OK, client.result_error());
623
624 // Change |inner_resolver| rules to an error.
625 inner_resolver->rules()->ClearRules();
626 inner_resolver->rules()->AddSimulatedFailure(kDomain);
627
628 // Resolves for |kFreshErrorDomain| should result in error only when cache is
629 // disabled because success was cached.
630 base::RunLoop cached_run_loop;
631 mojo::PendingRemote<mojom::ResolveHostClient> pending_cached_client;
632 TestResolveHostClient cached_client(&pending_cached_client, &cached_run_loop);
633 mojom::ResolveHostParametersPtr cached_parameters =
634 mojom::ResolveHostParameters::New();
635 cached_parameters->cache_usage =
636 mojom::ResolveHostParameters::CacheUsage::ALLOWED;
637 resolver.ResolveHost(net::HostPortPair(kDomain, 80),
638 net::NetworkIsolationKey(), std::move(cached_parameters),
639 std::move(pending_cached_client));
640 cached_run_loop.Run();
641 EXPECT_EQ(net::OK, cached_client.result_error());
642
643 base::RunLoop uncached_run_loop;
644 mojo::PendingRemote<mojom::ResolveHostClient> pending_uncached_client;
645 TestResolveHostClient uncached_client(&pending_uncached_client,
646 &uncached_run_loop);
647 mojom::ResolveHostParametersPtr uncached_parameters =
648 mojom::ResolveHostParameters::New();
649 uncached_parameters->cache_usage =
650 mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
651 resolver.ResolveHost(
652 net::HostPortPair(kDomain, 80), net::NetworkIsolationKey(),
653 std::move(uncached_parameters), std::move(pending_uncached_client));
654 uncached_run_loop.Run();
655 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, uncached_client.result_error());
656 }
657
TEST_F(HostResolverTest,IncludeCanonicalName)658 TEST_F(HostResolverTest, IncludeCanonicalName) {
659 auto inner_resolver = std::make_unique<net::MockHostResolver>();
660 inner_resolver->rules()->AddRuleWithFlags("example.com", "123.0.12.24",
661 net::HOST_RESOLVER_CANONNAME,
662 "canonicalexample.com");
663
664 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
665
666 mojom::ResolveHostParametersPtr optional_parameters =
667 mojom::ResolveHostParameters::New();
668 optional_parameters->include_canonical_name = true;
669
670 base::RunLoop run_loop;
671 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
672 TestResolveHostClient response_client(&pending_response_client, &run_loop);
673
674 resolver.ResolveHost(
675 net::HostPortPair("example.com", 80), net::NetworkIsolationKey(),
676 std::move(optional_parameters), std::move(pending_response_client));
677 run_loop.Run();
678
679 EXPECT_EQ(net::OK, response_client.result_error());
680 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
681 testing::ElementsAre(CreateExpectedEndPoint("123.0.12.24", 80)));
682 EXPECT_EQ("canonicalexample.com",
683 response_client.result_addresses().value().canonical_name());
684 }
685
TEST_F(HostResolverTest,LoopbackOnly)686 TEST_F(HostResolverTest, LoopbackOnly) {
687 auto inner_resolver = std::make_unique<net::MockHostResolver>();
688 inner_resolver->rules()->AddRuleWithFlags("example.com", "127.0.12.24",
689 net::HOST_RESOLVER_LOOPBACK_ONLY);
690
691 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
692
693 mojom::ResolveHostParametersPtr optional_parameters =
694 mojom::ResolveHostParameters::New();
695 optional_parameters->loopback_only = true;
696
697 base::RunLoop run_loop;
698 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
699 TestResolveHostClient response_client(&pending_response_client, &run_loop);
700
701 resolver.ResolveHost(
702 net::HostPortPair("example.com", 80), net::NetworkIsolationKey(),
703 std::move(optional_parameters), std::move(pending_response_client));
704 run_loop.Run();
705
706 EXPECT_EQ(net::OK, response_client.result_error());
707 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
708 testing::ElementsAre(CreateExpectedEndPoint("127.0.12.24", 80)));
709 }
710
TEST_F(HostResolverTest,SecureDnsModeOverride)711 TEST_F(HostResolverTest, SecureDnsModeOverride) {
712 auto inner_resolver = std::make_unique<net::MockHostResolver>();
713
714 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
715
716 mojom::ResolveHostParametersPtr optional_parameters =
717 mojom::ResolveHostParameters::New();
718 optional_parameters->secure_dns_mode_override =
719 network::mojom::OptionalSecureDnsMode::SECURE;
720
721 base::RunLoop run_loop;
722 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
723 TestResolveHostClient response_client(&pending_response_client, &run_loop);
724
725 resolver.ResolveHost(
726 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
727 std::move(optional_parameters), std::move(pending_response_client));
728 run_loop.Run();
729
730 EXPECT_EQ(net::OK, response_client.result_error());
731 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
732 testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 80)));
733 EXPECT_EQ(net::SecureDnsMode::kSecure,
734 inner_resolver->last_secure_dns_mode_override().value());
735 }
736
TEST_F(HostResolverTest,Failure_Sync)737 TEST_F(HostResolverTest, Failure_Sync) {
738 auto inner_resolver = std::make_unique<net::MockHostResolver>();
739 inner_resolver->rules()->AddSimulatedFailure("example.com");
740 inner_resolver->set_synchronous_mode(true);
741
742 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
743
744 base::RunLoop run_loop;
745 mojo::Remote<mojom::ResolveHostHandle> control_handle;
746 mojom::ResolveHostParametersPtr optional_parameters =
747 mojom::ResolveHostParameters::New();
748 optional_parameters->control_handle =
749 control_handle.BindNewPipeAndPassReceiver();
750 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
751 TestResolveHostClient response_client(&pending_response_client, &run_loop);
752
753 resolver.ResolveHost(
754 net::HostPortPair("example.com", 160), net::NetworkIsolationKey(),
755 std::move(optional_parameters), std::move(pending_response_client));
756 run_loop.Run();
757
758 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED,
759 response_client.top_level_result_error());
760 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, response_client.result_error());
761 EXPECT_FALSE(response_client.result_addresses());
762 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
763 }
764
TEST_F(HostResolverTest,Failure_Async)765 TEST_F(HostResolverTest, Failure_Async) {
766 auto inner_resolver = std::make_unique<net::MockHostResolver>();
767 inner_resolver->rules()->AddSimulatedFailure("example.com");
768 inner_resolver->set_synchronous_mode(false);
769
770 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
771
772 base::RunLoop run_loop;
773 mojo::Remote<mojom::ResolveHostHandle> control_handle;
774 mojom::ResolveHostParametersPtr optional_parameters =
775 mojom::ResolveHostParameters::New();
776 optional_parameters->control_handle =
777 control_handle.BindNewPipeAndPassReceiver();
778 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
779 TestResolveHostClient response_client(&pending_response_client, &run_loop);
780
781 resolver.ResolveHost(
782 net::HostPortPair("example.com", 160), net::NetworkIsolationKey(),
783 std::move(optional_parameters), std::move(pending_response_client));
784
785 bool control_handle_closed = false;
786 auto connection_error_callback =
787 base::BindLambdaForTesting([&]() { control_handle_closed = true; });
788 control_handle.set_disconnect_handler(connection_error_callback);
789 run_loop.Run();
790
791 EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, response_client.result_error());
792 EXPECT_FALSE(response_client.result_addresses());
793 EXPECT_TRUE(control_handle_closed);
794 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
795 }
796
TEST_F(HostResolverTest,NetworkIsolationKey)797 TEST_F(HostResolverTest, NetworkIsolationKey) {
798 const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
799 const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
800
801 auto inner_resolver = std::make_unique<net::MockHostResolver>();
802
803 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
804
805 base::RunLoop run_loop;
806 mojo::Remote<mojom::ResolveHostHandle> control_handle;
807 mojom::ResolveHostParametersPtr optional_parameters =
808 mojom::ResolveHostParameters::New();
809 optional_parameters->control_handle =
810 control_handle.BindNewPipeAndPassReceiver();
811 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
812 TestResolveHostClient response_client(&pending_response_client, &run_loop);
813
814 resolver.ResolveHost(net::HostPortPair("localhost", 160),
815 kNetworkIsolationKey, std::move(optional_parameters),
816 std::move(pending_response_client));
817 run_loop.Run();
818
819 EXPECT_EQ(net::OK, response_client.result_error());
820 EXPECT_THAT(response_client.result_addresses().value().endpoints(),
821 testing::ElementsAre(CreateExpectedEndPoint("127.0.0.1", 160)));
822 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
823 EXPECT_EQ(kNetworkIsolationKey,
824 inner_resolver->last_request_network_isolation_key());
825 }
826
TEST_F(HostResolverTest,NoOptionalParameters)827 TEST_F(HostResolverTest, NoOptionalParameters) {
828 std::unique_ptr<net::HostResolver> inner_resolver =
829 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
830
831 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
832
833 base::RunLoop run_loop;
834 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
835 TestResolveHostClient response_client(&pending_response_client, &run_loop);
836
837 // Resolve "localhost" because it should always resolve fast and locally, even
838 // when using a real HostResolver.
839 resolver.ResolveHost(net::HostPortPair("localhost", 80),
840 net::NetworkIsolationKey(), nullptr,
841 std::move(pending_response_client));
842 run_loop.Run();
843
844 EXPECT_EQ(net::OK, response_client.result_error());
845 EXPECT_THAT(
846 response_client.result_addresses().value().endpoints(),
847 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 80),
848 CreateExpectedEndPoint("::1", 80)));
849 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
850 }
851
TEST_F(HostResolverTest,NoControlHandle)852 TEST_F(HostResolverTest, NoControlHandle) {
853 std::unique_ptr<net::HostResolver> inner_resolver =
854 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
855
856 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
857
858 base::RunLoop run_loop;
859 mojom::ResolveHostParametersPtr optional_parameters =
860 mojom::ResolveHostParameters::New();
861 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
862 TestResolveHostClient response_client(&pending_response_client, &run_loop);
863
864 // Resolve "localhost" because it should always resolve fast and locally, even
865 // when using a real HostResolver.
866 resolver.ResolveHost(
867 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
868 std::move(optional_parameters), std::move(pending_response_client));
869 run_loop.Run();
870
871 EXPECT_EQ(net::OK, response_client.result_error());
872 EXPECT_THAT(
873 response_client.result_addresses().value().endpoints(),
874 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 80),
875 CreateExpectedEndPoint("::1", 80)));
876 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
877 }
878
TEST_F(HostResolverTest,CloseControlHandle)879 TEST_F(HostResolverTest, CloseControlHandle) {
880 std::unique_ptr<net::HostResolver> inner_resolver =
881 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
882
883 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
884
885 base::RunLoop run_loop;
886 mojo::Remote<mojom::ResolveHostHandle> control_handle;
887 mojom::ResolveHostParametersPtr optional_parameters =
888 mojom::ResolveHostParameters::New();
889 optional_parameters->control_handle =
890 control_handle.BindNewPipeAndPassReceiver();
891 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
892 TestResolveHostClient response_client(&pending_response_client, &run_loop);
893
894 // Resolve "localhost" because it should always resolve fast and locally, even
895 // when using a real HostResolver.
896 resolver.ResolveHost(
897 net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
898 std::move(optional_parameters), std::move(pending_response_client));
899 control_handle.reset();
900 run_loop.Run();
901
902 EXPECT_EQ(net::OK, response_client.result_error());
903 EXPECT_THAT(
904 response_client.result_addresses().value().endpoints(),
905 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 160),
906 CreateExpectedEndPoint("::1", 160)));
907 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
908 }
909
TEST_F(HostResolverTest,Cancellation)910 TEST_F(HostResolverTest, Cancellation) {
911 // Use a HangingHostResolver, so the test can ensure the request won't be
912 // completed before the cancellation arrives.
913 auto inner_resolver = std::make_unique<net::HangingHostResolver>();
914
915 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
916
917 ASSERT_EQ(0, inner_resolver->num_cancellations());
918
919 base::RunLoop run_loop;
920 mojo::Remote<mojom::ResolveHostHandle> control_handle;
921 mojom::ResolveHostParametersPtr optional_parameters =
922 mojom::ResolveHostParameters::New();
923 optional_parameters->control_handle =
924 control_handle.BindNewPipeAndPassReceiver();
925 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
926 TestResolveHostClient response_client(&pending_response_client, &run_loop);
927
928 resolver.ResolveHost(
929 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
930 std::move(optional_parameters), std::move(pending_response_client));
931 bool control_handle_closed = false;
932 auto connection_error_callback =
933 base::BindLambdaForTesting([&]() { control_handle_closed = true; });
934 control_handle.set_disconnect_handler(connection_error_callback);
935
936 control_handle->Cancel(net::ERR_ABORTED);
937 run_loop.Run();
938
939 // On cancellation, should receive an ERR_FAILED result, and the internal
940 // resolver request should have been cancelled.
941 EXPECT_EQ(net::ERR_ABORTED, response_client.result_error());
942 EXPECT_FALSE(response_client.result_addresses());
943 EXPECT_EQ(1, inner_resolver->num_cancellations());
944 EXPECT_TRUE(control_handle_closed);
945 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
946 }
947
TEST_F(HostResolverTest,Cancellation_SubsequentRequest)948 TEST_F(HostResolverTest, Cancellation_SubsequentRequest) {
949 std::unique_ptr<net::HostResolver> inner_resolver =
950 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
951
952 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
953
954 base::RunLoop run_loop;
955 mojo::Remote<mojom::ResolveHostHandle> control_handle;
956 mojom::ResolveHostParametersPtr optional_parameters =
957 mojom::ResolveHostParameters::New();
958 optional_parameters->control_handle =
959 control_handle.BindNewPipeAndPassReceiver();
960 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
961 TestResolveHostClient response_client(&pending_response_client, nullptr);
962
963 resolver.ResolveHost(
964 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
965 std::move(optional_parameters), std::move(pending_response_client));
966
967 control_handle->Cancel(net::ERR_ABORTED);
968 run_loop.RunUntilIdle();
969
970 // Not using a hanging resolver, so could be ERR_ABORTED or OK depending on
971 // timing of the cancellation.
972 EXPECT_TRUE(response_client.result_error() == net::ERR_ABORTED ||
973 response_client.result_error() == net::OK);
974 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
975
976 // Subsequent requests should be unaffected by the cancellation.
977 base::RunLoop run_loop2;
978 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client2;
979 TestResolveHostClient response_client2(&pending_response_client2, &run_loop2);
980 resolver.ResolveHost(net::HostPortPair("localhost", 80),
981 net::NetworkIsolationKey(), nullptr,
982 std::move(pending_response_client2));
983 run_loop2.Run();
984
985 EXPECT_EQ(net::OK, response_client2.result_error());
986 EXPECT_THAT(
987 response_client2.result_addresses().value().endpoints(),
988 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 80),
989 CreateExpectedEndPoint("::1", 80)));
990 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
991 }
992
TEST_F(HostResolverTest,DestroyResolver)993 TEST_F(HostResolverTest, DestroyResolver) {
994 // Use a HangingHostResolver, so the test can ensure the request won't be
995 // completed before the cancellation arrives.
996 auto inner_resolver = std::make_unique<net::HangingHostResolver>();
997
998 auto resolver =
999 std::make_unique<HostResolver>(inner_resolver.get(), net::NetLog::Get());
1000
1001 ASSERT_EQ(0, inner_resolver->num_cancellations());
1002
1003 base::RunLoop run_loop;
1004 mojo::Remote<mojom::ResolveHostHandle> control_handle;
1005 mojom::ResolveHostParametersPtr optional_parameters =
1006 mojom::ResolveHostParameters::New();
1007 optional_parameters->control_handle =
1008 control_handle.BindNewPipeAndPassReceiver();
1009 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1010 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1011
1012 resolver->ResolveHost(
1013 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
1014 std::move(optional_parameters), std::move(pending_response_client));
1015 bool control_handle_closed = false;
1016 auto connection_error_callback =
1017 base::BindLambdaForTesting([&]() { control_handle_closed = true; });
1018 control_handle.set_disconnect_handler(connection_error_callback);
1019
1020 resolver = nullptr;
1021 run_loop.Run();
1022
1023 // On context destruction, should receive an ERR_FAILED result, and the
1024 // internal resolver request should have been cancelled.
1025 EXPECT_EQ(net::ERR_FAILED, response_client.result_error());
1026 EXPECT_FALSE(response_client.result_addresses());
1027 EXPECT_EQ(1, inner_resolver->num_cancellations());
1028 EXPECT_TRUE(control_handle_closed);
1029 }
1030
TEST_F(HostResolverTest,CloseClient)1031 TEST_F(HostResolverTest, CloseClient) {
1032 // Use a HangingHostResolver, so the test can ensure the request won't be
1033 // completed before the cancellation arrives.
1034 auto inner_resolver = std::make_unique<net::HangingHostResolver>();
1035
1036 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1037
1038 ASSERT_EQ(0, inner_resolver->num_cancellations());
1039
1040 base::RunLoop run_loop;
1041 mojo::Remote<mojom::ResolveHostHandle> control_handle;
1042 mojom::ResolveHostParametersPtr optional_parameters =
1043 mojom::ResolveHostParameters::New();
1044 optional_parameters->control_handle =
1045 control_handle.BindNewPipeAndPassReceiver();
1046 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1047 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1048
1049 resolver.ResolveHost(
1050 net::HostPortPair("localhost", 80), net::NetworkIsolationKey(),
1051 std::move(optional_parameters), std::move(pending_response_client));
1052 bool control_handle_closed = false;
1053 auto connection_error_callback =
1054 base::BindLambdaForTesting([&]() { control_handle_closed = true; });
1055 control_handle.set_disconnect_handler(connection_error_callback);
1056
1057 response_client.CloseReceiver();
1058 run_loop.RunUntilIdle();
1059
1060 // Response pipe is closed, so no results to check. Internal request should be
1061 // cancelled.
1062 EXPECT_FALSE(response_client.complete());
1063 EXPECT_EQ(1, inner_resolver->num_cancellations());
1064 EXPECT_TRUE(control_handle_closed);
1065 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1066 }
1067
TEST_F(HostResolverTest,CloseClient_SubsequentRequest)1068 TEST_F(HostResolverTest, CloseClient_SubsequentRequest) {
1069 std::unique_ptr<net::HostResolver> inner_resolver =
1070 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
1071
1072 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1073
1074 base::RunLoop run_loop;
1075 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1076 TestResolveHostClient response_client(&pending_response_client, nullptr);
1077
1078 resolver.ResolveHost(net::HostPortPair("localhost", 80),
1079 net::NetworkIsolationKey(), nullptr,
1080 std::move(pending_response_client));
1081
1082 response_client.CloseReceiver();
1083 run_loop.RunUntilIdle();
1084
1085 // Not using a hanging resolver, so could be incomplete or OK depending on
1086 // timing of the cancellation.
1087 EXPECT_TRUE(!response_client.complete() ||
1088 response_client.result_error() == net::OK);
1089 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1090
1091 // Subsequent requests should be unaffected by the cancellation.
1092 base::RunLoop run_loop2;
1093 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client2;
1094 TestResolveHostClient response_client2(&pending_response_client2, &run_loop2);
1095 resolver.ResolveHost(net::HostPortPair("localhost", 80),
1096 net::NetworkIsolationKey(), nullptr,
1097 std::move(pending_response_client2));
1098 run_loop2.Run();
1099
1100 EXPECT_EQ(net::OK, response_client2.result_error());
1101 EXPECT_THAT(
1102 response_client2.result_addresses().value().endpoints(),
1103 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 80),
1104 CreateExpectedEndPoint("::1", 80)));
1105 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1106 }
1107
TEST_F(HostResolverTest,Binding)1108 TEST_F(HostResolverTest, Binding) {
1109 mojo::Remote<mojom::HostResolver> resolver_remote;
1110 HostResolver* shutdown_resolver = nullptr;
1111 HostResolver::ConnectionShutdownCallback shutdown_callback =
1112 base::BindLambdaForTesting(
1113 [&](HostResolver* resolver) { shutdown_resolver = resolver; });
1114
1115 std::unique_ptr<net::HostResolver> inner_resolver =
1116 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
1117
1118 HostResolver resolver(resolver_remote.BindNewPipeAndPassReceiver(),
1119 std::move(shutdown_callback), inner_resolver.get(),
1120 net::NetLog::Get());
1121
1122 base::RunLoop run_loop;
1123 mojo::Remote<mojom::ResolveHostHandle> control_handle;
1124 mojom::ResolveHostParametersPtr optional_parameters =
1125 mojom::ResolveHostParameters::New();
1126 optional_parameters->control_handle =
1127 control_handle.BindNewPipeAndPassReceiver();
1128 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1129 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1130
1131 // Resolve "localhost" because it should always resolve fast and locally, even
1132 // when using a real HostResolver.
1133 resolver_remote->ResolveHost(
1134 net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
1135 std::move(optional_parameters), std::move(pending_response_client));
1136 run_loop.Run();
1137
1138 EXPECT_EQ(net::OK, response_client.result_error());
1139 EXPECT_THAT(
1140 response_client.result_addresses().value().endpoints(),
1141 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 160),
1142 CreateExpectedEndPoint("::1", 160)));
1143 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1144 EXPECT_FALSE(shutdown_resolver);
1145 }
1146
TEST_F(HostResolverTest,CloseBinding)1147 TEST_F(HostResolverTest, CloseBinding) {
1148 mojo::Remote<mojom::HostResolver> resolver_remote;
1149 HostResolver* shutdown_resolver = nullptr;
1150 HostResolver::ConnectionShutdownCallback shutdown_callback =
1151 base::BindLambdaForTesting(
1152 [&](HostResolver* resolver) { shutdown_resolver = resolver; });
1153
1154 // Use a HangingHostResolver, so the test can ensure the request won't be
1155 // completed before the cancellation arrives.
1156 auto inner_resolver = std::make_unique<net::HangingHostResolver>();
1157
1158 HostResolver resolver(resolver_remote.BindNewPipeAndPassReceiver(),
1159 std::move(shutdown_callback), inner_resolver.get(),
1160 net::NetLog::Get());
1161
1162 ASSERT_EQ(0, inner_resolver->num_cancellations());
1163
1164 base::RunLoop run_loop;
1165 mojo::Remote<mojom::ResolveHostHandle> control_handle;
1166 mojom::ResolveHostParametersPtr optional_parameters =
1167 mojom::ResolveHostParameters::New();
1168 optional_parameters->control_handle =
1169 control_handle.BindNewPipeAndPassReceiver();
1170 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1171 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1172 resolver_remote->ResolveHost(
1173 net::HostPortPair("localhost", 160), net::NetworkIsolationKey(),
1174 std::move(optional_parameters), std::move(pending_response_client));
1175 bool control_handle_closed = false;
1176 auto connection_error_callback =
1177 base::BindLambdaForTesting([&]() { control_handle_closed = true; });
1178 control_handle.set_disconnect_handler(connection_error_callback);
1179
1180 resolver_remote.reset();
1181 run_loop.Run();
1182
1183 // Request should be cancelled.
1184 EXPECT_EQ(net::ERR_FAILED, response_client.result_error());
1185 EXPECT_FALSE(response_client.result_addresses());
1186 EXPECT_TRUE(control_handle_closed);
1187 EXPECT_EQ(1, inner_resolver->num_cancellations());
1188 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1189
1190 // Callback should have been called.
1191 EXPECT_EQ(&resolver, shutdown_resolver);
1192 }
1193
TEST_F(HostResolverTest,CloseBinding_SubsequentRequest)1194 TEST_F(HostResolverTest, CloseBinding_SubsequentRequest) {
1195 mojo::Remote<mojom::HostResolver> resolver_remote;
1196 HostResolver* shutdown_resolver = nullptr;
1197 HostResolver::ConnectionShutdownCallback shutdown_callback =
1198 base::BindLambdaForTesting(
1199 [&](HostResolver* resolver) { shutdown_resolver = resolver; });
1200
1201 std::unique_ptr<net::HostResolver> inner_resolver =
1202 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
1203
1204 HostResolver resolver(resolver_remote.BindNewPipeAndPassReceiver(),
1205 std::move(shutdown_callback), inner_resolver.get(),
1206 net::NetLog::Get());
1207
1208 base::RunLoop run_loop;
1209 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1210 TestResolveHostClient response_client(&pending_response_client, nullptr);
1211 resolver_remote->ResolveHost(net::HostPortPair("localhost", 160),
1212 net::NetworkIsolationKey(), nullptr,
1213 std::move(pending_response_client));
1214
1215 resolver_remote.reset();
1216 run_loop.RunUntilIdle();
1217
1218 // Not using a hanging resolver, so could be ERR_FAILED or OK depending on
1219 // timing of the cancellation.
1220 EXPECT_TRUE(response_client.result_error() == net::ERR_FAILED ||
1221 response_client.result_error() == net::OK);
1222 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1223
1224 // Callback should have been called.
1225 EXPECT_EQ(&resolver, shutdown_resolver);
1226
1227 // Subsequent requests should be unaffected by the cancellation.
1228 base::RunLoop run_loop2;
1229 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client2;
1230 TestResolveHostClient response_client2(&pending_response_client2, &run_loop2);
1231 resolver.ResolveHost(net::HostPortPair("localhost", 80),
1232 net::NetworkIsolationKey(), nullptr,
1233 std::move(pending_response_client2));
1234 run_loop2.Run();
1235
1236 EXPECT_EQ(net::OK, response_client2.result_error());
1237 EXPECT_THAT(
1238 response_client2.result_addresses().value().endpoints(),
1239 testing::UnorderedElementsAre(CreateExpectedEndPoint("127.0.0.1", 80),
1240 CreateExpectedEndPoint("::1", 80)));
1241 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1242 }
1243
TEST_F(HostResolverTest,IsSpeculative)1244 TEST_F(HostResolverTest, IsSpeculative) {
1245 std::unique_ptr<net::HostResolver> inner_resolver =
1246 net::HostResolver::CreateStandaloneResolver(net::NetLog::Get());
1247
1248 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1249
1250 base::RunLoop run_loop;
1251 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1252 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1253 mojom::ResolveHostParametersPtr parameters =
1254 mojom::ResolveHostParameters::New();
1255 parameters->is_speculative = true;
1256
1257 // Resolve "localhost" because it should always resolve fast and locally, even
1258 // when using a real HostResolver.
1259 resolver.ResolveHost(net::HostPortPair("localhost", 80),
1260 net::NetworkIsolationKey(), std::move(parameters),
1261 std::move(pending_response_client));
1262 run_loop.Run();
1263
1264 EXPECT_EQ(net::OK, response_client.result_error());
1265 EXPECT_FALSE(response_client.result_addresses());
1266 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1267 }
1268
CreateValidDnsConfig()1269 net::DnsConfig CreateValidDnsConfig() {
1270 net::IPAddress dns_ip(192, 168, 1, 0);
1271 net::DnsConfig config;
1272 config.nameservers.push_back(
1273 net::IPEndPoint(dns_ip, net::dns_protocol::kDefaultPort));
1274 EXPECT_TRUE(config.IsValid());
1275 return config;
1276 }
1277
TEST_F(HostResolverTest,TextResults)1278 TEST_F(HostResolverTest, TextResults) {
1279 static const char* kTextRecords[] = {"foo", "bar", "more text"};
1280 net::MockDnsClientRuleList rules;
1281 rules.emplace_back(
1282 "example.com", net::dns_protocol::kTypeTXT, false /* secure */,
1283 net::MockDnsClientRule::Result(net::BuildTestDnsTextResponse(
1284 "example.com", {std::vector<std::string>(std::begin(kTextRecords),
1285 std::end(kTextRecords))})),
1286 false /* delay */);
1287 auto dns_client = std::make_unique<net::MockDnsClient>(CreateValidDnsConfig(),
1288 std::move(rules));
1289 dns_client->set_ignore_system_config_changes(true);
1290
1291 std::unique_ptr<net::ContextHostResolver> inner_resolver =
1292 net::HostResolver::CreateStandaloneContextResolver(net::NetLog::Get());
1293 inner_resolver->GetManagerForTesting()->SetDnsClientForTesting(
1294 std::move(dns_client));
1295 inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(true);
1296
1297 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1298
1299 base::RunLoop run_loop;
1300 mojom::ResolveHostParametersPtr optional_parameters =
1301 mojom::ResolveHostParameters::New();
1302 optional_parameters->dns_query_type = net::DnsQueryType::TXT;
1303 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1304 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1305
1306 resolver.ResolveHost(
1307 net::HostPortPair("example.com", 160), net::NetworkIsolationKey(),
1308 std::move(optional_parameters), std::move(pending_response_client));
1309 run_loop.Run();
1310
1311 EXPECT_EQ(net::OK, response_client.result_error());
1312 EXPECT_FALSE(response_client.result_addresses());
1313 EXPECT_THAT(response_client.result_text(),
1314 testing::Optional(testing::ElementsAreArray(kTextRecords)));
1315 EXPECT_FALSE(response_client.result_hosts());
1316 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1317 }
1318
TEST_F(HostResolverTest,HostResults)1319 TEST_F(HostResolverTest, HostResults) {
1320 net::MockDnsClientRuleList rules;
1321 rules.emplace_back(
1322 "example.com", net::dns_protocol::kTypePTR, false /*secure */,
1323 net::MockDnsClientRule::Result(net::BuildTestDnsPointerResponse(
1324 "example.com", {"google.com", "chromium.org"})),
1325 false /* delay */);
1326 auto dns_client = std::make_unique<net::MockDnsClient>(CreateValidDnsConfig(),
1327 std::move(rules));
1328 dns_client->set_ignore_system_config_changes(true);
1329
1330 std::unique_ptr<net::ContextHostResolver> inner_resolver =
1331 net::HostResolver::CreateStandaloneContextResolver(net::NetLog::Get());
1332 inner_resolver->GetManagerForTesting()->SetDnsClientForTesting(
1333 std::move(dns_client));
1334 inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(true);
1335
1336 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1337
1338 base::RunLoop run_loop;
1339 mojom::ResolveHostParametersPtr optional_parameters =
1340 mojom::ResolveHostParameters::New();
1341 optional_parameters->dns_query_type = net::DnsQueryType::PTR;
1342 mojo::PendingRemote<mojom::ResolveHostClient> pending_response_client;
1343 TestResolveHostClient response_client(&pending_response_client, &run_loop);
1344
1345 resolver.ResolveHost(
1346 net::HostPortPair("example.com", 160), net::NetworkIsolationKey(),
1347 std::move(optional_parameters), std::move(pending_response_client));
1348 run_loop.Run();
1349
1350 EXPECT_EQ(net::OK, response_client.result_error());
1351 EXPECT_FALSE(response_client.result_addresses());
1352 EXPECT_FALSE(response_client.result_text());
1353 EXPECT_THAT(response_client.result_hosts(),
1354 testing::Optional(testing::UnorderedElementsAre(
1355 net::HostPortPair("google.com", 160),
1356 net::HostPortPair("chromium.org", 160))));
1357 EXPECT_EQ(0u, resolver.GetNumOutstandingRequestsForTesting());
1358 }
1359
1360 #if BUILDFLAG(ENABLE_MDNS)
TEST_F(HostResolverTest,MdnsListener_AddressResult)1361 TEST_F(HostResolverTest, MdnsListener_AddressResult) {
1362 auto inner_resolver = std::make_unique<net::MockHostResolver>();
1363 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1364
1365 mojo::PendingRemote<mojom::MdnsListenClient> pending_response_client;
1366 TestMdnsListenClient response_client(&pending_response_client);
1367
1368 int error = net::ERR_FAILED;
1369 base::RunLoop run_loop;
1370 net::HostPortPair host("host.local", 41);
1371 resolver.MdnsListen(host, net::DnsQueryType::A,
1372 std::move(pending_response_client),
1373 base::BindLambdaForTesting([&](int error_val) {
1374 error = error_val;
1375 run_loop.Quit();
1376 }));
1377
1378 run_loop.Run();
1379 ASSERT_EQ(net::OK, error);
1380
1381 net::IPAddress result_address(1, 2, 3, 4);
1382 net::IPEndPoint result(result_address, 41);
1383 inner_resolver->TriggerMdnsListeners(
1384 host, net::DnsQueryType::A,
1385 net::HostResolver::MdnsListener::Delegate::UpdateType::ADDED, result);
1386 base::RunLoop().RunUntilIdle();
1387
1388 EXPECT_THAT(response_client.address_results(),
1389 testing::ElementsAre(TestMdnsListenClient::CreateExpectedResult(
1390 net::HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
1391 net::DnsQueryType::A, result)));
1392
1393 EXPECT_THAT(response_client.text_results(), testing::IsEmpty());
1394 EXPECT_THAT(response_client.hostname_results(), testing::IsEmpty());
1395 EXPECT_THAT(response_client.unhandled_results(), testing::IsEmpty());
1396 }
1397
TEST_F(HostResolverTest,MdnsListener_TextResult)1398 TEST_F(HostResolverTest, MdnsListener_TextResult) {
1399 auto inner_resolver = std::make_unique<net::MockHostResolver>();
1400 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1401
1402 mojo::PendingRemote<mojom::MdnsListenClient> pending_response_client;
1403 TestMdnsListenClient response_client(&pending_response_client);
1404
1405 int error = net::ERR_FAILED;
1406 base::RunLoop run_loop;
1407 net::HostPortPair host("host.local", 42);
1408 resolver.MdnsListen(host, net::DnsQueryType::TXT,
1409 std::move(pending_response_client),
1410 base::BindLambdaForTesting([&](int error_val) {
1411 error = error_val;
1412 run_loop.Quit();
1413 }));
1414
1415 run_loop.Run();
1416 ASSERT_EQ(net::OK, error);
1417
1418 inner_resolver->TriggerMdnsListeners(
1419 host, net::DnsQueryType::TXT,
1420 net::HostResolver::MdnsListener::Delegate::UpdateType::CHANGED,
1421 {"foo", "bar"});
1422 base::RunLoop().RunUntilIdle();
1423
1424 EXPECT_THAT(
1425 response_client.text_results(),
1426 testing::UnorderedElementsAre(
1427 TestMdnsListenClient::CreateExpectedResult(
1428 net::HostResolver::MdnsListener::Delegate::UpdateType::CHANGED,
1429 net::DnsQueryType::TXT, "foo"),
1430 TestMdnsListenClient::CreateExpectedResult(
1431 net::HostResolver::MdnsListener::Delegate::UpdateType::CHANGED,
1432 net::DnsQueryType::TXT, "bar")));
1433
1434 EXPECT_THAT(response_client.address_results(), testing::IsEmpty());
1435 EXPECT_THAT(response_client.hostname_results(), testing::IsEmpty());
1436 EXPECT_THAT(response_client.unhandled_results(), testing::IsEmpty());
1437 }
1438
TEST_F(HostResolverTest,MdnsListener_HostnameResult)1439 TEST_F(HostResolverTest, MdnsListener_HostnameResult) {
1440 auto inner_resolver = std::make_unique<net::MockHostResolver>();
1441 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1442
1443 mojo::PendingRemote<mojom::MdnsListenClient> pending_response_client;
1444 TestMdnsListenClient response_client(&pending_response_client);
1445
1446 int error = net::ERR_FAILED;
1447 base::RunLoop run_loop;
1448 net::HostPortPair host("host.local", 43);
1449 resolver.MdnsListen(host, net::DnsQueryType::PTR,
1450 std::move(pending_response_client),
1451 base::BindLambdaForTesting([&](int error_val) {
1452 error = error_val;
1453 run_loop.Quit();
1454 }));
1455
1456 run_loop.Run();
1457 ASSERT_EQ(net::OK, error);
1458
1459 net::HostPortPair result("example.com", 43);
1460 inner_resolver->TriggerMdnsListeners(
1461 host, net::DnsQueryType::PTR,
1462 net::HostResolver::MdnsListener::Delegate::UpdateType::REMOVED, result);
1463 base::RunLoop().RunUntilIdle();
1464
1465 EXPECT_THAT(
1466 response_client.hostname_results(),
1467 testing::ElementsAre(TestMdnsListenClient::CreateExpectedResult(
1468 net::HostResolver::MdnsListener::Delegate::UpdateType::REMOVED,
1469 net::DnsQueryType::PTR, result)));
1470
1471 EXPECT_THAT(response_client.address_results(), testing::IsEmpty());
1472 EXPECT_THAT(response_client.text_results(), testing::IsEmpty());
1473 EXPECT_THAT(response_client.unhandled_results(), testing::IsEmpty());
1474 }
1475
TEST_F(HostResolverTest,MdnsListener_UnhandledResult)1476 TEST_F(HostResolverTest, MdnsListener_UnhandledResult) {
1477 auto inner_resolver = std::make_unique<net::MockHostResolver>();
1478 HostResolver resolver(inner_resolver.get(), net::NetLog::Get());
1479
1480 mojo::PendingRemote<mojom::MdnsListenClient> pending_response_client;
1481 TestMdnsListenClient response_client(&pending_response_client);
1482
1483 int error = net::ERR_FAILED;
1484 base::RunLoop run_loop;
1485 net::HostPortPair host("host.local", 44);
1486 resolver.MdnsListen(host, net::DnsQueryType::PTR,
1487 std::move(pending_response_client),
1488 base::BindLambdaForTesting([&](int error_val) {
1489 error = error_val;
1490 run_loop.Quit();
1491 }));
1492
1493 run_loop.Run();
1494 ASSERT_EQ(net::OK, error);
1495
1496 inner_resolver->TriggerMdnsListeners(
1497 host, net::DnsQueryType::PTR,
1498 net::HostResolver::MdnsListener::Delegate::UpdateType::ADDED);
1499 base::RunLoop().RunUntilIdle();
1500
1501 EXPECT_THAT(response_client.unhandled_results(),
1502 testing::ElementsAre(std::make_pair(
1503 net::HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
1504 net::DnsQueryType::PTR)));
1505
1506 EXPECT_THAT(response_client.address_results(), testing::IsEmpty());
1507 EXPECT_THAT(response_client.text_results(), testing::IsEmpty());
1508 EXPECT_THAT(response_client.hostname_results(), testing::IsEmpty());
1509 }
1510 #endif // BUILDFLAG(ENABLE_MDNS)
1511
1512 } // namespace
1513 } // namespace network
1514