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