15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_transaction.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/dns_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_protocol.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_query.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_response.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_session.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_test_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_test_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DomainFromDot(const base::StringPiece& dotted) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string out;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(DNSDomainFromDot(dotted, &out));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return out;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A SocketDataProvider builder.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DnsSocketData {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ctor takes parameters for the DnsQuery.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DnsSocketData(uint16 id,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                const char* dotted_name,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                uint16 qtype,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                IoMode mode,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                bool use_tcp)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : query_(new DnsQuery(id, DomainFromDot(dotted_name), qtype)),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        use_tcp_(use_tcp) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (use_tcp_) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<uint16> length(new uint16);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *length = base::HostToNet16(query_->io_buffer()->size());
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      writes_.push_back(MockWrite(mode,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  reinterpret_cast<const char*>(length.get()),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  sizeof(uint16)));
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      lengths_.push_back(length.release());
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    writes_.push_back(MockWrite(mode,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                query_->io_buffer()->data(),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                query_->io_buffer()->size()));
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DnsSocketData() {}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All responses must be added before GetProvider.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds pre-built DnsResponse. |tcp_length| will be used in TCP mode only.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddResponseWithLength(scoped_ptr<DnsResponse> response, IoMode mode,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             uint16 tcp_length) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!provider_.get());
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (use_tcp_) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<uint16> length(new uint16);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *length = base::HostToNet16(tcp_length);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reads_.push_back(MockRead(mode,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                reinterpret_cast<const char*>(length.get()),
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                sizeof(uint16)));
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      lengths_.push_back(length.release());
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_.push_back(MockRead(mode,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              response->io_buffer()->data(),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              response->io_buffer()->size()));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    responses_.push_back(response.release());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds pre-built DnsResponse.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddResponse(scoped_ptr<DnsResponse> response, IoMode mode) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint16 tcp_length = response->io_buffer()->size();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddResponseWithLength(response.Pass(), mode, tcp_length);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds pre-built response from |data| buffer.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddResponseData(const uint8* data, size_t length, IoMode mode) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!provider_.get());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddResponse(make_scoped_ptr(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new DnsResponse(reinterpret_cast<const char*>(data), length, 0)), mode);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add no-answer (RCODE only) response matching the query.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddRcode(int rcode, IoMode mode) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DnsResponse> response(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new DnsResponse(query_->io_buffer()->data(),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        query_->io_buffer()->size(),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        0));
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dns_protocol::Header* header =
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddResponse(response.Pass(), mode);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Add error response.
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void AddReadError(int error, IoMode mode) {
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    reads_.push_back(MockRead(mode, error));
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build, if needed, and return the SocketDataProvider. No new responses
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be added afterwards.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SocketDataProvider* GetProvider() {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (provider_.get())
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return provider_.get();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Terminate the reads with ERR_IO_PENDING to prevent overrun and default to
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // timeout.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    provider_.reset(new DelayedSocketData(1, &reads_[0], reads_.size(),
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          &writes_[0], writes_.size()));
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (use_tcp_) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      provider_->set_connect_data(MockConnect(reads_[0].mode, OK));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return provider_.get();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 query_id() const {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return query_->id();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the expected query was written to the socket.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_written() const {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(provider_.get());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return provider_->write_index() > 0;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DnsQuery> query_;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool use_tcp_;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<uint16> lengths_;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<DnsResponse> responses_;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<MockWrite> writes_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<MockRead> reads_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DelayedSocketData> provider_;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DnsSocketData);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSocketFactory;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A variant of MockUDPClientSocket which always fails to Connect.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FailingUDPClientSocket : public MockUDPClientSocket {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FailingUDPClientSocket(SocketDataProvider* data,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         net::NetLog* net_log)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : MockUDPClientSocket(data, net_log) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~FailingUDPClientSocket() {}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int Connect(const IPEndPoint& endpoint) OVERRIDE {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CONNECTION_REFUSED;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FailingUDPClientSocket);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A variant of MockUDPClientSocket which notifies the factory OnConnect.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestUDPClientSocket : public MockUDPClientSocket {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestUDPClientSocket(TestSocketFactory* factory,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SocketDataProvider* data,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      net::NetLog* net_log)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : MockUDPClientSocket(data, net_log), factory_(factory) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestUDPClientSocket() {}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int Connect(const IPEndPoint& endpoint) OVERRIDE;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSocketFactory* factory_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSocketFactory : public MockClientSocketFactory {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestSocketFactory() : fail_next_socket_(false) {}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSocketFactory() {}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DatagramSocket::BindType bind_type,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RandIntCallback& rand_int_cb,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog* net_log,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::NetLog::Source& source) OVERRIDE {
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (fail_next_socket_) {
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fail_next_socket_ = false;
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return scoped_ptr<DatagramClientSocket>(
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          new FailingUDPClientSocket(&empty_data_, net_log));
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SocketDataProvider* data_provider = mock_data().GetNext();
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<TestUDPClientSocket> socket(
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        new TestUDPClientSocket(this, data_provider, net_log));
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    data_provider->set_socket(socket.get());
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return socket.PassAs<DatagramClientSocket>();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnConnect(const IPEndPoint& endpoint) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remote_endpoints_.push_back(endpoint);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<IPEndPoint> remote_endpoints_;
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool fail_next_socket_;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider empty_data_;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  factory_->OnConnect(endpoint);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MockUDPClientSocket::Connect(endpoint);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class that holds a DnsTransaction and handles OnTransactionComplete.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TransactionHelper {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |expected_answer_count| < 0 then it is the expected net error.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper(const char* hostname,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    uint16 qtype,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int expected_answer_count)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : hostname_(hostname),
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        qtype_(qtype),
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_answer_count_(expected_answer_count),
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cancel_in_callback_(false),
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        quit_in_callback_(false),
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        completed_(false) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark that the transaction shall be destroyed immediately upon callback.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_cancel_in_callback() {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cancel_in_callback_ = true;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark to call MessageLoop::Quit() upon callback.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_quit_in_callback() {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_callback_ = true;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTransaction(DnsTransactionFactory* factory) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(NULL, transaction_.get());
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_ = factory->CreateTransaction(
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hostname_,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        qtype_,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TransactionHelper::OnTransactionComplete,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)),
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BoundNetLog());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(hostname_, transaction_->GetHostname());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(qtype_, transaction_->GetType());
257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    transaction_->Start();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(transaction_.get() != NULL);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_.reset(NULL);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnTransactionComplete(DnsTransaction* t,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int rv,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const DnsResponse* response) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(completed_);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(transaction_.get(), t);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    completed_ = true;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cancel_in_callback_) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Cancel();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell MessageLoop to quit now, in case any ASSERT_* fails.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (quit_in_callback_)
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_answer_count_ >= 0) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(OK, rv);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(response != NULL);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(static_cast<unsigned>(expected_answer_count_),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                response->answer_count());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(qtype_, response->qtype());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DnsRecordParser parser = response->Parser();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DnsResourceRecord record;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < expected_answer_count_; ++i) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(parser.ReadRecord(&record));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_answer_count_, rv);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_completed() const {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return completed_;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shorthands for commonly used commands.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Run(DnsTransactionFactory* factory) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartTransaction(factory);
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return has_completed();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use when some of the responses are timeouts.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool RunUntilDone(DnsTransactionFactory* factory) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_quit_in_callback();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartTransaction(factory);
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->Run();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return has_completed();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string hostname_;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 qtype_;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DnsTransaction> transaction_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int expected_answer_count_;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool cancel_in_callback_;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_in_callback_;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool completed_;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DnsTransactionTest : public testing::Test {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DnsTransactionTest() {}
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generates |nameservers| for DnsConfig.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConfigureNumServers(unsigned num_servers) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_LE(num_servers, 255u);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_.nameservers.clear();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressNumber dns_ip;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(rv);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned i = 0; i < num_servers; ++i) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dns_ip[3] = i;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_.nameservers.push_back(IPEndPoint(dns_ip,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               dns_protocol::kDefaultPort));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called after fully configuring |config|.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConfigureFactory() {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_factory_.reset(new TestSocketFactory());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_ = new DnsSession(
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DnsSocketPool::CreateNull(socket_factory_.get()),
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)),
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL /* NetLog */);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddSocketData(scoped_ptr<DnsSocketData> data) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(socket_factory_.get());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_ids_.push_back(data->query_id());
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_factory_->AddSocketDataProvider(data->GetProvider());
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_data_.push_back(data.release());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add expected query for |dotted_name| and |qtype| with |id| and response
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // taken verbatim from |data| of |data_length| bytes. The transaction id in
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |data| should equal |id|, unless testing mismatched response.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddQueryAndResponse(uint16 id,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const char* dotted_name,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint16 qtype,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const uint8* response_data,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           size_t response_length,
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           IoMode mode,
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bool use_tcp) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(socket_factory_.get());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DnsSocketData> data(
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->AddResponseData(response_data, response_length, mode);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddSocketData(data.Pass());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddAsyncQueryAndResponse(uint16 id,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char* dotted_name,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                uint16 qtype,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const uint8* data,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                size_t data_length) {
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC,
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        false);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddSyncQueryAndResponse(uint16 id,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const char* dotted_name,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               uint16 qtype,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const uint8* data,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               size_t data_length) {
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS,
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        false);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add expected query of |dotted_name| and |qtype| and no response.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 id = base::RandInt(0, kuint16max);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DnsSocketData> data(
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new DnsSocketData(id, dotted_name, qtype, ASYNC, false));
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddSocketData(data.Pass());
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add expected query of |dotted_name| and |qtype| and matching response with
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no answer and RCODE set to |rcode|. The id will be generated randomly.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddQueryAndRcode(const char* dotted_name,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        uint16 qtype,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int rcode,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        IoMode mode,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        bool use_tcp) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 id = base::RandInt(0, kuint16max);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DnsSocketData> data(
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->AddRcode(rcode, mode);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddSocketData(data.Pass());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks if the sockets were connected in the order matching the indices in
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |servers|.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckServerOrder(const unsigned* servers, size_t num_attempts) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < num_attempts; ++i) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(socket_factory_->remote_endpoints_[i],
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                session_->config().nameservers[servers[i]]);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // By default set one server,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfigureNumServers(1);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and no retransmissions,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_.attempts = 1;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but long enough timeout for memory tests.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_.timeout = TestTimeouts::action_timeout();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfigureFactory();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that all socket data was at least written to.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < socket_data_.size(); ++i) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(socket_data_[i]->was_written()) << i;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetNextId(int min, int max) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(transaction_ids_.empty());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id = transaction_ids_.front();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_ids_.pop_front();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GE(id, min);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LE(id, max);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DnsConfig config_;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<DnsSocketData> socket_data_;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::deque<int> transaction_ids_;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestSocketFactory> socket_factory_;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<DnsSession> session_;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DnsTransactionFactory> transaction_factory_;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, Lookup) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Concurrent lookup tests assume that DnsTransaction::Start immediately
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// consumes a socket from ClientSocketFactory.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, ConcurrentLookup) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper0.StartTransaction(transaction_factory_.get());
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper1.StartTransaction(transaction_factory_.get());
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.has_completed());
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper1.has_completed());
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, CancelLookup) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper0.StartTransaction(transaction_factory_.get());
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper1.StartTransaction(transaction_factory_.get());
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper0.Cancel();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(helper0.has_completed());
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper1.has_completed());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, DestroyFactory) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper0.StartTransaction(transaction_factory_.get());
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroying the client does not affect running requests.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction_factory_.reset(NULL);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.has_completed());
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, CancelFromCallback) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper0.set_cancel_in_callback();
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, MismatchedResponseSync) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.attempts = 2;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempt receives mismatched response followed by valid response.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DnsSocketData> data(
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS, false));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->AddResponseData(kT1ResponseDatagram,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        arraysize(kT1ResponseDatagram), SYNCHRONOUS);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->AddResponseData(kT0ResponseDatagram,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        arraysize(kT0ResponseDatagram), SYNCHRONOUS);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSocketData(data.Pass());
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, MismatchedResponseAsync) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.attempts = 2;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First attempt receives mismatched response followed by valid response.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Second attempt times out.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DnsSocketData> data(
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, false));
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->AddResponseData(kT1ResponseDatagram,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        arraysize(kT1ResponseDatagram), ASYNC);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->AddResponseData(kT0ResponseDatagram,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        arraysize(kT0ResponseDatagram), ASYNC);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSocketData(data.Pass());
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddQueryAndTimeout(kT0HostName, kT0Qtype);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, MismatchedResponseFail) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempt receives mismatched response but times out because only one attempt
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is allowed.
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype,
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, ServerFail) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, NoDomain) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, Timeout) {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.attempts = 3;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use short timeout to speed up the test.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddQueryAndTimeout(kT0HostName, kT0Qtype);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddQueryAndTimeout(kT0HostName, kT0Qtype);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddQueryAndTimeout(kT0HostName, kT0Qtype);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, ServerFallbackAndRotate) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we fallback on both server failure and timeout.
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.attempts = 2;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The next request should start from the next server.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.rotate = true;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureNumServers(3);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use short timeout to speed up the test.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for first request.
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddQueryAndTimeout(kT0HostName, kT0Qtype);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddQueryAndTimeout(kT0HostName, kT0Qtype);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for second request.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned kOrder[] = {
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, 1, 2, 0, 1,    // The first transaction.
660b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      1, 2, 0,          // The second transaction starts from the next server.
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckServerOrder(kOrder, arraysize(kOrder));
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.ndots = 2;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("a");
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("b");
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("c");
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.rotate = true;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureNumServers(2);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ERR_NAME_NOT_RESOLVED);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Also check if suffix search causes server rotation.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned kOrder0[] = { 0, 1, 0, 1 };
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckServerOrder(kOrder0, arraysize(kOrder0));
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.ndots = 2;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("a");
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("b");
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("c");
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for first transaction.
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA,
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA,
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA,
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for second transaction.
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for third transaction.
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A single-label name.
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A fully-qualified name.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper2("x.", dns_protocol::kTypeAAAA,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ERR_NAME_NOT_RESOLVED);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, EmptySuffixSearch) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for first transaction.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x", dns_protocol::kTypeA,
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A fully-qualified name.
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A single label name is not even attempted.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper1("singlelabel", dns_protocol::kTypeA,
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ERR_DNS_SEARCH_EMPTY);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  helper1.Run(transaction_factory_.get());
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper1.has_completed());
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("a");
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("b");
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("c");
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.append_to_multi_label_name = false;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for first transaction.
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for second transaction.
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responses for third transaction.
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ERR_NAME_NOT_RESOLVED);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 kResponseNoData[] = {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Question
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x01,  'x', 0x01,  'y', 0x01,  'z', 0x01,  'b', 0x00, 0x00, 0x01, 0x00, 0x01,
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Authority section, SOA record, TTL 0x3E6
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x01,  'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Minimal RDATA, 18 bytes
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x12,
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x00,
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x00, 0x00, 0x00,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x00, 0x00, 0x00,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x00, 0x00, 0x00,
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x00, 0x00, 0x00,
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, SuffixSearchStop) {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.ndots = 2;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("a");
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("b");
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("c");
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA,
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kResponseNoData, arraysize(kResponseNoData));
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */);
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, SyncFirstQuery) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("lab.ccs.neu.edu");
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("ccs.neu.edu");
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("lab.ccs.neu.edu");
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("ccs.neu.edu");
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype,
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       dns_protocol::kRcodeNXDOMAIN);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "www.ccs.neu.edu"
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, SyncSearchQuery) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("lab.ccs.neu.edu");
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.search.push_back("ccs.neu.edu");
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureFactory();
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA,
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dns_protocol::kRcodeNXDOMAIN);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DnsTransactionTest, ConnectFailure) {
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_factory_->fail_next_socket_ = true;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction_ids_.push_back(0);  // Needed to make a DnsUDPAttempt.
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelper helper0("www.chromium.org", dns_protocol::kTypeA,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ERR_CONNECTION_REFUSED);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DnsTransactionTest, ConnectFailureFollowedBySuccess) {
870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Retry after server failure.
871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  config_.attempts = 2;
872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ConfigureFactory();
873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // First server connection attempt fails.
874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction_ids_.push_back(0);  // Needed to make a DnsUDPAttempt.
875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_factory_->fail_next_socket_ = true;
876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Second DNS query succeeds.
877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
881868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPLookup) {
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      ASYNC, true /* use_tcp */);
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPFailure) {
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   ASYNC, true /* use_tcp */);
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPMalformed) {
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<DnsSocketData> data(
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Valid response but length too short.
9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // This must be truncated in the question section. The DnsResponse doesn't
9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // examine the answer section until asked to parse it, so truncating it in
9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // the answer section would result in the DnsTransaction itself succeeding.
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data->AddResponseWithLength(
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      make_scoped_ptr(
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          arraysize(kT0ResponseDatagram), 0)),
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ASYNC,
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<uint16>(kT0QuerySize - 1));
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddSocketData(data.Pass());
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_MALFORMED_RESPONSE);
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPTimeout) {
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfigureFactory();
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddSocketData(make_scoped_ptr(
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DnsSocketData(1 /* id */, kT0HostName, kT0Qtype, ASYNC, true)));
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPReadReturnsZeroAsync) {
9385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
9395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
9405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<DnsSocketData> data(
9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
9425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Return all but the last byte of the response.
9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data->AddResponseWithLength(
9445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      make_scoped_ptr(
9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          arraysize(kT0ResponseDatagram) - 1, 0)),
9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ASYNC,
9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<uint16>(arraysize(kT0ResponseDatagram)));
9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Then return a 0-length read.
9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data->AddReadError(0, ASYNC);
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddSocketData(data.Pass());
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPReadReturnsZeroSynchronous) {
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<DnsSocketData> data(
9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Return all but the last byte of the response.
9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data->AddResponseWithLength(
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      make_scoped_ptr(
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          arraysize(kT0ResponseDatagram) - 1, 0)),
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SYNCHRONOUS,
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<uint16>(arraysize(kT0ResponseDatagram)));
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Then return a 0-length read.
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data->AddReadError(0, SYNCHRONOUS);
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddSocketData(data.Pass());
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPConnectionClosedAsync) {
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<DnsSocketData> data(
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data->AddReadError(ERR_CONNECTION_CLOSED, ASYNC);
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddSocketData(data.Pass());
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(DnsTransactionTest, TCPConnectionClosedSynchronous) {
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<DnsSocketData> data(
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  data->AddReadError(ERR_CONNECTION_CLOSED, SYNCHRONOUS);
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AddSocketData(data.Pass());
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
100190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(DnsTransactionTest, InvalidQuery) {
100290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  config_.timeout = TestTimeouts::tiny_timeout();
100390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ConfigureFactory();
100490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
100590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TransactionHelper helper0(".", dns_protocol::kTypeA, ERR_INVALID_ARGUMENT);
100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
100890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1012