Add explicit |forceOnlineSignin| to user pod status
[chromium-blink-merge.git] / net / dns / dns_transaction_unittest.cc
blob7040e44be1636a51590fd32296f92c4d65a37c5e
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.
5 #include "net/dns/dns_transaction.h"
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/big_endian.h"
14 #include "net/base/dns_util.h"
15 #include "net/base/net_log.h"
16 #include "net/dns/dns_protocol.h"
17 #include "net/dns/dns_query.h"
18 #include "net/dns/dns_response.h"
19 #include "net/dns/dns_session.h"
20 #include "net/dns/dns_test_util.h"
21 #include "net/socket/socket_test_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 namespace net {
26 namespace {
28 std::string DomainFromDot(const base::StringPiece& dotted) {
29 std::string out;
30 EXPECT_TRUE(DNSDomainFromDot(dotted, &out));
31 return out;
34 // A SocketDataProvider builder.
35 class DnsSocketData {
36 public:
37 // The ctor takes parameters for the DnsQuery.
38 DnsSocketData(uint16 id,
39 const char* dotted_name,
40 uint16 qtype,
41 IoMode mode,
42 bool use_tcp)
43 : query_(new DnsQuery(id, DomainFromDot(dotted_name), qtype)),
44 use_tcp_(use_tcp) {
45 if (use_tcp_) {
46 scoped_ptr<uint16> length(new uint16);
47 *length = base::HostToNet16(query_->io_buffer()->size());
48 writes_.push_back(MockWrite(mode,
49 reinterpret_cast<const char*>(length.get()),
50 sizeof(uint16)));
51 lengths_.push_back(length.release());
53 writes_.push_back(MockWrite(mode,
54 query_->io_buffer()->data(),
55 query_->io_buffer()->size()));
57 ~DnsSocketData() {}
59 // All responses must be added before GetProvider.
61 // Adds pre-built DnsResponse. |tcp_length| will be used in TCP mode only.
62 void AddResponseWithLength(scoped_ptr<DnsResponse> response, IoMode mode,
63 uint16 tcp_length) {
64 CHECK(!provider_.get());
65 if (use_tcp_) {
66 scoped_ptr<uint16> length(new uint16);
67 *length = base::HostToNet16(tcp_length);
68 reads_.push_back(MockRead(mode,
69 reinterpret_cast<const char*>(length.get()),
70 sizeof(uint16)));
71 lengths_.push_back(length.release());
73 reads_.push_back(MockRead(mode,
74 response->io_buffer()->data(),
75 response->io_buffer()->size()));
76 responses_.push_back(response.release());
79 // Adds pre-built DnsResponse.
80 void AddResponse(scoped_ptr<DnsResponse> response, IoMode mode) {
81 uint16 tcp_length = response->io_buffer()->size();
82 AddResponseWithLength(response.Pass(), mode, tcp_length);
85 // Adds pre-built response from |data| buffer.
86 void AddResponseData(const uint8* data, size_t length, IoMode mode) {
87 CHECK(!provider_.get());
88 AddResponse(make_scoped_ptr(
89 new DnsResponse(reinterpret_cast<const char*>(data), length, 0)), mode);
92 // Add no-answer (RCODE only) response matching the query.
93 void AddRcode(int rcode, IoMode mode) {
94 scoped_ptr<DnsResponse> response(
95 new DnsResponse(query_->io_buffer()->data(),
96 query_->io_buffer()->size(),
97 0));
98 dns_protocol::Header* header =
99 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data());
100 header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode);
101 AddResponse(response.Pass(), mode);
104 // Build, if needed, and return the SocketDataProvider. No new responses
105 // should be added afterwards.
106 SocketDataProvider* GetProvider() {
107 if (provider_.get())
108 return provider_.get();
109 // Terminate the reads with ERR_IO_PENDING to prevent overrun and default to
110 // timeout.
111 reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING));
112 provider_.reset(new DelayedSocketData(1, &reads_[0], reads_.size(),
113 &writes_[0], writes_.size()));
114 if (use_tcp_) {
115 provider_->set_connect_data(MockConnect(reads_[0].mode, OK));
117 return provider_.get();
120 uint16 query_id() const {
121 return query_->id();
124 // Returns true if the expected query was written to the socket.
125 bool was_written() const {
126 CHECK(provider_.get());
127 return provider_->write_index() > 0;
130 private:
131 scoped_ptr<DnsQuery> query_;
132 bool use_tcp_;
133 ScopedVector<uint16> lengths_;
134 ScopedVector<DnsResponse> responses_;
135 std::vector<MockWrite> writes_;
136 std::vector<MockRead> reads_;
137 scoped_ptr<DelayedSocketData> provider_;
139 DISALLOW_COPY_AND_ASSIGN(DnsSocketData);
142 class TestSocketFactory;
144 // A variant of MockUDPClientSocket which always fails to Connect.
145 class FailingUDPClientSocket : public MockUDPClientSocket {
146 public:
147 FailingUDPClientSocket(SocketDataProvider* data,
148 net::NetLog* net_log)
149 : MockUDPClientSocket(data, net_log) {
151 virtual ~FailingUDPClientSocket() {}
152 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE {
153 return ERR_CONNECTION_REFUSED;
156 private:
157 DISALLOW_COPY_AND_ASSIGN(FailingUDPClientSocket);
160 // A variant of MockUDPClientSocket which notifies the factory OnConnect.
161 class TestUDPClientSocket : public MockUDPClientSocket {
162 public:
163 TestUDPClientSocket(TestSocketFactory* factory,
164 SocketDataProvider* data,
165 net::NetLog* net_log)
166 : MockUDPClientSocket(data, net_log), factory_(factory) {
168 virtual ~TestUDPClientSocket() {}
169 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE;
171 private:
172 TestSocketFactory* factory_;
174 DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket);
177 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
178 class TestSocketFactory : public MockClientSocketFactory {
179 public:
180 TestSocketFactory() : fail_next_socket_(false) {}
181 virtual ~TestSocketFactory() {}
183 virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket(
184 DatagramSocket::BindType bind_type,
185 const RandIntCallback& rand_int_cb,
186 net::NetLog* net_log,
187 const net::NetLog::Source& source) OVERRIDE {
188 if (fail_next_socket_) {
189 fail_next_socket_ = false;
190 return scoped_ptr<DatagramClientSocket>(
191 new FailingUDPClientSocket(&empty_data_, net_log));
193 SocketDataProvider* data_provider = mock_data().GetNext();
194 scoped_ptr<TestUDPClientSocket> socket(
195 new TestUDPClientSocket(this, data_provider, net_log));
196 data_provider->set_socket(socket.get());
197 return socket.PassAs<DatagramClientSocket>();
200 void OnConnect(const IPEndPoint& endpoint) {
201 remote_endpoints_.push_back(endpoint);
204 std::vector<IPEndPoint> remote_endpoints_;
205 bool fail_next_socket_;
207 private:
208 StaticSocketDataProvider empty_data_;
210 DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
213 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
214 factory_->OnConnect(endpoint);
215 return MockUDPClientSocket::Connect(endpoint);
218 // Helper class that holds a DnsTransaction and handles OnTransactionComplete.
219 class TransactionHelper {
220 public:
221 // If |expected_answer_count| < 0 then it is the expected net error.
222 TransactionHelper(const char* hostname,
223 uint16 qtype,
224 int expected_answer_count)
225 : hostname_(hostname),
226 qtype_(qtype),
227 expected_answer_count_(expected_answer_count),
228 cancel_in_callback_(false),
229 quit_in_callback_(false),
230 completed_(false) {
233 // Mark that the transaction shall be destroyed immediately upon callback.
234 void set_cancel_in_callback() {
235 cancel_in_callback_ = true;
238 // Mark to call MessageLoop::Quit() upon callback.
239 void set_quit_in_callback() {
240 quit_in_callback_ = true;
243 void StartTransaction(DnsTransactionFactory* factory) {
244 EXPECT_EQ(NULL, transaction_.get());
245 transaction_ = factory->CreateTransaction(
246 hostname_,
247 qtype_,
248 base::Bind(&TransactionHelper::OnTransactionComplete,
249 base::Unretained(this)),
250 BoundNetLog());
251 EXPECT_EQ(hostname_, transaction_->GetHostname());
252 EXPECT_EQ(qtype_, transaction_->GetType());
253 transaction_->Start();
256 void Cancel() {
257 ASSERT_TRUE(transaction_.get() != NULL);
258 transaction_.reset(NULL);
261 void OnTransactionComplete(DnsTransaction* t,
262 int rv,
263 const DnsResponse* response) {
264 EXPECT_FALSE(completed_);
265 EXPECT_EQ(transaction_.get(), t);
267 completed_ = true;
269 if (cancel_in_callback_) {
270 Cancel();
271 return;
274 // Tell MessageLoop to quit now, in case any ASSERT_* fails.
275 if (quit_in_callback_)
276 base::MessageLoop::current()->Quit();
278 if (expected_answer_count_ >= 0) {
279 ASSERT_EQ(OK, rv);
280 ASSERT_TRUE(response != NULL);
281 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_),
282 response->answer_count());
283 EXPECT_EQ(qtype_, response->qtype());
285 DnsRecordParser parser = response->Parser();
286 DnsResourceRecord record;
287 for (int i = 0; i < expected_answer_count_; ++i) {
288 EXPECT_TRUE(parser.ReadRecord(&record));
290 } else {
291 EXPECT_EQ(expected_answer_count_, rv);
295 bool has_completed() const {
296 return completed_;
299 // Shorthands for commonly used commands.
301 bool Run(DnsTransactionFactory* factory) {
302 StartTransaction(factory);
303 base::MessageLoop::current()->RunUntilIdle();
304 return has_completed();
307 // Use when some of the responses are timeouts.
308 bool RunUntilDone(DnsTransactionFactory* factory) {
309 set_quit_in_callback();
310 StartTransaction(factory);
311 base::MessageLoop::current()->Run();
312 return has_completed();
315 private:
316 std::string hostname_;
317 uint16 qtype_;
318 scoped_ptr<DnsTransaction> transaction_;
319 int expected_answer_count_;
320 bool cancel_in_callback_;
321 bool quit_in_callback_;
323 bool completed_;
326 class DnsTransactionTest : public testing::Test {
327 public:
328 DnsTransactionTest() {}
330 // Generates |nameservers| for DnsConfig.
331 void ConfigureNumServers(unsigned num_servers) {
332 CHECK_LE(num_servers, 255u);
333 config_.nameservers.clear();
334 IPAddressNumber dns_ip;
336 bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
337 EXPECT_TRUE(rv);
339 for (unsigned i = 0; i < num_servers; ++i) {
340 dns_ip[3] = i;
341 config_.nameservers.push_back(IPEndPoint(dns_ip,
342 dns_protocol::kDefaultPort));
346 // Called after fully configuring |config|.
347 void ConfigureFactory() {
348 socket_factory_.reset(new TestSocketFactory());
349 session_ = new DnsSession(
350 config_,
351 DnsSocketPool::CreateNull(socket_factory_.get()),
352 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)),
353 NULL /* NetLog */);
354 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
357 void AddSocketData(scoped_ptr<DnsSocketData> data) {
358 CHECK(socket_factory_.get());
359 transaction_ids_.push_back(data->query_id());
360 socket_factory_->AddSocketDataProvider(data->GetProvider());
361 socket_data_.push_back(data.release());
364 // Add expected query for |dotted_name| and |qtype| with |id| and response
365 // taken verbatim from |data| of |data_length| bytes. The transaction id in
366 // |data| should equal |id|, unless testing mismatched response.
367 void AddQueryAndResponse(uint16 id,
368 const char* dotted_name,
369 uint16 qtype,
370 const uint8* response_data,
371 size_t response_length,
372 IoMode mode,
373 bool use_tcp) {
374 CHECK(socket_factory_.get());
375 scoped_ptr<DnsSocketData> data(
376 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
377 data->AddResponseData(response_data, response_length, mode);
378 AddSocketData(data.Pass());
381 void AddAsyncQueryAndResponse(uint16 id,
382 const char* dotted_name,
383 uint16 qtype,
384 const uint8* data,
385 size_t data_length) {
386 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC,
387 false);
390 void AddSyncQueryAndResponse(uint16 id,
391 const char* dotted_name,
392 uint16 qtype,
393 const uint8* data,
394 size_t data_length) {
395 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS,
396 false);
399 // Add expected query of |dotted_name| and |qtype| and no response.
400 void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) {
401 uint16 id = base::RandInt(0, kuint16max);
402 scoped_ptr<DnsSocketData> data(
403 new DnsSocketData(id, dotted_name, qtype, ASYNC, false));
404 AddSocketData(data.Pass());
407 // Add expected query of |dotted_name| and |qtype| and matching response with
408 // no answer and RCODE set to |rcode|. The id will be generated randomly.
409 void AddQueryAndRcode(const char* dotted_name,
410 uint16 qtype,
411 int rcode,
412 IoMode mode,
413 bool use_tcp) {
414 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
415 uint16 id = base::RandInt(0, kuint16max);
416 scoped_ptr<DnsSocketData> data(
417 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
418 data->AddRcode(rcode, mode);
419 AddSocketData(data.Pass());
422 void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
423 AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false);
426 void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
427 AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false);
430 // Checks if the sockets were connected in the order matching the indices in
431 // |servers|.
432 void CheckServerOrder(const unsigned* servers, size_t num_attempts) {
433 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size());
434 for (size_t i = 0; i < num_attempts; ++i) {
435 EXPECT_EQ(socket_factory_->remote_endpoints_[i],
436 session_->config().nameservers[servers[i]]);
440 virtual void SetUp() OVERRIDE {
441 // By default set one server,
442 ConfigureNumServers(1);
443 // and no retransmissions,
444 config_.attempts = 1;
445 // but long enough timeout for memory tests.
446 config_.timeout = TestTimeouts::action_timeout();
447 ConfigureFactory();
450 virtual void TearDown() OVERRIDE {
451 // Check that all socket data was at least written to.
452 for (size_t i = 0; i < socket_data_.size(); ++i) {
453 EXPECT_TRUE(socket_data_[i]->was_written()) << i;
457 protected:
458 int GetNextId(int min, int max) {
459 EXPECT_FALSE(transaction_ids_.empty());
460 int id = transaction_ids_.front();
461 transaction_ids_.pop_front();
462 EXPECT_GE(id, min);
463 EXPECT_LE(id, max);
464 return id;
467 DnsConfig config_;
469 ScopedVector<DnsSocketData> socket_data_;
471 std::deque<int> transaction_ids_;
472 scoped_ptr<TestSocketFactory> socket_factory_;
473 scoped_refptr<DnsSession> session_;
474 scoped_ptr<DnsTransactionFactory> transaction_factory_;
477 TEST_F(DnsTransactionTest, Lookup) {
478 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
479 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
481 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
482 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
485 // Concurrent lookup tests assume that DnsTransaction::Start immediately
486 // consumes a socket from ClientSocketFactory.
487 TEST_F(DnsTransactionTest, ConcurrentLookup) {
488 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
489 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
490 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
491 kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
493 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
494 helper0.StartTransaction(transaction_factory_.get());
495 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
496 helper1.StartTransaction(transaction_factory_.get());
498 base::MessageLoop::current()->RunUntilIdle();
500 EXPECT_TRUE(helper0.has_completed());
501 EXPECT_TRUE(helper1.has_completed());
504 TEST_F(DnsTransactionTest, CancelLookup) {
505 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
506 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
507 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
508 kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
510 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
511 helper0.StartTransaction(transaction_factory_.get());
512 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
513 helper1.StartTransaction(transaction_factory_.get());
515 helper0.Cancel();
517 base::MessageLoop::current()->RunUntilIdle();
519 EXPECT_FALSE(helper0.has_completed());
520 EXPECT_TRUE(helper1.has_completed());
523 TEST_F(DnsTransactionTest, DestroyFactory) {
524 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
525 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
527 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
528 helper0.StartTransaction(transaction_factory_.get());
530 // Destroying the client does not affect running requests.
531 transaction_factory_.reset(NULL);
533 base::MessageLoop::current()->RunUntilIdle();
535 EXPECT_TRUE(helper0.has_completed());
538 TEST_F(DnsTransactionTest, CancelFromCallback) {
539 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
540 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
542 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
543 helper0.set_cancel_in_callback();
544 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
547 TEST_F(DnsTransactionTest, MismatchedResponseSync) {
548 config_.attempts = 2;
549 config_.timeout = TestTimeouts::tiny_timeout();
550 ConfigureFactory();
552 // Attempt receives mismatched response followed by valid response.
553 scoped_ptr<DnsSocketData> data(
554 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS, false));
555 data->AddResponseData(kT1ResponseDatagram,
556 arraysize(kT1ResponseDatagram), SYNCHRONOUS);
557 data->AddResponseData(kT0ResponseDatagram,
558 arraysize(kT0ResponseDatagram), SYNCHRONOUS);
559 AddSocketData(data.Pass());
561 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
562 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
565 TEST_F(DnsTransactionTest, MismatchedResponseAsync) {
566 config_.attempts = 2;
567 config_.timeout = TestTimeouts::tiny_timeout();
568 ConfigureFactory();
570 // First attempt receives mismatched response followed by valid response.
571 // Second attempt times out.
572 scoped_ptr<DnsSocketData> data(
573 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, false));
574 data->AddResponseData(kT1ResponseDatagram,
575 arraysize(kT1ResponseDatagram), ASYNC);
576 data->AddResponseData(kT0ResponseDatagram,
577 arraysize(kT0ResponseDatagram), ASYNC);
578 AddSocketData(data.Pass());
579 AddQueryAndTimeout(kT0HostName, kT0Qtype);
581 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
582 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
585 TEST_F(DnsTransactionTest, MismatchedResponseFail) {
586 config_.timeout = TestTimeouts::tiny_timeout();
587 ConfigureFactory();
589 // Attempt receives mismatched response but times out because only one attempt
590 // is allowed.
591 AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype,
592 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
594 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
595 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
598 TEST_F(DnsTransactionTest, ServerFail) {
599 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
601 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
602 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
605 TEST_F(DnsTransactionTest, NoDomain) {
606 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
608 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
609 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
612 TEST_F(DnsTransactionTest, Timeout) {
613 config_.attempts = 3;
614 // Use short timeout to speed up the test.
615 config_.timeout = TestTimeouts::tiny_timeout();
616 ConfigureFactory();
618 AddQueryAndTimeout(kT0HostName, kT0Qtype);
619 AddQueryAndTimeout(kT0HostName, kT0Qtype);
620 AddQueryAndTimeout(kT0HostName, kT0Qtype);
622 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
623 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
624 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
627 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) {
628 // Test that we fallback on both server failure and timeout.
629 config_.attempts = 2;
630 // The next request should start from the next server.
631 config_.rotate = true;
632 ConfigureNumServers(3);
633 // Use short timeout to speed up the test.
634 config_.timeout = TestTimeouts::tiny_timeout();
635 ConfigureFactory();
637 // Responses for first request.
638 AddQueryAndTimeout(kT0HostName, kT0Qtype);
639 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
640 AddQueryAndTimeout(kT0HostName, kT0Qtype);
641 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
642 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
643 // Responses for second request.
644 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
645 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
646 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN);
648 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
649 TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED);
651 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
652 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
654 unsigned kOrder[] = {
655 0, 1, 2, 0, 1, // The first transaction.
656 1, 2, 0, // The second transaction starts from the next server.
658 CheckServerOrder(kOrder, arraysize(kOrder));
661 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {
662 config_.ndots = 2;
663 config_.search.push_back("a");
664 config_.search.push_back("b");
665 config_.search.push_back("c");
666 config_.rotate = true;
667 ConfigureNumServers(2);
668 ConfigureFactory();
670 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
671 dns_protocol::kRcodeNXDOMAIN);
672 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
673 dns_protocol::kRcodeNXDOMAIN);
674 AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA,
675 dns_protocol::kRcodeNXDOMAIN);
676 AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA,
677 dns_protocol::kRcodeNXDOMAIN);
679 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
680 ERR_NAME_NOT_RESOLVED);
682 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
684 // Also check if suffix search causes server rotation.
685 unsigned kOrder0[] = { 0, 1, 0, 1 };
686 CheckServerOrder(kOrder0, arraysize(kOrder0));
689 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {
690 config_.ndots = 2;
691 config_.search.push_back("a");
692 config_.search.push_back("b");
693 config_.search.push_back("c");
694 ConfigureFactory();
696 // Responses for first transaction.
697 AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA,
698 dns_protocol::kRcodeNXDOMAIN);
699 AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA,
700 dns_protocol::kRcodeNXDOMAIN);
701 AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA,
702 dns_protocol::kRcodeNXDOMAIN);
703 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
704 dns_protocol::kRcodeNXDOMAIN);
705 // Responses for second transaction.
706 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
707 dns_protocol::kRcodeNXDOMAIN);
708 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
709 dns_protocol::kRcodeNXDOMAIN);
710 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
711 dns_protocol::kRcodeNXDOMAIN);
712 // Responses for third transaction.
713 AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA,
714 dns_protocol::kRcodeNXDOMAIN);
716 TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
718 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
720 // A single-label name.
721 TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
723 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
725 // A fully-qualified name.
726 TransactionHelper helper2("x.", dns_protocol::kTypeAAAA,
727 ERR_NAME_NOT_RESOLVED);
729 EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
732 TEST_F(DnsTransactionTest, EmptySuffixSearch) {
733 // Responses for first transaction.
734 AddAsyncQueryAndRcode("x", dns_protocol::kTypeA,
735 dns_protocol::kRcodeNXDOMAIN);
737 // A fully-qualified name.
738 TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
740 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
742 // A single label name is not even attempted.
743 TransactionHelper helper1("singlelabel", dns_protocol::kTypeA,
744 ERR_DNS_SEARCH_EMPTY);
746 helper1.Run(transaction_factory_.get());
747 EXPECT_TRUE(helper1.has_completed());
750 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) {
751 config_.search.push_back("a");
752 config_.search.push_back("b");
753 config_.search.push_back("c");
754 config_.append_to_multi_label_name = false;
755 ConfigureFactory();
757 // Responses for first transaction.
758 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
759 dns_protocol::kRcodeNXDOMAIN);
760 // Responses for second transaction.
761 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
762 dns_protocol::kRcodeNXDOMAIN);
763 // Responses for third transaction.
764 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
765 dns_protocol::kRcodeNXDOMAIN);
766 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
767 dns_protocol::kRcodeNXDOMAIN);
768 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
769 dns_protocol::kRcodeNXDOMAIN);
771 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
772 ERR_NAME_NOT_RESOLVED);
773 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
775 TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
776 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
778 TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
779 EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
782 const uint8 kResponseNoData[] = {
783 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
784 // Question
785 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01,
786 // Authority section, SOA record, TTL 0x3E6
787 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6,
788 // Minimal RDATA, 18 bytes
789 0x00, 0x12,
790 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00,
797 TEST_F(DnsTransactionTest, SuffixSearchStop) {
798 config_.ndots = 2;
799 config_.search.push_back("a");
800 config_.search.push_back("b");
801 config_.search.push_back("c");
802 ConfigureFactory();
804 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
805 dns_protocol::kRcodeNXDOMAIN);
806 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
807 dns_protocol::kRcodeNXDOMAIN);
808 AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA,
809 kResponseNoData, arraysize(kResponseNoData));
811 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */);
813 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
816 TEST_F(DnsTransactionTest, SyncFirstQuery) {
817 config_.search.push_back("lab.ccs.neu.edu");
818 config_.search.push_back("ccs.neu.edu");
819 ConfigureFactory();
821 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
822 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
824 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
825 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
828 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {
829 config_.search.push_back("lab.ccs.neu.edu");
830 config_.search.push_back("ccs.neu.edu");
831 ConfigureFactory();
833 AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype,
834 dns_protocol::kRcodeNXDOMAIN);
835 // "www.ccs.neu.edu"
836 AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
837 kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
839 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
840 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
843 TEST_F(DnsTransactionTest, SyncSearchQuery) {
844 config_.search.push_back("lab.ccs.neu.edu");
845 config_.search.push_back("ccs.neu.edu");
846 ConfigureFactory();
848 AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA,
849 dns_protocol::kRcodeNXDOMAIN);
850 AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
851 kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
853 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
854 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
857 TEST_F(DnsTransactionTest, ConnectFailure) {
858 socket_factory_->fail_next_socket_ = true;
859 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
860 TransactionHelper helper0("www.chromium.org", dns_protocol::kTypeA,
861 ERR_CONNECTION_REFUSED);
862 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
865 TEST_F(DnsTransactionTest, ConnectFailureFollowedBySuccess) {
866 // Retry after server failure.
867 config_.attempts = 2;
868 ConfigureFactory();
869 // First server connection attempt fails.
870 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
871 socket_factory_->fail_next_socket_ = true;
872 // Second DNS query succeeds.
873 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
874 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
875 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
876 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
879 TEST_F(DnsTransactionTest, TCPLookup) {
880 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
881 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
882 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
883 kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
884 ASYNC, true /* use_tcp */);
886 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
887 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
890 TEST_F(DnsTransactionTest, TCPFailure) {
891 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
892 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
893 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
894 ASYNC, true /* use_tcp */);
896 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
897 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
900 TEST_F(DnsTransactionTest, TCPMalformed) {
901 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
902 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
903 scoped_ptr<DnsSocketData> data(
904 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
905 // Valid response but length too short.
906 data->AddResponseWithLength(
907 make_scoped_ptr(
908 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
909 arraysize(kT0ResponseDatagram), 0)),
910 ASYNC,
911 static_cast<uint16>(kT0QuerySize - 1));
912 AddSocketData(data.Pass());
914 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_MALFORMED_RESPONSE);
915 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
918 TEST_F(DnsTransactionTest, TCPTimeout) {
919 config_.timeout = TestTimeouts::tiny_timeout();
920 ConfigureFactory();
921 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
922 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
923 AddSocketData(make_scoped_ptr(
924 new DnsSocketData(1 /* id */, kT0HostName, kT0Qtype, ASYNC, true)));
926 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
927 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
930 TEST_F(DnsTransactionTest, InvalidQuery) {
931 config_.timeout = TestTimeouts::tiny_timeout();
932 ConfigureFactory();
934 TransactionHelper helper0(".", dns_protocol::kTypeA, ERR_INVALID_ARGUMENT);
935 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
938 } // namespace
940 } // namespace net