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/dns_transaction.h" 6 7 #include "base/bind.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_vector.h" 10 #include "base/rand_util.h" 11 #include "base/sys_byteorder.h" 12 #include "base/test/test_timeouts.h" 13 #include "net/base/dns_util.h" 14 #include "net/base/net_log.h" 15 #include "net/dns/dns_protocol.h" 16 #include "net/dns/dns_query.h" 17 #include "net/dns/dns_response.h" 18 #include "net/dns/dns_session.h" 19 #include "net/dns/dns_test_util.h" 20 #include "net/socket/socket_test_util.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace net { 24 25 namespace { 26 27 std::string DomainFromDot(const base::StringPiece& dotted) { 28 std::string out; 29 EXPECT_TRUE(DNSDomainFromDot(dotted, &out)); 30 return out; 31 } 32 33 // A SocketDataProvider builder. 34 class DnsSocketData { 35 public: 36 // The ctor takes parameters for the DnsQuery. 37 DnsSocketData(uint16 id, 38 const char* dotted_name, 39 uint16 qtype, 40 IoMode mode, 41 bool use_tcp) 42 : query_(new DnsQuery(id, DomainFromDot(dotted_name), qtype)), 43 use_tcp_(use_tcp) { 44 if (use_tcp_) { 45 scoped_ptr<uint16> length(new uint16); 46 *length = base::HostToNet16(query_->io_buffer()->size()); 47 writes_.push_back(MockWrite(mode, 48 reinterpret_cast<const char*>(length.get()), 49 sizeof(uint16))); 50 lengths_.push_back(length.release()); 51 } 52 writes_.push_back(MockWrite(mode, 53 query_->io_buffer()->data(), 54 query_->io_buffer()->size())); 55 } 56 ~DnsSocketData() {} 57 58 // All responses must be added before GetProvider. 59 60 // Adds pre-built DnsResponse. |tcp_length| will be used in TCP mode only. 61 void AddResponseWithLength(scoped_ptr<DnsResponse> response, IoMode mode, 62 uint16 tcp_length) { 63 CHECK(!provider_.get()); 64 if (use_tcp_) { 65 scoped_ptr<uint16> length(new uint16); 66 *length = base::HostToNet16(tcp_length); 67 reads_.push_back(MockRead(mode, 68 reinterpret_cast<const char*>(length.get()), 69 sizeof(uint16))); 70 lengths_.push_back(length.release()); 71 } 72 reads_.push_back(MockRead(mode, 73 response->io_buffer()->data(), 74 response->io_buffer()->size())); 75 responses_.push_back(response.release()); 76 } 77 78 // Adds pre-built DnsResponse. 79 void AddResponse(scoped_ptr<DnsResponse> response, IoMode mode) { 80 uint16 tcp_length = response->io_buffer()->size(); 81 AddResponseWithLength(response.Pass(), mode, tcp_length); 82 } 83 84 // Adds pre-built response from |data| buffer. 85 void AddResponseData(const uint8* data, size_t length, IoMode mode) { 86 CHECK(!provider_.get()); 87 AddResponse(make_scoped_ptr( 88 new DnsResponse(reinterpret_cast<const char*>(data), length, 0)), mode); 89 } 90 91 // Add no-answer (RCODE only) response matching the query. 92 void AddRcode(int rcode, IoMode mode) { 93 scoped_ptr<DnsResponse> response( 94 new DnsResponse(query_->io_buffer()->data(), 95 query_->io_buffer()->size(), 96 0)); 97 dns_protocol::Header* header = 98 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data()); 99 header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode); 100 AddResponse(response.Pass(), mode); 101 } 102 103 // Add error response. 104 void AddReadError(int error, IoMode mode) { 105 reads_.push_back(MockRead(mode, error)); 106 } 107 108 // Build, if needed, and return the SocketDataProvider. No new responses 109 // should be added afterwards. 110 SocketDataProvider* GetProvider() { 111 if (provider_.get()) 112 return provider_.get(); 113 // Terminate the reads with ERR_IO_PENDING to prevent overrun and default to 114 // timeout. 115 reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING)); 116 provider_.reset(new DelayedSocketData(1, &reads_[0], reads_.size(), 117 &writes_[0], writes_.size())); 118 if (use_tcp_) { 119 provider_->set_connect_data(MockConnect(reads_[0].mode, OK)); 120 } 121 return provider_.get(); 122 } 123 124 uint16 query_id() const { 125 return query_->id(); 126 } 127 128 // Returns true if the expected query was written to the socket. 129 bool was_written() const { 130 CHECK(provider_.get()); 131 return provider_->write_index() > 0; 132 } 133 134 private: 135 scoped_ptr<DnsQuery> query_; 136 bool use_tcp_; 137 ScopedVector<uint16> lengths_; 138 ScopedVector<DnsResponse> responses_; 139 std::vector<MockWrite> writes_; 140 std::vector<MockRead> reads_; 141 scoped_ptr<DelayedSocketData> provider_; 142 143 DISALLOW_COPY_AND_ASSIGN(DnsSocketData); 144 }; 145 146 class TestSocketFactory; 147 148 // A variant of MockUDPClientSocket which always fails to Connect. 149 class FailingUDPClientSocket : public MockUDPClientSocket { 150 public: 151 FailingUDPClientSocket(SocketDataProvider* data, 152 net::NetLog* net_log) 153 : MockUDPClientSocket(data, net_log) { 154 } 155 virtual ~FailingUDPClientSocket() {} 156 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE { 157 return ERR_CONNECTION_REFUSED; 158 } 159 160 private: 161 DISALLOW_COPY_AND_ASSIGN(FailingUDPClientSocket); 162 }; 163 164 // A variant of MockUDPClientSocket which notifies the factory OnConnect. 165 class TestUDPClientSocket : public MockUDPClientSocket { 166 public: 167 TestUDPClientSocket(TestSocketFactory* factory, 168 SocketDataProvider* data, 169 net::NetLog* net_log) 170 : MockUDPClientSocket(data, net_log), factory_(factory) { 171 } 172 virtual ~TestUDPClientSocket() {} 173 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE; 174 175 private: 176 TestSocketFactory* factory_; 177 178 DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket); 179 }; 180 181 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect. 182 class TestSocketFactory : public MockClientSocketFactory { 183 public: 184 TestSocketFactory() : fail_next_socket_(false) {} 185 virtual ~TestSocketFactory() {} 186 187 virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket( 188 DatagramSocket::BindType bind_type, 189 const RandIntCallback& rand_int_cb, 190 net::NetLog* net_log, 191 const net::NetLog::Source& source) OVERRIDE { 192 if (fail_next_socket_) { 193 fail_next_socket_ = false; 194 return scoped_ptr<DatagramClientSocket>( 195 new FailingUDPClientSocket(&empty_data_, net_log)); 196 } 197 SocketDataProvider* data_provider = mock_data().GetNext(); 198 scoped_ptr<TestUDPClientSocket> socket( 199 new TestUDPClientSocket(this, data_provider, net_log)); 200 data_provider->set_socket(socket.get()); 201 return socket.PassAs<DatagramClientSocket>(); 202 } 203 204 void OnConnect(const IPEndPoint& endpoint) { 205 remote_endpoints_.push_back(endpoint); 206 } 207 208 std::vector<IPEndPoint> remote_endpoints_; 209 bool fail_next_socket_; 210 211 private: 212 StaticSocketDataProvider empty_data_; 213 214 DISALLOW_COPY_AND_ASSIGN(TestSocketFactory); 215 }; 216 217 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) { 218 factory_->OnConnect(endpoint); 219 return MockUDPClientSocket::Connect(endpoint); 220 } 221 222 // Helper class that holds a DnsTransaction and handles OnTransactionComplete. 223 class TransactionHelper { 224 public: 225 // If |expected_answer_count| < 0 then it is the expected net error. 226 TransactionHelper(const char* hostname, 227 uint16 qtype, 228 int expected_answer_count) 229 : hostname_(hostname), 230 qtype_(qtype), 231 expected_answer_count_(expected_answer_count), 232 cancel_in_callback_(false), 233 quit_in_callback_(false), 234 completed_(false) { 235 } 236 237 // Mark that the transaction shall be destroyed immediately upon callback. 238 void set_cancel_in_callback() { 239 cancel_in_callback_ = true; 240 } 241 242 // Mark to call MessageLoop::Quit() upon callback. 243 void set_quit_in_callback() { 244 quit_in_callback_ = true; 245 } 246 247 void StartTransaction(DnsTransactionFactory* factory) { 248 EXPECT_EQ(NULL, transaction_.get()); 249 transaction_ = factory->CreateTransaction( 250 hostname_, 251 qtype_, 252 base::Bind(&TransactionHelper::OnTransactionComplete, 253 base::Unretained(this)), 254 BoundNetLog()); 255 EXPECT_EQ(hostname_, transaction_->GetHostname()); 256 EXPECT_EQ(qtype_, transaction_->GetType()); 257 transaction_->Start(); 258 } 259 260 void Cancel() { 261 ASSERT_TRUE(transaction_.get() != NULL); 262 transaction_.reset(NULL); 263 } 264 265 void OnTransactionComplete(DnsTransaction* t, 266 int rv, 267 const DnsResponse* response) { 268 EXPECT_FALSE(completed_); 269 EXPECT_EQ(transaction_.get(), t); 270 271 completed_ = true; 272 273 if (cancel_in_callback_) { 274 Cancel(); 275 return; 276 } 277 278 // Tell MessageLoop to quit now, in case any ASSERT_* fails. 279 if (quit_in_callback_) 280 base::MessageLoop::current()->Quit(); 281 282 if (expected_answer_count_ >= 0) { 283 ASSERT_EQ(OK, rv); 284 ASSERT_TRUE(response != NULL); 285 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_), 286 response->answer_count()); 287 EXPECT_EQ(qtype_, response->qtype()); 288 289 DnsRecordParser parser = response->Parser(); 290 DnsResourceRecord record; 291 for (int i = 0; i < expected_answer_count_; ++i) { 292 EXPECT_TRUE(parser.ReadRecord(&record)); 293 } 294 } else { 295 EXPECT_EQ(expected_answer_count_, rv); 296 } 297 } 298 299 bool has_completed() const { 300 return completed_; 301 } 302 303 // Shorthands for commonly used commands. 304 305 bool Run(DnsTransactionFactory* factory) { 306 StartTransaction(factory); 307 base::MessageLoop::current()->RunUntilIdle(); 308 return has_completed(); 309 } 310 311 // Use when some of the responses are timeouts. 312 bool RunUntilDone(DnsTransactionFactory* factory) { 313 set_quit_in_callback(); 314 StartTransaction(factory); 315 base::MessageLoop::current()->Run(); 316 return has_completed(); 317 } 318 319 private: 320 std::string hostname_; 321 uint16 qtype_; 322 scoped_ptr<DnsTransaction> transaction_; 323 int expected_answer_count_; 324 bool cancel_in_callback_; 325 bool quit_in_callback_; 326 327 bool completed_; 328 }; 329 330 class DnsTransactionTest : public testing::Test { 331 public: 332 DnsTransactionTest() {} 333 334 // Generates |nameservers| for DnsConfig. 335 void ConfigureNumServers(unsigned num_servers) { 336 CHECK_LE(num_servers, 255u); 337 config_.nameservers.clear(); 338 IPAddressNumber dns_ip; 339 { 340 bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip); 341 EXPECT_TRUE(rv); 342 } 343 for (unsigned i = 0; i < num_servers; ++i) { 344 dns_ip[3] = i; 345 config_.nameservers.push_back(IPEndPoint(dns_ip, 346 dns_protocol::kDefaultPort)); 347 } 348 } 349 350 // Called after fully configuring |config|. 351 void ConfigureFactory() { 352 socket_factory_.reset(new TestSocketFactory()); 353 session_ = new DnsSession( 354 config_, 355 DnsSocketPool::CreateNull(socket_factory_.get()), 356 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)), 357 NULL /* NetLog */); 358 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get()); 359 } 360 361 void AddSocketData(scoped_ptr<DnsSocketData> data) { 362 CHECK(socket_factory_.get()); 363 transaction_ids_.push_back(data->query_id()); 364 socket_factory_->AddSocketDataProvider(data->GetProvider()); 365 socket_data_.push_back(data.release()); 366 } 367 368 // Add expected query for |dotted_name| and |qtype| with |id| and response 369 // taken verbatim from |data| of |data_length| bytes. The transaction id in 370 // |data| should equal |id|, unless testing mismatched response. 371 void AddQueryAndResponse(uint16 id, 372 const char* dotted_name, 373 uint16 qtype, 374 const uint8* response_data, 375 size_t response_length, 376 IoMode mode, 377 bool use_tcp) { 378 CHECK(socket_factory_.get()); 379 scoped_ptr<DnsSocketData> data( 380 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp)); 381 data->AddResponseData(response_data, response_length, mode); 382 AddSocketData(data.Pass()); 383 } 384 385 void AddAsyncQueryAndResponse(uint16 id, 386 const char* dotted_name, 387 uint16 qtype, 388 const uint8* data, 389 size_t data_length) { 390 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC, 391 false); 392 } 393 394 void AddSyncQueryAndResponse(uint16 id, 395 const char* dotted_name, 396 uint16 qtype, 397 const uint8* data, 398 size_t data_length) { 399 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS, 400 false); 401 } 402 403 // Add expected query of |dotted_name| and |qtype| and no response. 404 void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) { 405 uint16 id = base::RandInt(0, kuint16max); 406 scoped_ptr<DnsSocketData> data( 407 new DnsSocketData(id, dotted_name, qtype, ASYNC, false)); 408 AddSocketData(data.Pass()); 409 } 410 411 // Add expected query of |dotted_name| and |qtype| and matching response with 412 // no answer and RCODE set to |rcode|. The id will be generated randomly. 413 void AddQueryAndRcode(const char* dotted_name, 414 uint16 qtype, 415 int rcode, 416 IoMode mode, 417 bool use_tcp) { 418 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode); 419 uint16 id = base::RandInt(0, kuint16max); 420 scoped_ptr<DnsSocketData> data( 421 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp)); 422 data->AddRcode(rcode, mode); 423 AddSocketData(data.Pass()); 424 } 425 426 void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) { 427 AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false); 428 } 429 430 void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) { 431 AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false); 432 } 433 434 // Checks if the sockets were connected in the order matching the indices in 435 // |servers|. 436 void CheckServerOrder(const unsigned* servers, size_t num_attempts) { 437 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size()); 438 for (size_t i = 0; i < num_attempts; ++i) { 439 EXPECT_EQ(socket_factory_->remote_endpoints_[i], 440 session_->config().nameservers[servers[i]]); 441 } 442 } 443 444 virtual void SetUp() OVERRIDE { 445 // By default set one server, 446 ConfigureNumServers(1); 447 // and no retransmissions, 448 config_.attempts = 1; 449 // but long enough timeout for memory tests. 450 config_.timeout = TestTimeouts::action_timeout(); 451 ConfigureFactory(); 452 } 453 454 virtual void TearDown() OVERRIDE { 455 // Check that all socket data was at least written to. 456 for (size_t i = 0; i < socket_data_.size(); ++i) { 457 EXPECT_TRUE(socket_data_[i]->was_written()) << i; 458 } 459 } 460 461 protected: 462 int GetNextId(int min, int max) { 463 EXPECT_FALSE(transaction_ids_.empty()); 464 int id = transaction_ids_.front(); 465 transaction_ids_.pop_front(); 466 EXPECT_GE(id, min); 467 EXPECT_LE(id, max); 468 return id; 469 } 470 471 DnsConfig config_; 472 473 ScopedVector<DnsSocketData> socket_data_; 474 475 std::deque<int> transaction_ids_; 476 scoped_ptr<TestSocketFactory> socket_factory_; 477 scoped_refptr<DnsSession> session_; 478 scoped_ptr<DnsTransactionFactory> transaction_factory_; 479 }; 480 481 TEST_F(DnsTransactionTest, Lookup) { 482 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 483 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 484 485 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 486 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 487 } 488 489 // Concurrent lookup tests assume that DnsTransaction::Start immediately 490 // consumes a socket from ClientSocketFactory. 491 TEST_F(DnsTransactionTest, ConcurrentLookup) { 492 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 493 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 494 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype, 495 kT1ResponseDatagram, arraysize(kT1ResponseDatagram)); 496 497 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 498 helper0.StartTransaction(transaction_factory_.get()); 499 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount); 500 helper1.StartTransaction(transaction_factory_.get()); 501 502 base::MessageLoop::current()->RunUntilIdle(); 503 504 EXPECT_TRUE(helper0.has_completed()); 505 EXPECT_TRUE(helper1.has_completed()); 506 } 507 508 TEST_F(DnsTransactionTest, CancelLookup) { 509 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 510 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 511 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype, 512 kT1ResponseDatagram, arraysize(kT1ResponseDatagram)); 513 514 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 515 helper0.StartTransaction(transaction_factory_.get()); 516 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount); 517 helper1.StartTransaction(transaction_factory_.get()); 518 519 helper0.Cancel(); 520 521 base::MessageLoop::current()->RunUntilIdle(); 522 523 EXPECT_FALSE(helper0.has_completed()); 524 EXPECT_TRUE(helper1.has_completed()); 525 } 526 527 TEST_F(DnsTransactionTest, DestroyFactory) { 528 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 529 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 530 531 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 532 helper0.StartTransaction(transaction_factory_.get()); 533 534 // Destroying the client does not affect running requests. 535 transaction_factory_.reset(NULL); 536 537 base::MessageLoop::current()->RunUntilIdle(); 538 539 EXPECT_TRUE(helper0.has_completed()); 540 } 541 542 TEST_F(DnsTransactionTest, CancelFromCallback) { 543 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 544 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 545 546 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 547 helper0.set_cancel_in_callback(); 548 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 549 } 550 551 TEST_F(DnsTransactionTest, MismatchedResponseSync) { 552 config_.attempts = 2; 553 config_.timeout = TestTimeouts::tiny_timeout(); 554 ConfigureFactory(); 555 556 // Attempt receives mismatched response followed by valid response. 557 scoped_ptr<DnsSocketData> data( 558 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS, false)); 559 data->AddResponseData(kT1ResponseDatagram, 560 arraysize(kT1ResponseDatagram), SYNCHRONOUS); 561 data->AddResponseData(kT0ResponseDatagram, 562 arraysize(kT0ResponseDatagram), SYNCHRONOUS); 563 AddSocketData(data.Pass()); 564 565 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 566 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); 567 } 568 569 TEST_F(DnsTransactionTest, MismatchedResponseAsync) { 570 config_.attempts = 2; 571 config_.timeout = TestTimeouts::tiny_timeout(); 572 ConfigureFactory(); 573 574 // First attempt receives mismatched response followed by valid response. 575 // Second attempt times out. 576 scoped_ptr<DnsSocketData> data( 577 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, false)); 578 data->AddResponseData(kT1ResponseDatagram, 579 arraysize(kT1ResponseDatagram), ASYNC); 580 data->AddResponseData(kT0ResponseDatagram, 581 arraysize(kT0ResponseDatagram), ASYNC); 582 AddSocketData(data.Pass()); 583 AddQueryAndTimeout(kT0HostName, kT0Qtype); 584 585 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 586 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); 587 } 588 589 TEST_F(DnsTransactionTest, MismatchedResponseFail) { 590 config_.timeout = TestTimeouts::tiny_timeout(); 591 ConfigureFactory(); 592 593 // Attempt receives mismatched response but times out because only one attempt 594 // is allowed. 595 AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype, 596 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 597 598 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT); 599 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); 600 } 601 602 TEST_F(DnsTransactionTest, ServerFail) { 603 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); 604 605 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED); 606 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 607 } 608 609 TEST_F(DnsTransactionTest, NoDomain) { 610 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN); 611 612 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED); 613 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 614 } 615 616 TEST_F(DnsTransactionTest, Timeout) { 617 config_.attempts = 3; 618 // Use short timeout to speed up the test. 619 config_.timeout = TestTimeouts::tiny_timeout(); 620 ConfigureFactory(); 621 622 AddQueryAndTimeout(kT0HostName, kT0Qtype); 623 AddQueryAndTimeout(kT0HostName, kT0Qtype); 624 AddQueryAndTimeout(kT0HostName, kT0Qtype); 625 626 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT); 627 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); 628 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 629 } 630 631 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) { 632 // Test that we fallback on both server failure and timeout. 633 config_.attempts = 2; 634 // The next request should start from the next server. 635 config_.rotate = true; 636 ConfigureNumServers(3); 637 // Use short timeout to speed up the test. 638 config_.timeout = TestTimeouts::tiny_timeout(); 639 ConfigureFactory(); 640 641 // Responses for first request. 642 AddQueryAndTimeout(kT0HostName, kT0Qtype); 643 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); 644 AddQueryAndTimeout(kT0HostName, kT0Qtype); 645 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); 646 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN); 647 // Responses for second request. 648 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL); 649 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL); 650 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN); 651 652 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED); 653 TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED); 654 655 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); 656 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); 657 658 unsigned kOrder[] = { 659 0, 1, 2, 0, 1, // The first transaction. 660 1, 2, 0, // The second transaction starts from the next server. 661 }; 662 CheckServerOrder(kOrder, arraysize(kOrder)); 663 } 664 665 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) { 666 config_.ndots = 2; 667 config_.search.push_back("a"); 668 config_.search.push_back("b"); 669 config_.search.push_back("c"); 670 config_.rotate = true; 671 ConfigureNumServers(2); 672 ConfigureFactory(); 673 674 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA, 675 dns_protocol::kRcodeNXDOMAIN); 676 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA, 677 dns_protocol::kRcodeNXDOMAIN); 678 AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA, 679 dns_protocol::kRcodeNXDOMAIN); 680 AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA, 681 dns_protocol::kRcodeNXDOMAIN); 682 683 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 684 ERR_NAME_NOT_RESOLVED); 685 686 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 687 688 // Also check if suffix search causes server rotation. 689 unsigned kOrder0[] = { 0, 1, 0, 1 }; 690 CheckServerOrder(kOrder0, arraysize(kOrder0)); 691 } 692 693 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) { 694 config_.ndots = 2; 695 config_.search.push_back("a"); 696 config_.search.push_back("b"); 697 config_.search.push_back("c"); 698 ConfigureFactory(); 699 700 // Responses for first transaction. 701 AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA, 702 dns_protocol::kRcodeNXDOMAIN); 703 AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA, 704 dns_protocol::kRcodeNXDOMAIN); 705 AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA, 706 dns_protocol::kRcodeNXDOMAIN); 707 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA, 708 dns_protocol::kRcodeNXDOMAIN); 709 // Responses for second transaction. 710 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA, 711 dns_protocol::kRcodeNXDOMAIN); 712 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA, 713 dns_protocol::kRcodeNXDOMAIN); 714 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA, 715 dns_protocol::kRcodeNXDOMAIN); 716 // Responses for third transaction. 717 AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA, 718 dns_protocol::kRcodeNXDOMAIN); 719 720 TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); 721 722 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 723 724 // A single-label name. 725 TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); 726 727 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); 728 729 // A fully-qualified name. 730 TransactionHelper helper2("x.", dns_protocol::kTypeAAAA, 731 ERR_NAME_NOT_RESOLVED); 732 733 EXPECT_TRUE(helper2.Run(transaction_factory_.get())); 734 } 735 736 TEST_F(DnsTransactionTest, EmptySuffixSearch) { 737 // Responses for first transaction. 738 AddAsyncQueryAndRcode("x", dns_protocol::kTypeA, 739 dns_protocol::kRcodeNXDOMAIN); 740 741 // A fully-qualified name. 742 TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); 743 744 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 745 746 // A single label name is not even attempted. 747 TransactionHelper helper1("singlelabel", dns_protocol::kTypeA, 748 ERR_DNS_SEARCH_EMPTY); 749 750 helper1.Run(transaction_factory_.get()); 751 EXPECT_TRUE(helper1.has_completed()); 752 } 753 754 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) { 755 config_.search.push_back("a"); 756 config_.search.push_back("b"); 757 config_.search.push_back("c"); 758 config_.append_to_multi_label_name = false; 759 ConfigureFactory(); 760 761 // Responses for first transaction. 762 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA, 763 dns_protocol::kRcodeNXDOMAIN); 764 // Responses for second transaction. 765 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA, 766 dns_protocol::kRcodeNXDOMAIN); 767 // Responses for third transaction. 768 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA, 769 dns_protocol::kRcodeNXDOMAIN); 770 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA, 771 dns_protocol::kRcodeNXDOMAIN); 772 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA, 773 dns_protocol::kRcodeNXDOMAIN); 774 775 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 776 ERR_NAME_NOT_RESOLVED); 777 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 778 779 TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); 780 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); 781 782 TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); 783 EXPECT_TRUE(helper2.Run(transaction_factory_.get())); 784 } 785 786 const uint8 kResponseNoData[] = { 787 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 788 // Question 789 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 790 // Authority section, SOA record, TTL 0x3E6 791 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6, 792 // Minimal RDATA, 18 bytes 793 0x00, 0x12, 794 0x00, 0x00, 795 0x00, 0x00, 0x00, 0x00, 796 0x00, 0x00, 0x00, 0x00, 797 0x00, 0x00, 0x00, 0x00, 798 0x00, 0x00, 0x00, 0x00, 799 }; 800 801 TEST_F(DnsTransactionTest, SuffixSearchStop) { 802 config_.ndots = 2; 803 config_.search.push_back("a"); 804 config_.search.push_back("b"); 805 config_.search.push_back("c"); 806 ConfigureFactory(); 807 808 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA, 809 dns_protocol::kRcodeNXDOMAIN); 810 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA, 811 dns_protocol::kRcodeNXDOMAIN); 812 AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA, 813 kResponseNoData, arraysize(kResponseNoData)); 814 815 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */); 816 817 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 818 } 819 820 TEST_F(DnsTransactionTest, SyncFirstQuery) { 821 config_.search.push_back("lab.ccs.neu.edu"); 822 config_.search.push_back("ccs.neu.edu"); 823 ConfigureFactory(); 824 825 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 826 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 827 828 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 829 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 830 } 831 832 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) { 833 config_.search.push_back("lab.ccs.neu.edu"); 834 config_.search.push_back("ccs.neu.edu"); 835 ConfigureFactory(); 836 837 AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype, 838 dns_protocol::kRcodeNXDOMAIN); 839 // "www.ccs.neu.edu" 840 AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype, 841 kT2ResponseDatagram, arraysize(kT2ResponseDatagram)); 842 843 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount); 844 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 845 } 846 847 TEST_F(DnsTransactionTest, SyncSearchQuery) { 848 config_.search.push_back("lab.ccs.neu.edu"); 849 config_.search.push_back("ccs.neu.edu"); 850 ConfigureFactory(); 851 852 AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA, 853 dns_protocol::kRcodeNXDOMAIN); 854 AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype, 855 kT2ResponseDatagram, arraysize(kT2ResponseDatagram)); 856 857 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount); 858 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 859 } 860 861 TEST_F(DnsTransactionTest, ConnectFailure) { 862 socket_factory_->fail_next_socket_ = true; 863 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt. 864 TransactionHelper helper0("www.chromium.org", dns_protocol::kTypeA, 865 ERR_CONNECTION_REFUSED); 866 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 867 } 868 869 TEST_F(DnsTransactionTest, ConnectFailureFollowedBySuccess) { 870 // Retry after server failure. 871 config_.attempts = 2; 872 ConfigureFactory(); 873 // First server connection attempt fails. 874 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt. 875 socket_factory_->fail_next_socket_ = true; 876 // Second DNS query succeeds. 877 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 878 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); 879 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 880 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 881 } 882 883 TEST_F(DnsTransactionTest, TCPLookup) { 884 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 885 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 886 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, 887 kT0ResponseDatagram, arraysize(kT0ResponseDatagram), 888 ASYNC, true /* use_tcp */); 889 890 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); 891 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 892 } 893 894 TEST_F(DnsTransactionTest, TCPFailure) { 895 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 896 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 897 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL, 898 ASYNC, true /* use_tcp */); 899 900 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED); 901 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 902 } 903 904 TEST_F(DnsTransactionTest, TCPMalformed) { 905 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 906 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 907 scoped_ptr<DnsSocketData> data( 908 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true)); 909 // Valid response but length too short. 910 // This must be truncated in the question section. The DnsResponse doesn't 911 // examine the answer section until asked to parse it, so truncating it in 912 // the answer section would result in the DnsTransaction itself succeeding. 913 data->AddResponseWithLength( 914 make_scoped_ptr( 915 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram), 916 arraysize(kT0ResponseDatagram), 0)), 917 ASYNC, 918 static_cast<uint16>(kT0QuerySize - 1)); 919 AddSocketData(data.Pass()); 920 921 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_MALFORMED_RESPONSE); 922 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 923 } 924 925 TEST_F(DnsTransactionTest, TCPTimeout) { 926 config_.timeout = TestTimeouts::tiny_timeout(); 927 ConfigureFactory(); 928 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 929 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 930 AddSocketData(make_scoped_ptr( 931 new DnsSocketData(1 /* id */, kT0HostName, kT0Qtype, ASYNC, true))); 932 933 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT); 934 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); 935 } 936 937 TEST_F(DnsTransactionTest, TCPReadReturnsZeroAsync) { 938 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 939 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 940 scoped_ptr<DnsSocketData> data( 941 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true)); 942 // Return all but the last byte of the response. 943 data->AddResponseWithLength( 944 make_scoped_ptr( 945 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram), 946 arraysize(kT0ResponseDatagram) - 1, 0)), 947 ASYNC, 948 static_cast<uint16>(arraysize(kT0ResponseDatagram))); 949 // Then return a 0-length read. 950 data->AddReadError(0, ASYNC); 951 AddSocketData(data.Pass()); 952 953 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED); 954 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 955 } 956 957 TEST_F(DnsTransactionTest, TCPReadReturnsZeroSynchronous) { 958 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 959 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 960 scoped_ptr<DnsSocketData> data( 961 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true)); 962 // Return all but the last byte of the response. 963 data->AddResponseWithLength( 964 make_scoped_ptr( 965 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram), 966 arraysize(kT0ResponseDatagram) - 1, 0)), 967 SYNCHRONOUS, 968 static_cast<uint16>(arraysize(kT0ResponseDatagram))); 969 // Then return a 0-length read. 970 data->AddReadError(0, SYNCHRONOUS); 971 AddSocketData(data.Pass()); 972 973 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED); 974 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 975 } 976 977 TEST_F(DnsTransactionTest, TCPConnectionClosedAsync) { 978 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 979 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 980 scoped_ptr<DnsSocketData> data( 981 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true)); 982 data->AddReadError(ERR_CONNECTION_CLOSED, ASYNC); 983 AddSocketData(data.Pass()); 984 985 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED); 986 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 987 } 988 989 TEST_F(DnsTransactionTest, TCPConnectionClosedSynchronous) { 990 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, 991 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC); 992 scoped_ptr<DnsSocketData> data( 993 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true)); 994 data->AddReadError(ERR_CONNECTION_CLOSED, SYNCHRONOUS); 995 AddSocketData(data.Pass()); 996 997 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED); 998 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 999 } 1000 1001 TEST_F(DnsTransactionTest, InvalidQuery) { 1002 config_.timeout = TestTimeouts::tiny_timeout(); 1003 ConfigureFactory(); 1004 1005 TransactionHelper helper0(".", dns_protocol::kTypeA, ERR_INVALID_ARGUMENT); 1006 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); 1007 } 1008 1009 } // namespace 1010 1011 } // namespace net 1012