| 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 |