- add sources.
[platform/framework/web/crosswalk.git] / src / net / dns / dns_transaction_unittest.cc
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/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"
23
24 namespace net {
25
26 namespace {
27
28 std::string DomainFromDot(const base::StringPiece& dotted) {
29   std::string out;
30   EXPECT_TRUE(DNSDomainFromDot(dotted, &out));
31   return out;
32 }
33
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());
52     }
53     writes_.push_back(MockWrite(mode,
54                                 query_->io_buffer()->data(),
55                                 query_->io_buffer()->size()));
56   }
57   ~DnsSocketData() {}
58
59   // All responses must be added before GetProvider.
60
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());
72     }
73     reads_.push_back(MockRead(mode,
74                               response->io_buffer()->data(),
75                               response->io_buffer()->size()));
76     responses_.push_back(response.release());
77   }
78
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);
83   }
84
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);
90   }
91
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);
102   }
103
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));
116     }
117     return provider_.get();
118   }
119
120   uint16 query_id() const {
121     return query_->id();
122   }
123
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;
128   }
129
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_;
138
139   DISALLOW_COPY_AND_ASSIGN(DnsSocketData);
140 };
141
142 class TestSocketFactory;
143
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) {
150   }
151   virtual ~FailingUDPClientSocket() {}
152   virtual int Connect(const IPEndPoint& endpoint) OVERRIDE {
153     return ERR_CONNECTION_REFUSED;
154   }
155
156  private:
157   DISALLOW_COPY_AND_ASSIGN(FailingUDPClientSocket);
158 };
159
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) {
167   }
168   virtual ~TestUDPClientSocket() {}
169   virtual int Connect(const IPEndPoint& endpoint) OVERRIDE;
170
171  private:
172   TestSocketFactory* factory_;
173
174   DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket);
175 };
176
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() {}
182
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));
192     }
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>();
198   }
199
200   void OnConnect(const IPEndPoint& endpoint) {
201     remote_endpoints_.push_back(endpoint);
202   }
203
204   std::vector<IPEndPoint> remote_endpoints_;
205   bool fail_next_socket_;
206
207  private:
208   StaticSocketDataProvider empty_data_;
209
210   DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
211 };
212
213 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
214   factory_->OnConnect(endpoint);
215   return MockUDPClientSocket::Connect(endpoint);
216 }
217
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) {
231   }
232
233   // Mark that the transaction shall be destroyed immediately upon callback.
234   void set_cancel_in_callback() {
235     cancel_in_callback_ = true;
236   }
237
238   // Mark to call MessageLoop::Quit() upon callback.
239   void set_quit_in_callback() {
240     quit_in_callback_ = true;
241   }
242
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();
254   }
255
256   void Cancel() {
257     ASSERT_TRUE(transaction_.get() != NULL);
258     transaction_.reset(NULL);
259   }
260
261   void OnTransactionComplete(DnsTransaction* t,
262                              int rv,
263                              const DnsResponse* response) {
264     EXPECT_FALSE(completed_);
265     EXPECT_EQ(transaction_.get(), t);
266
267     completed_ = true;
268
269     if (cancel_in_callback_) {
270       Cancel();
271       return;
272     }
273
274     // Tell MessageLoop to quit now, in case any ASSERT_* fails.
275     if (quit_in_callback_)
276       base::MessageLoop::current()->Quit();
277
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());
284
285       DnsRecordParser parser = response->Parser();
286       DnsResourceRecord record;
287       for (int i = 0; i < expected_answer_count_; ++i) {
288         EXPECT_TRUE(parser.ReadRecord(&record));
289       }
290     } else {
291       EXPECT_EQ(expected_answer_count_, rv);
292     }
293   }
294
295   bool has_completed() const {
296     return completed_;
297   }
298
299   // Shorthands for commonly used commands.
300
301   bool Run(DnsTransactionFactory* factory) {
302     StartTransaction(factory);
303     base::MessageLoop::current()->RunUntilIdle();
304     return has_completed();
305   }
306
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();
313   }
314
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_;
322
323   bool completed_;
324 };
325
326 class DnsTransactionTest : public testing::Test {
327  public:
328   DnsTransactionTest() {}
329
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;
335     {
336       bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
337       EXPECT_TRUE(rv);
338     }
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));
343     }
344   }
345
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());
355   }
356
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());
362   }
363
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());
379   }
380
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);
388   }
389
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);
397   }
398
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());
405   }
406
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());
420   }
421
422   void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
423     AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false);
424   }
425
426   void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
427     AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false);
428   }
429
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]]);
437     }
438   }
439
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();
448   }
449
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;
454     }
455   }
456
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;
465   }
466
467   DnsConfig config_;
468
469   ScopedVector<DnsSocketData> socket_data_;
470
471   std::deque<int> transaction_ids_;
472   scoped_ptr<TestSocketFactory> socket_factory_;
473   scoped_refptr<DnsSession> session_;
474   scoped_ptr<DnsTransactionFactory> transaction_factory_;
475 };
476
477 TEST_F(DnsTransactionTest, Lookup) {
478   AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
479                            kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
480
481   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
482   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
483 }
484
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));
492
493   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
494   helper0.StartTransaction(transaction_factory_.get());
495   TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
496   helper1.StartTransaction(transaction_factory_.get());
497
498   base::MessageLoop::current()->RunUntilIdle();
499
500   EXPECT_TRUE(helper0.has_completed());
501   EXPECT_TRUE(helper1.has_completed());
502 }
503
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));
509
510   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
511   helper0.StartTransaction(transaction_factory_.get());
512   TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
513   helper1.StartTransaction(transaction_factory_.get());
514
515   helper0.Cancel();
516
517   base::MessageLoop::current()->RunUntilIdle();
518
519   EXPECT_FALSE(helper0.has_completed());
520   EXPECT_TRUE(helper1.has_completed());
521 }
522
523 TEST_F(DnsTransactionTest, DestroyFactory) {
524   AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
525                            kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
526
527   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
528   helper0.StartTransaction(transaction_factory_.get());
529
530   // Destroying the client does not affect running requests.
531   transaction_factory_.reset(NULL);
532
533   base::MessageLoop::current()->RunUntilIdle();
534
535   EXPECT_TRUE(helper0.has_completed());
536 }
537
538 TEST_F(DnsTransactionTest, CancelFromCallback) {
539   AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
540                            kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
541
542   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
543   helper0.set_cancel_in_callback();
544   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
545 }
546
547 TEST_F(DnsTransactionTest, MismatchedResponseSync) {
548   config_.attempts = 2;
549   config_.timeout = TestTimeouts::tiny_timeout();
550   ConfigureFactory();
551
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());
560
561   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
562   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
563 }
564
565 TEST_F(DnsTransactionTest, MismatchedResponseAsync) {
566   config_.attempts = 2;
567   config_.timeout = TestTimeouts::tiny_timeout();
568   ConfigureFactory();
569
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);
580
581   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
582   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
583 }
584
585 TEST_F(DnsTransactionTest, MismatchedResponseFail) {
586   config_.timeout = TestTimeouts::tiny_timeout();
587   ConfigureFactory();
588
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));
593
594   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
595   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
596 }
597
598 TEST_F(DnsTransactionTest, ServerFail) {
599   AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
600
601   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
602   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
603 }
604
605 TEST_F(DnsTransactionTest, NoDomain) {
606   AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
607
608   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
609   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
610 }
611
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();
617
618   AddQueryAndTimeout(kT0HostName, kT0Qtype);
619   AddQueryAndTimeout(kT0HostName, kT0Qtype);
620   AddQueryAndTimeout(kT0HostName, kT0Qtype);
621
622   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
623   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
624   EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
625 }
626
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();
636
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);
647
648   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
649   TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED);
650
651   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
652   EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
653
654   unsigned kOrder[] = {
655       0, 1, 2, 0, 1,    // The first transaction.
656       1, 2, 0,          // The second transaction starts from the next server.
657   };
658   CheckServerOrder(kOrder, arraysize(kOrder));
659 }
660
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();
669
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);
678
679   TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
680                             ERR_NAME_NOT_RESOLVED);
681
682   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
683
684   // Also check if suffix search causes server rotation.
685   unsigned kOrder0[] = { 0, 1, 0, 1 };
686   CheckServerOrder(kOrder0, arraysize(kOrder0));
687 }
688
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();
695
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);
715
716   TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
717
718   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
719
720   // A single-label name.
721   TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
722
723   EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
724
725   // A fully-qualified name.
726   TransactionHelper helper2("x.", dns_protocol::kTypeAAAA,
727                             ERR_NAME_NOT_RESOLVED);
728
729   EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
730 }
731
732 TEST_F(DnsTransactionTest, EmptySuffixSearch) {
733   // Responses for first transaction.
734   AddAsyncQueryAndRcode("x", dns_protocol::kTypeA,
735                         dns_protocol::kRcodeNXDOMAIN);
736
737   // A fully-qualified name.
738   TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
739
740   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
741
742   // A single label name is not even attempted.
743   TransactionHelper helper1("singlelabel", dns_protocol::kTypeA,
744                             ERR_DNS_SEARCH_EMPTY);
745
746   helper1.Run(transaction_factory_.get());
747   EXPECT_TRUE(helper1.has_completed());
748 }
749
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();
756
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);
770
771   TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
772                             ERR_NAME_NOT_RESOLVED);
773   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
774
775   TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
776   EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
777
778   TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
779   EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
780 }
781
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,
795 };
796
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();
803
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));
810
811   TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */);
812
813   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
814 }
815
816 TEST_F(DnsTransactionTest, SyncFirstQuery) {
817   config_.search.push_back("lab.ccs.neu.edu");
818   config_.search.push_back("ccs.neu.edu");
819   ConfigureFactory();
820
821   AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
822                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
823
824   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
825   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
826 }
827
828 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {
829   config_.search.push_back("lab.ccs.neu.edu");
830   config_.search.push_back("ccs.neu.edu");
831   ConfigureFactory();
832
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));
838
839   TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
840   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
841 }
842
843 TEST_F(DnsTransactionTest, SyncSearchQuery) {
844   config_.search.push_back("lab.ccs.neu.edu");
845   config_.search.push_back("ccs.neu.edu");
846   ConfigureFactory();
847
848   AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA,
849                         dns_protocol::kRcodeNXDOMAIN);
850   AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
851                           kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
852
853   TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
854   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
855 }
856
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()));
863 }
864
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()));
877 }
878
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 */);
885
886   TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
887   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
888 }
889
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 */);
895
896   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
897   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
898 }
899
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());
913
914   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_MALFORMED_RESPONSE);
915   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
916 }
917
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)));
925
926   TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
927   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
928 }
929
930 TEST_F(DnsTransactionTest, InvalidQuery) {
931   config_.timeout = TestTimeouts::tiny_timeout();
932   ConfigureFactory();
933
934   TransactionHelper helper0(".", dns_protocol::kTypeA, ERR_INVALID_ARGUMENT);
935   EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
936 }
937
938 }  // namespace
939
940 }  // namespace net