Revert "Merged all Chromoting Host code into remoting_core.dll (Windows)."
[chromium-blink-merge.git] / net / dns / dns_transaction_unittest.cc
blob91840230ac52d61fab788c1005dd0b75645e048c
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() : create_failing_sockets_(false) {}
181 virtual ~TestSocketFactory() {}
183 virtual 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 (create_failing_sockets_)
189 return new FailingUDPClientSocket(&empty_data_, net_log);
190 SocketDataProvider* data_provider = mock_data().GetNext();
191 TestUDPClientSocket* socket = new TestUDPClientSocket(this,
192 data_provider,
193 net_log);
194 data_provider->set_socket(socket);
195 return socket;
198 void OnConnect(const IPEndPoint& endpoint) {
199 remote_endpoints_.push_back(endpoint);
202 std::vector<IPEndPoint> remote_endpoints_;
203 bool create_failing_sockets_;
205 private:
206 StaticSocketDataProvider empty_data_;
208 DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
211 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
212 factory_->OnConnect(endpoint);
213 return MockUDPClientSocket::Connect(endpoint);
216 // Helper class that holds a DnsTransaction and handles OnTransactionComplete.
217 class TransactionHelper {
218 public:
219 // If |expected_answer_count| < 0 then it is the expected net error.
220 TransactionHelper(const char* hostname,
221 uint16 qtype,
222 int expected_answer_count)
223 : hostname_(hostname),
224 qtype_(qtype),
225 expected_answer_count_(expected_answer_count),
226 cancel_in_callback_(false),
227 quit_in_callback_(false),
228 completed_(false) {
231 // Mark that the transaction shall be destroyed immediately upon callback.
232 void set_cancel_in_callback() {
233 cancel_in_callback_ = true;
236 // Mark to call MessageLoop::Quit() upon callback.
237 void set_quit_in_callback() {
238 quit_in_callback_ = true;
241 void StartTransaction(DnsTransactionFactory* factory) {
242 EXPECT_EQ(NULL, transaction_.get());
243 transaction_ = factory->CreateTransaction(
244 hostname_,
245 qtype_,
246 base::Bind(&TransactionHelper::OnTransactionComplete,
247 base::Unretained(this)),
248 BoundNetLog());
249 EXPECT_EQ(hostname_, transaction_->GetHostname());
250 EXPECT_EQ(qtype_, transaction_->GetType());
251 int rv = transaction_->Start();
252 if (rv != ERR_IO_PENDING) {
253 EXPECT_NE(OK, rv);
254 EXPECT_EQ(expected_answer_count_, rv);
255 completed_ = true;
259 void Cancel() {
260 ASSERT_TRUE(transaction_.get() != NULL);
261 transaction_.reset(NULL);
264 void OnTransactionComplete(DnsTransaction* t,
265 int rv,
266 const DnsResponse* response) {
267 EXPECT_FALSE(completed_);
268 EXPECT_EQ(transaction_.get(), t);
270 completed_ = true;
272 if (cancel_in_callback_) {
273 Cancel();
274 return;
277 // Tell MessageLoop to quit now, in case any ASSERT_* fails.
278 if (quit_in_callback_)
279 MessageLoop::current()->Quit();
281 if (expected_answer_count_ >= 0) {
282 ASSERT_EQ(OK, rv);
283 ASSERT_TRUE(response != NULL);
284 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_),
285 response->answer_count());
286 EXPECT_EQ(qtype_, response->qtype());
288 DnsRecordParser parser = response->Parser();
289 DnsResourceRecord record;
290 for (int i = 0; i < expected_answer_count_; ++i) {
291 EXPECT_TRUE(parser.ReadRecord(&record));
293 } else {
294 EXPECT_EQ(expected_answer_count_, rv);
298 bool has_completed() const {
299 return completed_;
302 // Shorthands for commonly used commands.
304 bool Run(DnsTransactionFactory* factory) {
305 StartTransaction(factory);
306 MessageLoop::current()->RunUntilIdle();
307 return has_completed();
310 // Use when some of the responses are timeouts.
311 bool RunUntilDone(DnsTransactionFactory* factory) {
312 set_quit_in_callback();
313 StartTransaction(factory);
314 MessageLoop::current()->Run();
315 return has_completed();
318 private:
319 std::string hostname_;
320 uint16 qtype_;
321 scoped_ptr<DnsTransaction> transaction_;
322 int expected_answer_count_;
323 bool cancel_in_callback_;
324 bool quit_in_callback_;
326 bool completed_;
329 class DnsTransactionTest : public testing::Test {
330 public:
331 DnsTransactionTest() : socket_factory_(NULL) {}
333 // Generates |nameservers| for DnsConfig.
334 void ConfigureNumServers(unsigned num_servers) {
335 CHECK_LE(num_servers, 255u);
336 config_.nameservers.clear();
337 IPAddressNumber dns_ip;
339 bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
340 EXPECT_TRUE(rv);
342 for (unsigned i = 0; i < num_servers; ++i) {
343 dns_ip[3] = i;
344 config_.nameservers.push_back(IPEndPoint(dns_ip,
345 dns_protocol::kDefaultPort));
349 // Called after fully configuring |config|.
350 void ConfigureFactory() {
351 socket_factory_.reset(new TestSocketFactory());
352 session_ = new DnsSession(
353 config_,
354 DnsSocketPool::CreateNull(socket_factory_.get()),
355 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)),
356 NULL /* NetLog */);
357 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
360 void AddSocketData(scoped_ptr<DnsSocketData> data) {
361 CHECK(socket_factory_.get());
362 transaction_ids_.push_back(data->query_id());
363 socket_factory_->AddSocketDataProvider(data->GetProvider());
364 socket_data_.push_back(data.release());
367 // Add expected query for |dotted_name| and |qtype| with |id| and response
368 // taken verbatim from |data| of |data_length| bytes. The transaction id in
369 // |data| should equal |id|, unless testing mismatched response.
370 void AddQueryAndResponse(uint16 id,
371 const char* dotted_name,
372 uint16 qtype,
373 const uint8* response_data,
374 size_t response_length,
375 IoMode mode,
376 bool use_tcp) {
377 CHECK(socket_factory_.get());
378 scoped_ptr<DnsSocketData> data(
379 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
380 data->AddResponseData(response_data, response_length, mode);
381 AddSocketData(data.Pass());
384 void AddAsyncQueryAndResponse(uint16 id,
385 const char* dotted_name,
386 uint16 qtype,
387 const uint8* data,
388 size_t data_length) {
389 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC,
390 false);
393 void AddSyncQueryAndResponse(uint16 id,
394 const char* dotted_name,
395 uint16 qtype,
396 const uint8* data,
397 size_t data_length) {
398 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS,
399 false);
402 // Add expected query of |dotted_name| and |qtype| and no response.
403 void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) {
404 uint16 id = base::RandInt(0, kuint16max);
405 scoped_ptr<DnsSocketData> data(
406 new DnsSocketData(id, dotted_name, qtype, ASYNC, false));
407 AddSocketData(data.Pass());
410 // Add expected query of |dotted_name| and |qtype| and matching response with
411 // no answer and RCODE set to |rcode|. The id will be generated randomly.
412 void AddQueryAndRcode(const char* dotted_name,
413 uint16 qtype,
414 int rcode,
415 IoMode mode,
416 bool use_tcp) {
417 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
418 uint16 id = base::RandInt(0, kuint16max);
419 scoped_ptr<DnsSocketData> data(
420 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
421 data->AddRcode(rcode, mode);
422 AddSocketData(data.Pass());
425 void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
426 AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false);
429 void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
430 AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false);
433 // Checks if the sockets were connected in the order matching the indices in
434 // |servers|.
435 void CheckServerOrder(const unsigned* servers, size_t num_attempts) {
436 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size());
437 for (size_t i = 0; i < num_attempts; ++i) {
438 EXPECT_EQ(socket_factory_->remote_endpoints_[i],
439 session_->config().nameservers[servers[i]]);
443 void SetUp() OVERRIDE {
444 // By default set one server,
445 ConfigureNumServers(1);
446 // and no retransmissions,
447 config_.attempts = 1;
448 // but long enough timeout for memory tests.
449 config_.timeout = TestTimeouts::action_timeout();
450 ConfigureFactory();
453 void TearDown() OVERRIDE {
454 // Check that all socket data was at least written to.
455 for (size_t i = 0; i < socket_data_.size(); ++i) {
456 EXPECT_TRUE(socket_data_[i]->was_written()) << i;
460 protected:
461 int GetNextId(int min, int max) {
462 EXPECT_FALSE(transaction_ids_.empty());
463 int id = transaction_ids_.front();
464 transaction_ids_.pop_front();
465 EXPECT_GE(id, min);
466 EXPECT_LE(id, max);
467 return id;
470 DnsConfig config_;
472 ScopedVector<DnsSocketData> socket_data_;
474 std::deque<int> transaction_ids_;
475 scoped_ptr<TestSocketFactory> socket_factory_;
476 scoped_refptr<DnsSession> session_;
477 scoped_ptr<DnsTransactionFactory> transaction_factory_;
480 TEST_F(DnsTransactionTest, Lookup) {
481 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
482 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
484 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
485 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
488 // Concurrent lookup tests assume that DnsTransaction::Start immediately
489 // consumes a socket from ClientSocketFactory.
490 TEST_F(DnsTransactionTest, ConcurrentLookup) {
491 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
492 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
493 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
494 kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
496 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
497 helper0.StartTransaction(transaction_factory_.get());
498 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
499 helper1.StartTransaction(transaction_factory_.get());
501 MessageLoop::current()->RunUntilIdle();
503 EXPECT_TRUE(helper0.has_completed());
504 EXPECT_TRUE(helper1.has_completed());
507 TEST_F(DnsTransactionTest, CancelLookup) {
508 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
509 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
510 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
511 kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
513 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
514 helper0.StartTransaction(transaction_factory_.get());
515 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
516 helper1.StartTransaction(transaction_factory_.get());
518 helper0.Cancel();
520 MessageLoop::current()->RunUntilIdle();
522 EXPECT_FALSE(helper0.has_completed());
523 EXPECT_TRUE(helper1.has_completed());
526 TEST_F(DnsTransactionTest, DestroyFactory) {
527 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
528 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
530 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
531 helper0.StartTransaction(transaction_factory_.get());
533 // Destroying the client does not affect running requests.
534 transaction_factory_.reset(NULL);
536 MessageLoop::current()->RunUntilIdle();
538 EXPECT_TRUE(helper0.has_completed());
541 TEST_F(DnsTransactionTest, CancelFromCallback) {
542 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
543 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
545 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
546 helper0.set_cancel_in_callback();
547 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
550 TEST_F(DnsTransactionTest, MismatchedResponseSync) {
551 config_.attempts = 2;
552 config_.timeout = TestTimeouts::tiny_timeout();
553 ConfigureFactory();
555 // Attempt receives mismatched response followed by valid response.
556 scoped_ptr<DnsSocketData> data(
557 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS, false));
558 data->AddResponseData(kT1ResponseDatagram,
559 arraysize(kT1ResponseDatagram), SYNCHRONOUS);
560 data->AddResponseData(kT0ResponseDatagram,
561 arraysize(kT0ResponseDatagram), SYNCHRONOUS);
562 AddSocketData(data.Pass());
564 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
565 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
568 TEST_F(DnsTransactionTest, MismatchedResponseAsync) {
569 config_.attempts = 2;
570 config_.timeout = TestTimeouts::tiny_timeout();
571 ConfigureFactory();
573 // First attempt receives mismatched response followed by valid response.
574 // Second attempt times out.
575 scoped_ptr<DnsSocketData> data(
576 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, false));
577 data->AddResponseData(kT1ResponseDatagram,
578 arraysize(kT1ResponseDatagram), ASYNC);
579 data->AddResponseData(kT0ResponseDatagram,
580 arraysize(kT0ResponseDatagram), ASYNC);
581 AddSocketData(data.Pass());
582 AddQueryAndTimeout(kT0HostName, kT0Qtype);
584 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
585 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
588 TEST_F(DnsTransactionTest, MismatchedResponseFail) {
589 config_.timeout = TestTimeouts::tiny_timeout();
590 ConfigureFactory();
592 // Attempt receives mismatched response but times out because only one attempt
593 // is allowed.
594 AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype,
595 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
597 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
598 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
601 TEST_F(DnsTransactionTest, ServerFail) {
602 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
604 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
605 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
608 TEST_F(DnsTransactionTest, NoDomain) {
609 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
611 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
612 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
615 TEST_F(DnsTransactionTest, Timeout) {
616 config_.attempts = 3;
617 // Use short timeout to speed up the test.
618 config_.timeout = TestTimeouts::tiny_timeout();
619 ConfigureFactory();
621 AddQueryAndTimeout(kT0HostName, kT0Qtype);
622 AddQueryAndTimeout(kT0HostName, kT0Qtype);
623 AddQueryAndTimeout(kT0HostName, kT0Qtype);
625 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
626 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
627 MessageLoop::current()->AssertIdle();
630 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) {
631 // Test that we fallback on both server failure and timeout.
632 config_.attempts = 2;
633 // The next request should start from the next server.
634 config_.rotate = true;
635 ConfigureNumServers(3);
636 // Use short timeout to speed up the test.
637 config_.timeout = TestTimeouts::tiny_timeout();
638 ConfigureFactory();
640 // Responses for first request.
641 AddQueryAndTimeout(kT0HostName, kT0Qtype);
642 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
643 AddQueryAndTimeout(kT0HostName, kT0Qtype);
644 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
645 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
646 // Responses for second request.
647 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
648 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN);
650 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
651 TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED);
653 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
654 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
656 unsigned kOrder[] = {
657 0, 1, 2, 0, 1, // The first transaction.
658 1, 2, // The second transaction starts from the next server.
660 CheckServerOrder(kOrder, arraysize(kOrder));
663 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {
664 config_.ndots = 2;
665 config_.search.push_back("a");
666 config_.search.push_back("b");
667 config_.search.push_back("c");
668 config_.rotate = true;
669 ConfigureNumServers(2);
670 ConfigureFactory();
672 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
673 dns_protocol::kRcodeNXDOMAIN);
674 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
675 dns_protocol::kRcodeNXDOMAIN);
676 AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA,
677 dns_protocol::kRcodeNXDOMAIN);
678 AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA,
679 dns_protocol::kRcodeNXDOMAIN);
681 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
682 ERR_NAME_NOT_RESOLVED);
684 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
686 // Also check if suffix search causes server rotation.
687 unsigned kOrder0[] = { 0, 1, 0, 1 };
688 CheckServerOrder(kOrder0, arraysize(kOrder0));
691 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {
692 config_.ndots = 2;
693 config_.search.push_back("a");
694 config_.search.push_back("b");
695 config_.search.push_back("c");
696 ConfigureFactory();
698 // Responses for first transaction.
699 AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA,
700 dns_protocol::kRcodeNXDOMAIN);
701 AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA,
702 dns_protocol::kRcodeNXDOMAIN);
703 AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA,
704 dns_protocol::kRcodeNXDOMAIN);
705 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
706 dns_protocol::kRcodeNXDOMAIN);
707 // Responses for second transaction.
708 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
709 dns_protocol::kRcodeNXDOMAIN);
710 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
711 dns_protocol::kRcodeNXDOMAIN);
712 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
713 dns_protocol::kRcodeNXDOMAIN);
714 // Responses for third transaction.
715 AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA,
716 dns_protocol::kRcodeNXDOMAIN);
718 TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
720 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
722 // A single-label name.
723 TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
725 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
727 // A fully-qualified name.
728 TransactionHelper helper2("x.", dns_protocol::kTypeAAAA,
729 ERR_NAME_NOT_RESOLVED);
731 EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
734 TEST_F(DnsTransactionTest, EmptySuffixSearch) {
735 // Responses for first transaction.
736 AddAsyncQueryAndRcode("x", dns_protocol::kTypeA,
737 dns_protocol::kRcodeNXDOMAIN);
739 // A fully-qualified name.
740 TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
742 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
744 // A single label name is not even attempted.
745 TransactionHelper helper1("singlelabel", dns_protocol::kTypeA,
746 ERR_DNS_SEARCH_EMPTY);
748 helper1.StartTransaction(transaction_factory_.get());
749 EXPECT_TRUE(helper1.has_completed());
752 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) {
753 config_.search.push_back("a");
754 config_.search.push_back("b");
755 config_.search.push_back("c");
756 config_.append_to_multi_label_name = false;
757 ConfigureFactory();
759 // Responses for first transaction.
760 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
761 dns_protocol::kRcodeNXDOMAIN);
762 // Responses for second transaction.
763 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
764 dns_protocol::kRcodeNXDOMAIN);
765 // Responses for third transaction.
766 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
767 dns_protocol::kRcodeNXDOMAIN);
768 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
769 dns_protocol::kRcodeNXDOMAIN);
770 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
771 dns_protocol::kRcodeNXDOMAIN);
773 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
774 ERR_NAME_NOT_RESOLVED);
775 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
777 TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
778 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
780 TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
781 EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
784 const uint8 kResponseNoData[] = {
785 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
786 // Question
787 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01,
788 // Authority section, SOA record, TTL 0x3E6
789 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6,
790 // Minimal RDATA, 18 bytes
791 0x00, 0x12,
792 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00,
799 TEST_F(DnsTransactionTest, SuffixSearchStop) {
800 config_.ndots = 2;
801 config_.search.push_back("a");
802 config_.search.push_back("b");
803 config_.search.push_back("c");
804 ConfigureFactory();
806 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
807 dns_protocol::kRcodeNXDOMAIN);
808 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
809 dns_protocol::kRcodeNXDOMAIN);
810 AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA,
811 kResponseNoData, arraysize(kResponseNoData));
813 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */);
815 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
818 TEST_F(DnsTransactionTest, SyncFirstQuery) {
819 config_.search.push_back("lab.ccs.neu.edu");
820 config_.search.push_back("ccs.neu.edu");
821 ConfigureFactory();
823 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
824 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
826 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
827 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
830 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {
831 config_.search.push_back("lab.ccs.neu.edu");
832 config_.search.push_back("ccs.neu.edu");
833 ConfigureFactory();
835 AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype,
836 dns_protocol::kRcodeNXDOMAIN);
837 // "www.ccs.neu.edu"
838 AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
839 kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
841 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
842 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
845 TEST_F(DnsTransactionTest, SyncSearchQuery) {
846 config_.search.push_back("lab.ccs.neu.edu");
847 config_.search.push_back("ccs.neu.edu");
848 ConfigureFactory();
850 AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA,
851 dns_protocol::kRcodeNXDOMAIN);
852 AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
853 kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
855 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
856 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
859 TEST_F(DnsTransactionTest, ConnectFailure) {
860 socket_factory_->create_failing_sockets_ = true;
861 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
862 TransactionHelper helper0("www.chromium.org", dns_protocol::kTypeA,
863 ERR_CONNECTION_REFUSED);
864 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
867 TEST_F(DnsTransactionTest, TCPLookup) {
868 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
869 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
870 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
871 kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
872 ASYNC, true /* use_tcp */);
874 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
875 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
878 TEST_F(DnsTransactionTest, TCPFailure) {
879 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
880 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
881 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
882 ASYNC, true /* use_tcp */);
884 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
885 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
888 TEST_F(DnsTransactionTest, TCPMalformed) {
889 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
890 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
891 scoped_ptr<DnsSocketData> data(
892 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
893 // Valid response but length too short.
894 data->AddResponseWithLength(
895 make_scoped_ptr(
896 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
897 arraysize(kT0ResponseDatagram), 0)),
898 ASYNC,
899 static_cast<uint16>(kT0QuerySize - 1));
900 AddSocketData(data.Pass());
902 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_MALFORMED_RESPONSE);
903 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
906 TEST_F(DnsTransactionTest, TCPTimeout) {
907 config_.timeout = TestTimeouts::tiny_timeout();
908 ConfigureFactory();
909 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
910 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
911 AddSocketData(make_scoped_ptr(
912 new DnsSocketData(1 /* id */, kT0HostName, kT0Qtype, ASYNC, true)));
914 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
915 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
918 } // namespace
920 } // namespace net