OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "net/dns/async_host_resolver.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/message_loop.h" | |
10 #include "base/stl_util.h" | |
11 #include "net/base/host_cache.h" | |
12 #include "net/base/net_errors.h" | |
13 #include "net/base/net_log.h" | |
14 #include "net/base/sys_addrinfo.h" | |
15 #include "net/base/test_completion_callback.h" | |
16 #include "net/dns/dns_query.h" | |
17 #include "net/dns/dns_response.h" | |
18 #include "net/dns/dns_test_util.h" | |
19 #include "net/dns/dns_transaction.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 | |
22 namespace net { | |
23 | |
24 namespace { | |
25 | |
26 const int kPortNum = 80; | |
27 const size_t kMaxTransactions = 2; | |
28 const size_t kMaxPendingRequests = 1; | |
29 | |
30 void VerifyAddressList(const std::vector<const char*>& ip_addresses, | |
31 int port, | |
32 const AddressList& addrlist) { | |
33 ASSERT_LT(0u, ip_addresses.size()); | |
34 ASSERT_NE(static_cast<addrinfo*>(NULL), addrlist.head()); | |
35 | |
36 IPAddressNumber ip_number; | |
37 const struct addrinfo* ainfo = addrlist.head(); | |
38 for (std::vector<const char*>::const_iterator i = ip_addresses.begin(); | |
39 i != ip_addresses.end(); ++i, ainfo = ainfo->ai_next) { | |
40 ASSERT_NE(static_cast<addrinfo*>(NULL), ainfo); | |
41 EXPECT_EQ(sizeof(struct sockaddr_in), | |
42 static_cast<size_t>(ainfo->ai_addrlen)); | |
43 | |
44 const struct sockaddr* sa = ainfo->ai_addr; | |
45 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; | |
46 EXPECT_TRUE(htons(port) == sa_in->sin_port); | |
47 EXPECT_STREQ(*i, NetAddressToString(sa, ainfo->ai_addrlen).c_str()); | |
48 } | |
49 ASSERT_EQ(static_cast<addrinfo*>(NULL), ainfo); | |
50 } | |
51 | |
52 class MockTransactionFactory : public DnsTransactionFactory, | |
53 public base::SupportsWeakPtr<MockTransactionFactory> { | |
54 public: | |
55 // Using WeakPtr to support cancellation. All MockTransactions succeed unless | |
56 // cancelled or MockTransactionFactory is destroyed. | |
57 class MockTransaction : public DnsTransaction, | |
58 public base::SupportsWeakPtr<MockTransaction> { | |
59 public: | |
60 MockTransaction(const std::string& hostname, | |
61 uint16 qtype, | |
62 const DnsTransactionFactory::CallbackType& callback, | |
63 const base::WeakPtr<MockTransactionFactory>& factory) | |
64 : hostname_(hostname), | |
65 qtype_(qtype), | |
66 callback_(callback), | |
67 started_(false), | |
68 factory_(factory) { | |
69 EXPECT_FALSE(started_); | |
70 started_ = true; | |
71 MessageLoop::current()->PostTask( | |
72 FROM_HERE, | |
73 base::Bind(&MockTransaction::Finish, AsWeakPtr())); | |
74 } | |
75 | |
76 virtual const std::string& GetHostname() const OVERRIDE { | |
77 return hostname_; | |
78 } | |
79 | |
80 virtual uint16 GetType() const OVERRIDE { | |
81 return qtype_; | |
82 } | |
83 | |
84 virtual int Start() OVERRIDE { | |
85 return ERR_IO_PENDING; | |
86 } | |
87 | |
88 private: | |
89 void Finish() { | |
90 if (!factory_) { | |
91 callback_.Run(this, ERR_DNS_SERVER_FAILED, NULL); | |
92 return; | |
93 } | |
94 callback_.Run(this, | |
95 OK, | |
96 factory_->responses_[Key(GetHostname(), GetType())]); | |
97 } | |
98 | |
99 const std::string hostname_; | |
100 const uint16 qtype_; | |
101 DnsTransactionFactory::CallbackType callback_; | |
102 bool started_; | |
103 const base::WeakPtr<MockTransactionFactory> factory_; | |
104 }; | |
105 | |
106 typedef std::pair<std::string, uint16> Key; | |
107 | |
108 MockTransactionFactory() : num_requests_(0) {} | |
109 ~MockTransactionFactory() { | |
110 STLDeleteValues(&responses_); | |
111 } | |
112 | |
113 scoped_ptr<DnsTransaction> CreateTransaction( | |
114 const std::string& qname, | |
115 uint16 qtype, | |
116 const DnsTransactionFactory::CallbackType& callback, | |
117 const BoundNetLog&) { | |
118 ++num_requests_; | |
119 return scoped_ptr<DnsTransaction>( | |
120 new MockTransaction(qname, qtype, callback, AsWeakPtr())); | |
121 } | |
122 | |
123 void AddResponse(const std::string& name, uint8 type, DnsResponse* response) { | |
124 responses_[MockTransactionFactory::Key(name, type)] = response; | |
125 } | |
126 | |
127 int num_requests() const { return num_requests_; } | |
128 | |
129 private: | |
130 int num_requests_; | |
131 std::map<Key, DnsResponse*> responses_; | |
132 }; | |
133 | |
134 } // namespace | |
135 | |
136 | |
137 // The following fixture sets up an environment for four different lookups | |
138 // with their data defined in dns_test_util.h. All tests make use of these | |
139 // predefined variables instead of each defining their own, to avoid | |
140 // boilerplate code in every test. Assuming every coming query is for a | |
141 // distinct hostname, as |kMaxTransactions| is set to 2 and | |
142 // |kMaxPendingRequests| is set to 1, first two queries start immediately | |
143 // and the next one is sent to pending queue; as a result, the next query | |
144 // should either fail itself or cause the pending query to fail depending | |
145 // on its priority. | |
146 class AsyncHostResolverTest : public testing::Test { | |
147 public: | |
148 AsyncHostResolverTest() | |
149 : info0_(HostPortPair(kT0HostName, kPortNum)), | |
150 info1_(HostPortPair(kT1HostName, kPortNum)), | |
151 info2_(HostPortPair(kT2HostName, kPortNum)), | |
152 info3_(HostPortPair(kT3HostName, kPortNum)), | |
153 ip_addresses0_(kT0IpAddresses, | |
154 kT0IpAddresses + arraysize(kT0IpAddresses)), | |
155 ip_addresses1_(kT1IpAddresses, | |
156 kT1IpAddresses + arraysize(kT1IpAddresses)), | |
157 ip_addresses2_(kT2IpAddresses, | |
158 kT2IpAddresses + arraysize(kT2IpAddresses)), | |
159 ip_addresses3_(kT3IpAddresses, | |
160 kT3IpAddresses + arraysize(kT3IpAddresses)) { | |
161 // AF_INET only for now. | |
162 info0_.set_address_family(ADDRESS_FAMILY_IPV4); | |
163 info1_.set_address_family(ADDRESS_FAMILY_IPV4); | |
164 info2_.set_address_family(ADDRESS_FAMILY_IPV4); | |
165 info3_.set_address_family(ADDRESS_FAMILY_IPV4); | |
166 | |
167 client_ = new MockTransactionFactory(); | |
168 | |
169 client_->AddResponse(kT0HostName, kT0Qtype, | |
170 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram), | |
171 arraysize(kT0ResponseDatagram), | |
172 arraysize(kT0QueryDatagram))); | |
173 | |
174 client_->AddResponse(kT1HostName, kT1Qtype, | |
175 new DnsResponse(reinterpret_cast<const char*>(kT1ResponseDatagram), | |
176 arraysize(kT1ResponseDatagram), | |
177 arraysize(kT1QueryDatagram))); | |
178 | |
179 client_->AddResponse(kT2HostName, kT2Qtype, | |
180 new DnsResponse(reinterpret_cast<const char*>(kT2ResponseDatagram), | |
181 arraysize(kT2ResponseDatagram), | |
182 arraysize(kT2QueryDatagram))); | |
183 | |
184 client_->AddResponse(kT3HostName, kT3Qtype, | |
185 new DnsResponse(reinterpret_cast<const char*>(kT3ResponseDatagram), | |
186 arraysize(kT3ResponseDatagram), | |
187 arraysize(kT3QueryDatagram))); | |
188 | |
189 resolver_.reset( | |
190 new AsyncHostResolver(kMaxTransactions, kMaxPendingRequests, | |
191 HostCache::CreateDefaultCache(), | |
192 scoped_ptr<DnsTransactionFactory>(client_), NULL)); | |
193 } | |
194 | |
195 protected: | |
196 AddressList addrlist0_, addrlist1_, addrlist2_, addrlist3_; | |
197 HostResolver::RequestInfo info0_, info1_, info2_, info3_; | |
198 std::vector<const char*> ip_addresses0_, ip_addresses1_, | |
199 ip_addresses2_, ip_addresses3_; | |
200 scoped_ptr<HostResolver> resolver_; | |
201 MockTransactionFactory* client_; // Owned by the AsyncHostResolver. | |
202 TestCompletionCallback callback0_, callback1_, callback2_, callback3_; | |
203 }; | |
204 | |
205 TEST_F(AsyncHostResolverTest, EmptyHostLookup) { | |
206 info0_.set_host_port_pair(HostPortPair("", kPortNum)); | |
207 int rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
208 BoundNetLog()); | |
209 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); | |
210 } | |
211 | |
212 TEST_F(AsyncHostResolverTest, IPv4LiteralLookup) { | |
213 const char* kIPLiteral = "192.168.1.2"; | |
214 info0_.set_host_port_pair(HostPortPair(kIPLiteral, kPortNum)); | |
215 info0_.set_host_resolver_flags(HOST_RESOLVER_CANONNAME); | |
216 int rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
217 BoundNetLog()); | |
218 EXPECT_EQ(OK, rv); | |
219 std::vector<const char*> ip_addresses(1, kIPLiteral); | |
220 VerifyAddressList(ip_addresses, kPortNum, addrlist0_); | |
221 EXPECT_STREQ(kIPLiteral, addrlist0_.head()->ai_canonname); | |
222 } | |
223 | |
224 TEST_F(AsyncHostResolverTest, IPv6LiteralLookup) { | |
225 info0_.set_host_port_pair(HostPortPair("2001:db8:0::42", kPortNum)); | |
226 int rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
227 BoundNetLog()); | |
228 // When support for IPv6 is added, this should succeed. | |
229 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); | |
230 } | |
231 | |
232 TEST_F(AsyncHostResolverTest, CachedLookup) { | |
233 int rv = resolver_->ResolveFromCache(info0_, &addrlist0_, BoundNetLog()); | |
234 EXPECT_EQ(ERR_DNS_CACHE_MISS, rv); | |
235 | |
236 // Cache the result of |info0_| lookup. | |
237 rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
238 BoundNetLog()); | |
239 EXPECT_EQ(ERR_IO_PENDING, rv); | |
240 rv = callback0_.WaitForResult(); | |
241 EXPECT_EQ(OK, rv); | |
242 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
243 | |
244 // Now lookup |info0_| from cache only, store results in |addrlist1_|, | |
245 // should succeed synchronously. | |
246 rv = resolver_->ResolveFromCache(info0_, &addrlist1_, BoundNetLog()); | |
247 EXPECT_EQ(OK, rv); | |
248 VerifyAddressList(ip_addresses0_, kPortNum, addrlist1_); | |
249 } | |
250 | |
251 // TODO(szym): This tests DnsTransaction not AsyncHostResolver. Remove or move | |
252 // to dns_transaction_unittest.cc | |
253 TEST_F(AsyncHostResolverTest, DISABLED_InvalidHostNameLookup) { | |
254 const std::string kHostName1(64, 'a'); | |
255 info0_.set_host_port_pair(HostPortPair(kHostName1, kPortNum)); | |
256 int rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
257 BoundNetLog()); | |
258 EXPECT_EQ(ERR_INVALID_ARGUMENT, rv); | |
259 | |
260 const std::string kHostName2(4097, 'b'); | |
261 info0_.set_host_port_pair(HostPortPair(kHostName2, kPortNum)); | |
262 rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
263 BoundNetLog()); | |
264 EXPECT_EQ(ERR_INVALID_ARGUMENT, rv); | |
265 } | |
266 | |
267 TEST_F(AsyncHostResolverTest, Lookup) { | |
268 int rv = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
269 BoundNetLog()); | |
270 EXPECT_EQ(ERR_IO_PENDING, rv); | |
271 rv = callback0_.WaitForResult(); | |
272 EXPECT_EQ(OK, rv); | |
273 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
274 } | |
275 | |
276 TEST_F(AsyncHostResolverTest, ConcurrentLookup) { | |
277 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
278 BoundNetLog()); | |
279 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
280 BoundNetLog()); | |
281 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), NULL, | |
282 BoundNetLog()); | |
283 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
284 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
285 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
286 | |
287 rv0 = callback0_.WaitForResult(); | |
288 EXPECT_EQ(OK, rv0); | |
289 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
290 | |
291 rv1 = callback1_.WaitForResult(); | |
292 EXPECT_EQ(OK, rv1); | |
293 VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); | |
294 | |
295 rv2 = callback2_.WaitForResult(); | |
296 EXPECT_EQ(OK, rv2); | |
297 VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); | |
298 | |
299 EXPECT_EQ(3, client_->num_requests()); | |
300 } | |
301 | |
302 TEST_F(AsyncHostResolverTest, SameHostLookupsConsumeSingleTransaction) { | |
303 // We pass the info0_ to all requests. | |
304 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
305 BoundNetLog()); | |
306 int rv1 = resolver_->Resolve(info0_, &addrlist1_, callback1_.callback(), NULL, | |
307 BoundNetLog()); | |
308 int rv2 = resolver_->Resolve(info0_, &addrlist2_, callback2_.callback(), NULL, | |
309 BoundNetLog()); | |
310 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
311 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
312 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
313 | |
314 rv0 = callback0_.WaitForResult(); | |
315 EXPECT_EQ(OK, rv0); | |
316 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
317 | |
318 rv1 = callback1_.WaitForResult(); | |
319 EXPECT_EQ(OK, rv1); | |
320 VerifyAddressList(ip_addresses0_, kPortNum, addrlist1_); | |
321 | |
322 rv2 = callback2_.WaitForResult(); | |
323 EXPECT_EQ(OK, rv2); | |
324 VerifyAddressList(ip_addresses0_, kPortNum, addrlist2_); | |
325 | |
326 // Although we have three lookups, a single UDP socket was used. | |
327 EXPECT_EQ(1, client_->num_requests()); | |
328 } | |
329 | |
330 TEST_F(AsyncHostResolverTest, CancelLookup) { | |
331 HostResolver::RequestHandle req0 = NULL, req2 = NULL; | |
332 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), | |
333 &req0, BoundNetLog()); | |
334 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
335 BoundNetLog()); | |
336 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), | |
337 &req2, BoundNetLog()); | |
338 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
339 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
340 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
341 | |
342 resolver_->CancelRequest(req0); | |
343 resolver_->CancelRequest(req2); | |
344 | |
345 MessageLoop::current()->RunAllPending(); | |
346 | |
347 EXPECT_FALSE(callback0_.have_result()); | |
348 EXPECT_FALSE(callback2_.have_result()); | |
349 | |
350 rv1 = callback1_.WaitForResult(); | |
351 EXPECT_EQ(OK, rv1); | |
352 VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); | |
353 } | |
354 | |
355 // Tests the following scenario: start two resolutions for the same host, | |
356 // cancel one of them, make sure that the other one completes. | |
357 TEST_F(AsyncHostResolverTest, CancelSameHostLookup) { | |
358 HostResolver::RequestHandle req0 = NULL; | |
359 | |
360 // Pass the info0_ to both requests. | |
361 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), | |
362 &req0, BoundNetLog()); | |
363 int rv1 = resolver_->Resolve(info0_, &addrlist1_, callback1_.callback(), NULL, | |
364 BoundNetLog()); | |
365 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
366 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
367 | |
368 resolver_->CancelRequest(req0); | |
369 MessageLoop::current()->RunAllPending(); | |
370 EXPECT_FALSE(callback0_.have_result()); | |
371 | |
372 rv1 = callback1_.WaitForResult(); | |
373 EXPECT_EQ(OK, rv1); | |
374 VerifyAddressList(ip_addresses0_, kPortNum, addrlist1_); | |
375 | |
376 EXPECT_EQ(1, client_->num_requests()); | |
377 } | |
378 | |
379 // Test that a queued lookup completes. | |
380 TEST_F(AsyncHostResolverTest, QueuedLookup) { | |
381 // kMaxTransactions is 2, thus the following requests consume all | |
382 // available transactions. | |
383 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
384 BoundNetLog()); | |
385 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
386 BoundNetLog()); | |
387 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
388 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
389 | |
390 // The following request will end up in queue. | |
391 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), NULL, | |
392 BoundNetLog()); | |
393 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
394 EXPECT_EQ(1u, | |
395 static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); | |
396 | |
397 // Make sure all requests complete. | |
398 rv0 = callback0_.WaitForResult(); | |
399 EXPECT_EQ(OK, rv0); | |
400 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
401 | |
402 rv1 = callback1_.WaitForResult(); | |
403 EXPECT_EQ(OK, rv1); | |
404 VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); | |
405 | |
406 rv2 = callback2_.WaitForResult(); | |
407 EXPECT_EQ(OK, rv2); | |
408 VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); | |
409 } | |
410 | |
411 // Test that cancelling a queued lookup works. | |
412 TEST_F(AsyncHostResolverTest, CancelPendingLookup) { | |
413 // kMaxTransactions is 2, thus the following requests consume all | |
414 // available transactions. | |
415 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
416 BoundNetLog()); | |
417 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
418 BoundNetLog()); | |
419 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
420 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
421 | |
422 // The following request will end up in queue. | |
423 HostResolver::RequestHandle req2 = NULL; | |
424 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), | |
425 &req2, BoundNetLog()); | |
426 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
427 EXPECT_EQ(1u, | |
428 static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); | |
429 | |
430 resolver_->CancelRequest(req2); | |
431 | |
432 // Make sure first two requests complete while the cancelled one doesn't. | |
433 MessageLoop::current()->RunAllPending(); | |
434 EXPECT_FALSE(callback2_.have_result()); | |
435 | |
436 rv0 = callback0_.WaitForResult(); | |
437 EXPECT_EQ(OK, rv0); | |
438 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
439 | |
440 rv1 = callback1_.WaitForResult(); | |
441 EXPECT_EQ(OK, rv1); | |
442 VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); | |
443 } | |
444 | |
445 TEST_F(AsyncHostResolverTest, ResolverDestructionCancelsLookups) { | |
446 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
447 BoundNetLog()); | |
448 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
449 BoundNetLog()); | |
450 // This one is queued. | |
451 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), NULL, | |
452 BoundNetLog()); | |
453 EXPECT_EQ(1u, | |
454 static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); | |
455 | |
456 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
457 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
458 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
459 | |
460 resolver_.reset(); | |
461 | |
462 MessageLoop::current()->RunAllPending(); | |
463 | |
464 EXPECT_FALSE(callback0_.have_result()); | |
465 EXPECT_FALSE(callback1_.have_result()); | |
466 EXPECT_FALSE(callback2_.have_result()); | |
467 } | |
468 | |
469 // Test that when the number of pending lookups is at max, a new lookup | |
470 // with a priority lower than all of those in the queue fails. | |
471 TEST_F(AsyncHostResolverTest, OverflowQueueWithLowPriorityLookup) { | |
472 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
473 BoundNetLog()); | |
474 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
475 BoundNetLog()); | |
476 // This one is queued and fills up the queue since its size is 1. | |
477 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), NULL, | |
478 BoundNetLog()); | |
479 EXPECT_EQ(1u, | |
480 static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); | |
481 | |
482 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
483 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
484 EXPECT_EQ(ERR_IO_PENDING, rv2); | |
485 | |
486 // This one fails. | |
487 info3_.set_priority(LOWEST); | |
488 int rv3 = resolver_->Resolve(info3_, &addrlist3_, callback3_.callback(), NULL, | |
489 BoundNetLog()); | |
490 EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, rv3); | |
491 | |
492 MessageLoop::current()->RunAllPending(); | |
493 EXPECT_FALSE(callback3_.have_result()); | |
494 } | |
495 | |
496 // Test that when the number of pending lookups is at max, a new lookup | |
497 // with a priority higher than any of those in the queue succeeds and | |
498 // causes the lowest priority lookup in the queue to fail. | |
499 TEST_F(AsyncHostResolverTest, OverflowQueueWithHighPriorityLookup) { | |
500 int rv0 = resolver_->Resolve(info0_, &addrlist0_, callback0_.callback(), NULL, | |
501 BoundNetLog()); | |
502 int rv1 = resolver_->Resolve(info1_, &addrlist1_, callback1_.callback(), NULL, | |
503 BoundNetLog()); | |
504 | |
505 // Next lookup is queued. Since this will be ejected from the queue and | |
506 // will not consume a socket from our factory, we are not passing it | |
507 // predefined members. | |
508 HostResolver::RequestInfo info(HostPortPair("cnn.com", 80)); | |
509 info.set_address_family(ADDRESS_FAMILY_IPV4); | |
510 AddressList addrlist_fail; | |
511 TestCompletionCallback callback_fail; | |
512 int rv_fail = resolver_->Resolve(info, &addrlist_fail, | |
513 callback_fail.callback(), NULL, | |
514 BoundNetLog()); | |
515 EXPECT_EQ(1u, | |
516 static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); | |
517 | |
518 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
519 EXPECT_EQ(ERR_IO_PENDING, rv1); | |
520 EXPECT_EQ(ERR_IO_PENDING, rv_fail); | |
521 | |
522 // Lookup 2 causes the above to fail, but itself should succeed. | |
523 info2_.set_priority(HIGHEST); | |
524 int rv2 = resolver_->Resolve(info2_, &addrlist2_, callback2_.callback(), NULL, | |
525 BoundNetLog()); | |
526 | |
527 rv0 = callback0_.WaitForResult(); | |
528 EXPECT_EQ(OK, rv0); | |
529 VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); | |
530 | |
531 rv1 = callback1_.WaitForResult(); | |
532 EXPECT_EQ(OK, rv1); | |
533 VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); | |
534 | |
535 rv_fail = callback_fail.WaitForResult(); | |
536 EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, rv_fail); | |
537 EXPECT_EQ(static_cast<addrinfo*>(NULL), addrlist_fail.head()); | |
538 | |
539 rv2 = callback2_.WaitForResult(); | |
540 EXPECT_EQ(OK, rv2); | |
541 VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); | |
542 } | |
543 | |
544 } // namespace net | |
OLD | NEW |