Home | History | Annotate | Download | only in dns
      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   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.
    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   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.
    182 class 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 
    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   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 
    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
   1012