[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "net/dns/dns_test_util.h" |
| 6 | |
| 7 | #include <string> |
| 8 | |
[email protected] | d9806a97 | 2014-02-26 18:14:57 | [diff] [blame] | 9 | #include "base/big_endian.h" |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 10 | #include "base/bind.h" |
skyostil | 4891b25b | 2015-06-11 11:43:45 | [diff] [blame^] | 11 | #include "base/location.h" |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 12 | #include "base/memory/weak_ptr.h" |
skyostil | 4891b25b | 2015-06-11 11:43:45 | [diff] [blame^] | 13 | #include "base/single_thread_task_runner.h" |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 14 | #include "base/sys_byteorder.h" |
skyostil | 4891b25b | 2015-06-11 11:43:45 | [diff] [blame^] | 15 | #include "base/thread_task_runner_handle.h" |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 16 | #include "net/base/dns_util.h" |
| 17 | #include "net/base/io_buffer.h" |
| 18 | #include "net/base/net_errors.h" |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 19 | #include "net/dns/address_sorter.h" |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 20 | #include "net/dns/dns_query.h" |
| 21 | #include "net/dns/dns_response.h" |
| 22 | #include "net/dns/dns_transaction.h" |
| 23 | #include "testing/gtest/include/gtest/gtest.h" |
| 24 | |
| 25 | namespace net { |
| 26 | namespace { |
| 27 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 28 | class MockAddressSorter : public AddressSorter { |
| 29 | public: |
dcheng | b03027d | 2014-10-21 12:00:20 | [diff] [blame] | 30 | ~MockAddressSorter() override {} |
| 31 | void Sort(const AddressList& list, |
| 32 | const CallbackType& callback) const override { |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 33 | // Do nothing. |
| 34 | callback.Run(true, list); |
| 35 | } |
| 36 | }; |
| 37 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 38 | // A DnsTransaction which uses MockDnsClientRuleList to determine the response. |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 39 | class MockTransaction : public DnsTransaction, |
| 40 | public base::SupportsWeakPtr<MockTransaction> { |
| 41 | public: |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 42 | MockTransaction(const MockDnsClientRuleList& rules, |
| 43 | const std::string& hostname, |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 44 | uint16 qtype, |
| 45 | const DnsTransactionFactory::CallbackType& callback) |
[email protected] | a210eef9 | 2013-07-19 19:06:12 | [diff] [blame] | 46 | : result_(MockDnsClientRule::FAIL), |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 47 | hostname_(hostname), |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 48 | qtype_(qtype), |
| 49 | callback_(callback), |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 50 | started_(false), |
| 51 | delayed_(false) { |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 52 | // Find the relevant rule which matches |qtype| and prefix of |hostname|. |
| 53 | for (size_t i = 0; i < rules.size(); ++i) { |
| 54 | const std::string& prefix = rules[i].prefix; |
| 55 | if ((rules[i].qtype == qtype) && |
| 56 | (hostname.size() >= prefix.size()) && |
| 57 | (hostname.compare(0, prefix.size(), prefix) == 0)) { |
| 58 | result_ = rules[i].result; |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 59 | delayed_ = rules[i].delay; |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 60 | break; |
| 61 | } |
| 62 | } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 63 | } |
| 64 | |
nick | d3f30d02 | 2015-04-23 10:18:37 | [diff] [blame] | 65 | const std::string& GetHostname() const override { return hostname_; } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 66 | |
nick | d3f30d02 | 2015-04-23 10:18:37 | [diff] [blame] | 67 | uint16 GetType() const override { return qtype_; } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 68 | |
nick | d3f30d02 | 2015-04-23 10:18:37 | [diff] [blame] | 69 | void Start() override { |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 70 | EXPECT_FALSE(started_); |
| 71 | started_ = true; |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 72 | if (delayed_) |
| 73 | return; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 74 | // Using WeakPtr to cleanly cancel when transaction is destroyed. |
skyostil | 4891b25b | 2015-06-11 11:43:45 | [diff] [blame^] | 75 | base::ThreadTaskRunnerHandle::Get()->PostTask( |
[email protected] | 2da659e | 2013-05-23 20:51:34 | [diff] [blame] | 76 | FROM_HERE, base::Bind(&MockTransaction::Finish, AsWeakPtr())); |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 77 | } |
| 78 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 79 | void FinishDelayedTransaction() { |
| 80 | EXPECT_TRUE(delayed_); |
| 81 | delayed_ = false; |
| 82 | Finish(); |
| 83 | } |
| 84 | |
| 85 | bool delayed() const { return delayed_; } |
| 86 | |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 87 | private: |
| 88 | void Finish() { |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 89 | switch (result_) { |
| 90 | case MockDnsClientRule::EMPTY: |
| 91 | case MockDnsClientRule::OK: { |
| 92 | std::string qname; |
| 93 | DNSDomainFromDot(hostname_, &qname); |
| 94 | DnsQuery query(0, qname, qtype_); |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 95 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 96 | DnsResponse response; |
| 97 | char* buffer = response.io_buffer()->data(); |
| 98 | int nbytes = query.io_buffer()->size(); |
| 99 | memcpy(buffer, query.io_buffer()->data(), nbytes); |
| 100 | dns_protocol::Header* header = |
| 101 | reinterpret_cast<dns_protocol::Header*>(buffer); |
| 102 | header->flags |= dns_protocol::kFlagResponse; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 103 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 104 | if (MockDnsClientRule::OK == result_) { |
| 105 | const uint16 kPointerToQueryName = |
| 106 | static_cast<uint16>(0xc000 | sizeof(*header)); |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 107 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 108 | const uint32 kTTL = 86400; // One day. |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 109 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 110 | // Size of RDATA which is a IPv4 or IPv6 address. |
ttuttle | 859dc7a | 2015-04-23 19:42:29 | [diff] [blame] | 111 | size_t rdata_size = qtype_ == dns_protocol::kTypeA ? kIPv4AddressSize |
| 112 | : kIPv6AddressSize; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 113 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 114 | // 12 is the sum of sizes of the compressed name reference, TYPE, |
| 115 | // CLASS, TTL and RDLENGTH. |
| 116 | size_t answer_size = 12 + rdata_size; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 117 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 118 | // Write answer with loopback IP address. |
| 119 | header->ancount = base::HostToNet16(1); |
[email protected] | d9806a97 | 2014-02-26 18:14:57 | [diff] [blame] | 120 | base::BigEndianWriter writer(buffer + nbytes, answer_size); |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 121 | writer.WriteU16(kPointerToQueryName); |
| 122 | writer.WriteU16(qtype_); |
ttuttle | 859dc7a | 2015-04-23 19:42:29 | [diff] [blame] | 123 | writer.WriteU16(dns_protocol::kClassIN); |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 124 | writer.WriteU32(kTTL); |
| 125 | writer.WriteU16(rdata_size); |
ttuttle | 859dc7a | 2015-04-23 19:42:29 | [diff] [blame] | 126 | if (qtype_ == dns_protocol::kTypeA) { |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 127 | char kIPv4Loopback[] = { 0x7f, 0, 0, 1 }; |
| 128 | writer.WriteBytes(kIPv4Loopback, sizeof(kIPv4Loopback)); |
| 129 | } else { |
| 130 | char kIPv6Loopback[] = { 0, 0, 0, 0, 0, 0, 0, 0, |
| 131 | 0, 0, 0, 0, 0, 0, 0, 1 }; |
| 132 | writer.WriteBytes(kIPv6Loopback, sizeof(kIPv6Loopback)); |
| 133 | } |
| 134 | nbytes += answer_size; |
| 135 | } |
| 136 | EXPECT_TRUE(response.InitParse(nbytes, query)); |
| 137 | callback_.Run(this, OK, &response); |
| 138 | } break; |
[email protected] | a210eef9 | 2013-07-19 19:06:12 | [diff] [blame] | 139 | case MockDnsClientRule::FAIL: |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 140 | callback_.Run(this, ERR_NAME_NOT_RESOLVED, NULL); |
| 141 | break; |
[email protected] | 4817d12 | 2012-12-13 02:21:59 | [diff] [blame] | 142 | case MockDnsClientRule::TIMEOUT: |
| 143 | callback_.Run(this, ERR_DNS_TIMED_OUT, NULL); |
| 144 | break; |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 145 | default: |
| 146 | NOTREACHED(); |
| 147 | break; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 148 | } |
| 149 | } |
| 150 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 151 | MockDnsClientRule::Result result_; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 152 | const std::string hostname_; |
| 153 | const uint16 qtype_; |
| 154 | DnsTransactionFactory::CallbackType callback_; |
| 155 | bool started_; |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 156 | bool delayed_; |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 157 | }; |
| 158 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 159 | } // namespace |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 160 | |
| 161 | // A DnsTransactionFactory which creates MockTransaction. |
| 162 | class MockTransactionFactory : public DnsTransactionFactory { |
| 163 | public: |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 164 | explicit MockTransactionFactory(const MockDnsClientRuleList& rules) |
| 165 | : rules_(rules) {} |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 166 | |
dcheng | b03027d | 2014-10-21 12:00:20 | [diff] [blame] | 167 | ~MockTransactionFactory() override {} |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 168 | |
dcheng | b03027d | 2014-10-21 12:00:20 | [diff] [blame] | 169 | scoped_ptr<DnsTransaction> CreateTransaction( |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 170 | const std::string& hostname, |
| 171 | uint16 qtype, |
| 172 | const DnsTransactionFactory::CallbackType& callback, |
mostynb | ba063d603 | 2014-10-09 11:01:13 | [diff] [blame] | 173 | const BoundNetLog&) override { |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 174 | MockTransaction* transaction = |
| 175 | new MockTransaction(rules_, hostname, qtype, callback); |
| 176 | if (transaction->delayed()) |
| 177 | delayed_transactions_.push_back(transaction->AsWeakPtr()); |
| 178 | return scoped_ptr<DnsTransaction>(transaction); |
| 179 | } |
| 180 | |
| 181 | void CompleteDelayedTransactions() { |
| 182 | DelayedTransactionList old_delayed_transactions; |
| 183 | old_delayed_transactions.swap(delayed_transactions_); |
| 184 | for (DelayedTransactionList::iterator it = old_delayed_transactions.begin(); |
| 185 | it != old_delayed_transactions.end(); ++it) { |
| 186 | if (it->get()) |
| 187 | (*it)->FinishDelayedTransaction(); |
| 188 | } |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 189 | } |
| 190 | |
| 191 | private: |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 192 | typedef std::vector<base::WeakPtr<MockTransaction> > DelayedTransactionList; |
| 193 | |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 194 | MockDnsClientRuleList rules_; |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 195 | DelayedTransactionList delayed_transactions_; |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 196 | }; |
| 197 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 198 | MockDnsClient::MockDnsClient(const DnsConfig& config, |
| 199 | const MockDnsClientRuleList& rules) |
| 200 | : config_(config), |
| 201 | factory_(new MockTransactionFactory(rules)), |
| 202 | address_sorter_(new MockAddressSorter()) { |
| 203 | } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 204 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 205 | MockDnsClient::~MockDnsClient() {} |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 206 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 207 | void MockDnsClient::SetConfig(const DnsConfig& config) { |
| 208 | config_ = config; |
| 209 | } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 210 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 211 | const DnsConfig* MockDnsClient::GetConfig() const { |
| 212 | return config_.IsValid() ? &config_ : NULL; |
| 213 | } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 214 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 215 | DnsTransactionFactory* MockDnsClient::GetTransactionFactory() { |
| 216 | return config_.IsValid() ? factory_.get() : NULL; |
| 217 | } |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 218 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 219 | AddressSorter* MockDnsClient::GetAddressSorter() { |
| 220 | return address_sorter_.get(); |
| 221 | } |
[email protected] | 0adcb2b | 2012-08-15 21:30:46 | [diff] [blame] | 222 | |
[email protected] | daae132 | 2013-09-05 18:26:50 | [diff] [blame] | 223 | void MockDnsClient::CompleteDelayedTransactions() { |
| 224 | factory_->CompleteDelayedTransactions(); |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 225 | } |
| 226 | |
[email protected] | 78eac2a | 2012-03-14 19:09:27 | [diff] [blame] | 227 | } // namespace net |