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
23namespace net {
24
25namespace {
26
27std::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.
34class 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
146class TestSocketFactory;
147
148// A variant of MockUDPClientSocket which always fails to Connect.
149class FailingUDPClientSocket : public MockUDPClientSocket {
150 public:
151  FailingUDPClientSocket(SocketDataProvider* data,
152                         net::NetLog* net_log)
153      : MockUDPClientSocket(data, net_log) {
154  }
155  virtual ~FailingUDPClientSocket() {}
156  virtual int Connect(const IPEndPoint& endpoint) OVERRIDE {
157    return ERR_CONNECTION_REFUSED;
158  }
159
160 private:
161  DISALLOW_COPY_AND_ASSIGN(FailingUDPClientSocket);
162};
163
164// A variant of MockUDPClientSocket which notifies the factory OnConnect.
165class TestUDPClientSocket : public MockUDPClientSocket {
166 public:
167  TestUDPClientSocket(TestSocketFactory* factory,
168                      SocketDataProvider* data,
169                      net::NetLog* net_log)
170      : MockUDPClientSocket(data, net_log), factory_(factory) {
171  }
172  virtual ~TestUDPClientSocket() {}
173  virtual int Connect(const IPEndPoint& endpoint) OVERRIDE;
174
175 private:
176  TestSocketFactory* factory_;
177
178  DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket);
179};
180
181// Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
182class TestSocketFactory : public MockClientSocketFactory {
183 public:
184  TestSocketFactory() : fail_next_socket_(false) {}
185  virtual ~TestSocketFactory() {}
186
187  virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket(
188      DatagramSocket::BindType bind_type,
189      const RandIntCallback& rand_int_cb,
190      net::NetLog* net_log,
191      const net::NetLog::Source& source) OVERRIDE {
192    if (fail_next_socket_) {
193      fail_next_socket_ = false;
194      return scoped_ptr<DatagramClientSocket>(
195          new FailingUDPClientSocket(&empty_data_, net_log));
196    }
197    SocketDataProvider* data_provider = mock_data().GetNext();
198    scoped_ptr<TestUDPClientSocket> socket(
199        new TestUDPClientSocket(this, data_provider, net_log));
200    data_provider->set_socket(socket.get());
201    return socket.PassAs<DatagramClientSocket>();
202  }
203
204  void OnConnect(const IPEndPoint& endpoint) {
205    remote_endpoints_.push_back(endpoint);
206  }
207
208  std::vector<IPEndPoint> remote_endpoints_;
209  bool fail_next_socket_;
210
211 private:
212  StaticSocketDataProvider empty_data_;
213
214  DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
215};
216
217int 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.
223class 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
330class DnsTransactionTest : public testing::Test {
331 public:
332  DnsTransactionTest() {}
333
334  // Generates |nameservers| for DnsConfig.
335  void ConfigureNumServers(unsigned num_servers) {
336    CHECK_LE(num_servers, 255u);
337    config_.nameservers.clear();
338    IPAddressNumber dns_ip;
339    {
340      bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
341      EXPECT_TRUE(rv);
342    }
343    for (unsigned i = 0; i < num_servers; ++i) {
344      dns_ip[3] = i;
345      config_.nameservers.push_back(IPEndPoint(dns_ip,
346                                               dns_protocol::kDefaultPort));
347    }
348  }
349
350  // Called after fully configuring |config|.
351  void ConfigureFactory() {
352    socket_factory_.reset(new TestSocketFactory());
353    session_ = new DnsSession(
354        config_,
355        DnsSocketPool::CreateNull(socket_factory_.get()),
356        base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)),
357        NULL /* NetLog */);
358    transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
359  }
360
361  void AddSocketData(scoped_ptr<DnsSocketData> data) {
362    CHECK(socket_factory_.get());
363    transaction_ids_.push_back(data->query_id());
364    socket_factory_->AddSocketDataProvider(data->GetProvider());
365    socket_data_.push_back(data.release());
366  }
367
368  // Add expected query for |dotted_name| and |qtype| with |id| and response
369  // taken verbatim from |data| of |data_length| bytes. The transaction id in
370  // |data| should equal |id|, unless testing mismatched response.
371  void AddQueryAndResponse(uint16 id,
372                           const char* dotted_name,
373                           uint16 qtype,
374                           const uint8* response_data,
375                           size_t response_length,
376                           IoMode mode,
377                           bool use_tcp) {
378    CHECK(socket_factory_.get());
379    scoped_ptr<DnsSocketData> data(
380        new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
381    data->AddResponseData(response_data, response_length, mode);
382    AddSocketData(data.Pass());
383  }
384
385  void AddAsyncQueryAndResponse(uint16 id,
386                                const char* dotted_name,
387                                uint16 qtype,
388                                const uint8* data,
389                                size_t data_length) {
390    AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC,
391                        false);
392  }
393
394  void AddSyncQueryAndResponse(uint16 id,
395                               const char* dotted_name,
396                               uint16 qtype,
397                               const uint8* data,
398                               size_t data_length) {
399    AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS,
400                        false);
401  }
402
403  // Add expected query of |dotted_name| and |qtype| and no response.
404  void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) {
405    uint16 id = base::RandInt(0, kuint16max);
406    scoped_ptr<DnsSocketData> data(
407        new DnsSocketData(id, dotted_name, qtype, ASYNC, false));
408    AddSocketData(data.Pass());
409  }
410
411  // Add expected query of |dotted_name| and |qtype| and matching response with
412  // no answer and RCODE set to |rcode|. The id will be generated randomly.
413  void AddQueryAndRcode(const char* dotted_name,
414                        uint16 qtype,
415                        int rcode,
416                        IoMode mode,
417                        bool use_tcp) {
418    CHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
419    uint16 id = base::RandInt(0, kuint16max);
420    scoped_ptr<DnsSocketData> data(
421        new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
422    data->AddRcode(rcode, mode);
423    AddSocketData(data.Pass());
424  }
425
426  void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
427    AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false);
428  }
429
430  void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
431    AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false);
432  }
433
434  // Checks if the sockets were connected in the order matching the indices in
435  // |servers|.
436  void CheckServerOrder(const unsigned* servers, size_t num_attempts) {
437    ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size());
438    for (size_t i = 0; i < num_attempts; ++i) {
439      EXPECT_EQ(socket_factory_->remote_endpoints_[i],
440                session_->config().nameservers[servers[i]]);
441    }
442  }
443
444  virtual void SetUp() OVERRIDE {
445    // By default set one server,
446    ConfigureNumServers(1);
447    // and no retransmissions,
448    config_.attempts = 1;
449    // but long enough timeout for memory tests.
450    config_.timeout = TestTimeouts::action_timeout();
451    ConfigureFactory();
452  }
453
454  virtual void TearDown() OVERRIDE {
455    // Check that all socket data was at least written to.
456    for (size_t i = 0; i < socket_data_.size(); ++i) {
457      EXPECT_TRUE(socket_data_[i]->was_written()) << i;
458    }
459  }
460
461 protected:
462  int GetNextId(int min, int max) {
463    EXPECT_FALSE(transaction_ids_.empty());
464    int id = transaction_ids_.front();
465    transaction_ids_.pop_front();
466    EXPECT_GE(id, min);
467    EXPECT_LE(id, max);
468    return id;
469  }
470
471  DnsConfig config_;
472
473  ScopedVector<DnsSocketData> socket_data_;
474
475  std::deque<int> transaction_ids_;
476  scoped_ptr<TestSocketFactory> socket_factory_;
477  scoped_refptr<DnsSession> session_;
478  scoped_ptr<DnsTransactionFactory> transaction_factory_;
479};
480
481TEST_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.
491TEST_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
508TEST_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
527TEST_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
542TEST_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
551TEST_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
569TEST_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
589TEST_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
602TEST_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
609TEST_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
616TEST_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
631TEST_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
665TEST_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
693TEST_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
736TEST_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
754TEST_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
786const 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
801TEST_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
820TEST_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
832TEST_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
847TEST_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
861TEST_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
869TEST_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
883TEST_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
894TEST_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
904TEST_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
925TEST_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
937TEST_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
957TEST_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
977TEST_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
989TEST_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
1001TEST_F(DnsTransactionTest, InvalidQuery) {
1002  config_.timeout = TestTimeouts::tiny_timeout();
1003  ConfigureFactory();
1004
1005  TransactionHelper helper0(".", dns_protocol::kTypeA, ERR_INVALID_ARGUMENT);
1006  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
1007}
1008
1009}  // namespace
1010
1011}  // namespace net
1012