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