| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/dns/dns_transaction.h" | 5 #include "net/dns/dns_transaction.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/memory/scoped_vector.h" | 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 namespace net { | 24 namespace net { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 std::string DomainFromDot(const base::StringPiece& dotted) { | 28 std::string DomainFromDot(const base::StringPiece& dotted) { |
| 29 std::string out; | 29 std::string out; |
| 30 EXPECT_TRUE(DNSDomainFromDot(dotted, &out)); | 30 EXPECT_TRUE(DNSDomainFromDot(dotted, &out)); |
| 31 return out; | 31 return out; |
| 32 } | 32 } |
| 33 | 33 |
| 34 // A SocketDataProvider builder for MockUDPClientSocket. Each socket used by a |
| 35 // DnsTransaction expects only one write and zero or more reads. |
| 36 class DnsSocketData { |
| 37 public: |
| 38 // The ctor takes parameters for the DnsQuery. |
| 39 DnsSocketData(uint16 id, const char* dotted_name, uint16 qtype, IoMode mode) |
| 40 : query_(new DnsQuery(id, DomainFromDot(dotted_name), qtype)), |
| 41 write_(mode, query_->io_buffer()->data(), query_->io_buffer()->size()) { |
| 42 } |
| 43 ~DnsSocketData() {} |
| 44 |
| 45 // All responses must be added before GetProvider. |
| 46 |
| 47 // Add pre-built DnsResponse. |
| 48 void AddResponse(scoped_ptr<DnsResponse> response, IoMode mode) { |
| 49 CHECK(!provider_.get()); |
| 50 reads_.push_back(MockRead(mode, |
| 51 response->io_buffer()->data(), |
| 52 response->io_buffer()->size())); |
| 53 responses_.push_back(response.release()); |
| 54 } |
| 55 |
| 56 // Adds pre-built response from |data| buffer. |
| 57 void AddResponseData(const uint8* data, size_t length, IoMode mode) { |
| 58 CHECK(!provider_.get()); |
| 59 AddResponse(make_scoped_ptr( |
| 60 new DnsResponse(reinterpret_cast<const char*>(data), length, 0)), mode); |
| 61 } |
| 62 |
| 63 // Add no-answer (RCODE only) response matching the query. |
| 64 void AddRcode(int rcode, IoMode mode) { |
| 65 scoped_ptr<DnsResponse> response( |
| 66 new DnsResponse(query_->io_buffer()->data(), |
| 67 query_->io_buffer()->size(), |
| 68 0)); |
| 69 dns_protocol::Header* header = |
| 70 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data()); |
| 71 header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode); |
| 72 AddResponse(response.Pass(), mode); |
| 73 } |
| 74 |
| 75 // Build, if needed, and return the SocketDataProvider. No new responses |
| 76 // should be added afterwards. |
| 77 SocketDataProvider* GetProvider() { |
| 78 if (provider_.get()) |
| 79 return provider_.get(); |
| 80 if (reads_.empty()) { |
| 81 // Timeout. |
| 82 provider_.reset(new DelayedSocketData(2, NULL, 0, &write_, 1)); |
| 83 } else { |
| 84 // Terminate the reads with ERR_IO_PENDING to prevent overrun. |
| 85 reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING)); |
| 86 provider_.reset(new DelayedSocketData(1, &reads_[0], reads_.size(), |
| 87 &write_, 1)); |
| 88 } |
| 89 return provider_.get(); |
| 90 } |
| 91 |
| 92 uint16 query_id() const { |
| 93 return query_->id(); |
| 94 } |
| 95 |
| 96 // Returns true if the expected query was written to the socket. |
| 97 bool was_written() const { |
| 98 CHECK(provider_.get()); |
| 99 return provider_->write_index() > 0; |
| 100 } |
| 101 |
| 102 private: |
| 103 scoped_ptr<DnsQuery> query_; |
| 104 ScopedVector<DnsResponse> responses_; |
| 105 MockWrite write_; |
| 106 std::vector<MockRead> reads_; |
| 107 scoped_ptr<DelayedSocketData> provider_; |
| 108 |
| 109 DISALLOW_COPY_AND_ASSIGN(DnsSocketData); |
| 110 }; |
| 111 |
| 34 class TestSocketFactory; | 112 class TestSocketFactory; |
| 35 | 113 |
| 36 // A variant of MockUDPClientSocket which notifies the factory OnConnect. | 114 // A variant of MockUDPClientSocket which notifies the factory OnConnect. |
| 37 class TestUDPClientSocket : public MockUDPClientSocket { | 115 class TestUDPClientSocket : public MockUDPClientSocket { |
| 38 public: | 116 public: |
| 39 TestUDPClientSocket(TestSocketFactory* factory, | 117 TestUDPClientSocket(TestSocketFactory* factory, |
| 40 SocketDataProvider* data, | 118 SocketDataProvider* data, |
| 41 net::NetLog* net_log) | 119 net::NetLog* net_log) |
| 42 : MockUDPClientSocket(data, net_log), factory_(factory) { | 120 : MockUDPClientSocket(data, net_log), factory_(factory) { |
| 43 } | 121 } |
| 44 virtual ~TestUDPClientSocket() {} | 122 virtual ~TestUDPClientSocket() {} |
| 45 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE; | 123 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE; |
| 124 |
| 46 private: | 125 private: |
| 47 TestSocketFactory* factory_; | 126 TestSocketFactory* factory_; |
| 127 |
| 128 DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket); |
| 48 }; | 129 }; |
| 49 | 130 |
| 50 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect. | 131 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect. |
| 51 class TestSocketFactory : public MockClientSocketFactory { | 132 class TestSocketFactory : public MockClientSocketFactory { |
| 52 public: | 133 public: |
| 53 TestSocketFactory() {} | 134 TestSocketFactory() {} |
| 54 virtual ~TestSocketFactory() {} | 135 virtual ~TestSocketFactory() {} |
| 55 | 136 |
| 56 virtual DatagramClientSocket* CreateDatagramClientSocket( | 137 virtual DatagramClientSocket* CreateDatagramClientSocket( |
| 57 DatagramSocket::BindType bind_type, | 138 DatagramSocket::BindType bind_type, |
| 58 const RandIntCallback& rand_int_cb, | 139 const RandIntCallback& rand_int_cb, |
| 59 net::NetLog* net_log, | 140 net::NetLog* net_log, |
| 60 const net::NetLog::Source& source) OVERRIDE { | 141 const net::NetLog::Source& source) OVERRIDE { |
| 61 SocketDataProvider* data_provider = mock_data().GetNext(); | 142 SocketDataProvider* data_provider = mock_data().GetNext(); |
| 62 TestUDPClientSocket* socket = new TestUDPClientSocket(this, | 143 TestUDPClientSocket* socket = new TestUDPClientSocket(this, |
| 63 data_provider, | 144 data_provider, |
| 64 net_log); | 145 net_log); |
| 65 data_provider->set_socket(socket); | 146 data_provider->set_socket(socket); |
| 66 return socket; | 147 return socket; |
| 67 } | 148 } |
| 68 | 149 |
| 69 void OnConnect(const IPEndPoint& endpoint) { | 150 void OnConnect(const IPEndPoint& endpoint) { |
| 70 remote_endpoints.push_back(endpoint); | 151 remote_endpoints.push_back(endpoint); |
| 71 } | 152 } |
| 72 | 153 |
| 73 std::vector<IPEndPoint> remote_endpoints; | 154 std::vector<IPEndPoint> remote_endpoints; |
| 155 |
| 156 private: |
| 157 DISALLOW_COPY_AND_ASSIGN(TestSocketFactory); |
| 74 }; | 158 }; |
| 75 | 159 |
| 76 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) { | 160 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) { |
| 77 factory_->OnConnect(endpoint); | 161 factory_->OnConnect(endpoint); |
| 78 return MockUDPClientSocket::Connect(endpoint); | 162 return MockUDPClientSocket::Connect(endpoint); |
| 79 } | 163 } |
| 80 | 164 |
| 81 // Helper class that holds a DnsTransaction and handles OnTransactionComplete. | 165 // Helper class that holds a DnsTransaction and handles OnTransactionComplete. |
| 82 class TransactionHelper { | 166 class TransactionHelper { |
| 83 public: | 167 public: |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 EXPECT_FALSE(completed_); | 216 EXPECT_FALSE(completed_); |
| 133 EXPECT_EQ(transaction_.get(), t); | 217 EXPECT_EQ(transaction_.get(), t); |
| 134 | 218 |
| 135 completed_ = true; | 219 completed_ = true; |
| 136 | 220 |
| 137 if (cancel_in_callback_) { | 221 if (cancel_in_callback_) { |
| 138 Cancel(); | 222 Cancel(); |
| 139 return; | 223 return; |
| 140 } | 224 } |
| 141 | 225 |
| 226 // Tell MessageLoop to quit now, in case any ASSERT_* fails. |
| 227 if (quit_in_callback_) |
| 228 MessageLoop::current()->Quit(); |
| 229 |
| 142 if (expected_answer_count_ >= 0) { | 230 if (expected_answer_count_ >= 0) { |
| 143 EXPECT_EQ(OK, rv); | 231 ASSERT_EQ(OK, rv); |
| 232 ASSERT_TRUE(response != NULL); |
| 144 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_), | 233 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_), |
| 145 response->answer_count()); | 234 response->answer_count()); |
| 146 EXPECT_EQ(qtype_, response->qtype()); | 235 EXPECT_EQ(qtype_, response->qtype()); |
| 147 | 236 |
| 148 DnsRecordParser parser = response->Parser(); | 237 DnsRecordParser parser = response->Parser(); |
| 149 DnsResourceRecord record; | 238 DnsResourceRecord record; |
| 150 for (int i = 0; i < expected_answer_count_; ++i) { | 239 for (int i = 0; i < expected_answer_count_; ++i) { |
| 151 EXPECT_TRUE(parser.ReadRecord(&record)); | 240 EXPECT_TRUE(parser.ReadRecord(&record)); |
| 152 } | 241 } |
| 153 } else { | 242 } else { |
| 154 EXPECT_EQ(expected_answer_count_, rv); | 243 EXPECT_EQ(expected_answer_count_, rv); |
| 155 } | 244 } |
| 156 | |
| 157 if (quit_in_callback_) | |
| 158 MessageLoop::current()->Quit(); | |
| 159 } | 245 } |
| 160 | 246 |
| 161 bool has_completed() const { | 247 bool has_completed() const { |
| 162 return completed_; | 248 return completed_; |
| 163 } | 249 } |
| 164 | 250 |
| 165 // Shorthands for commonly used commands. | 251 // Shorthands for commonly used commands. |
| 166 | 252 |
| 167 bool Run(DnsTransactionFactory* factory) { | 253 bool Run(DnsTransactionFactory* factory) { |
| 168 StartTransaction(factory); | 254 StartTransaction(factory); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 void ConfigureFactory() { | 299 void ConfigureFactory() { |
| 214 socket_factory_.reset(new TestSocketFactory()); | 300 socket_factory_.reset(new TestSocketFactory()); |
| 215 session_ = new DnsSession( | 301 session_ = new DnsSession( |
| 216 config_, | 302 config_, |
| 217 socket_factory_.get(), | 303 socket_factory_.get(), |
| 218 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)), | 304 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)), |
| 219 NULL /* NetLog */); | 305 NULL /* NetLog */); |
| 220 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get()); | 306 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get()); |
| 221 } | 307 } |
| 222 | 308 |
| 223 // Each socket used by a DnsTransaction expects only one write and zero or one | 309 void AddSocketData(scoped_ptr<DnsSocketData> data) { |
| 224 // reads. | 310 transaction_ids_.push_back(data->query_id()); |
| 311 socket_factory_->AddSocketDataProvider(data->GetProvider()); |
| 312 socket_data_.push_back(data.release()); |
| 313 } |
| 225 | 314 |
| 226 // Add expected query for |dotted_name| and |qtype| with |id| and response | 315 // Add expected query for |dotted_name| and |qtype| with |id| and response |
| 227 // taken verbatim from |data| of |data_length| bytes. The transaction id in | 316 // taken verbatim from |data| of |data_length| bytes. The transaction id in |
| 228 // |data| should equal |id|, unless testing mismatched response. | 317 // |data| should equal |id|, unless testing mismatched response. |
| 229 void AddResponse(const std::string& dotted_name, | 318 void AddQueryAndResponse(uint16 id, |
| 230 uint16 qtype, | 319 const char* dotted_name, |
| 231 uint16 id, | 320 uint16 qtype, |
| 232 const char* data, | 321 const uint8* response_data, |
| 233 size_t data_length, | 322 size_t response_length, |
| 234 IoMode mode) { | 323 IoMode mode) { |
| 235 CHECK(socket_factory_.get()); | 324 CHECK(socket_factory_.get()); |
| 236 DnsQuery* query = new DnsQuery(id, DomainFromDot(dotted_name), qtype); | 325 scoped_ptr<DnsSocketData> data( |
| 237 queries_.push_back(query); | 326 new DnsSocketData(id, dotted_name, qtype, mode)); |
| 238 | 327 data->AddResponseData(response_data, response_length, mode); |
| 239 // The response is only used to hold the IOBuffer. | 328 AddSocketData(data.Pass()); |
| 240 DnsResponse* response = new DnsResponse(data, data_length, 0); | |
| 241 responses_.push_back(response); | |
| 242 | |
| 243 writes_.push_back(MockWrite(mode, | |
| 244 query->io_buffer()->data(), | |
| 245 query->io_buffer()->size())); | |
| 246 reads_.push_back(MockRead(mode, | |
| 247 response->io_buffer()->data(), | |
| 248 data_length)); | |
| 249 | |
| 250 transaction_ids_.push_back(id); | |
| 251 } | 329 } |
| 252 | 330 |
| 253 void AddAsyncResponse(const std::string& dotted_name, | 331 void AddAsyncQueryAndResponse(uint16 id, |
| 254 uint16 qtype, | 332 const char* dotted_name, |
| 255 uint16 id, | 333 uint16 qtype, |
| 256 const char* data, | 334 const uint8* data, |
| 257 size_t data_length) { | 335 size_t data_length) { |
| 258 AddResponse(dotted_name, qtype, id, data, data_length, ASYNC); | 336 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC); |
| 337 } |
| 338 |
| 339 void AddSyncQueryAndResponse(uint16 id, |
| 340 const char* dotted_name, |
| 341 uint16 qtype, |
| 342 const uint8* data, |
| 343 size_t data_length) { |
| 344 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS); |
| 259 } | 345 } |
| 260 | 346 |
| 261 // Add expected query of |dotted_name| and |qtype| and no response. | 347 // Add expected query of |dotted_name| and |qtype| and no response. |
| 262 void AddTimeout(const char* dotted_name, uint16 qtype) { | 348 void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) { |
| 263 CHECK(socket_factory_.get()); | 349 CHECK(socket_factory_.get()); |
| 264 uint16 id = base::RandInt(0, kuint16max); | 350 uint16 id = base::RandInt(0, kuint16max); |
| 265 DnsQuery* query = new DnsQuery(id, DomainFromDot(dotted_name), qtype); | 351 scoped_ptr<DnsSocketData> data( |
| 266 queries_.push_back(query); | 352 new DnsSocketData(id, dotted_name, qtype, ASYNC)); |
| 267 | 353 AddSocketData(data.Pass()); |
| 268 writes_.push_back(MockWrite(ASYNC, | |
| 269 query->io_buffer()->data(), | |
| 270 query->io_buffer()->size())); | |
| 271 // Empty MockRead indicates no data. | |
| 272 reads_.push_back(MockRead()); | |
| 273 transaction_ids_.push_back(id); | |
| 274 } | 354 } |
| 275 | 355 |
| 276 // Add expected query of |dotted_name| and |qtype| and response with no answer | 356 // Add expected query of |dotted_name| and |qtype| and matching response with |
| 277 // and rcode set to |rcode|. | 357 // no answer and RCODE set to |rcode|. The id will be generated randomly. |
| 278 void AddRcode(const char* dotted_name, uint16 qtype, int rcode, IoMode mode) { | 358 void AddQueryAndRcode(const char* dotted_name, |
| 359 uint16 qtype, |
| 360 int rcode, |
| 361 IoMode mode) { |
| 279 CHECK(socket_factory_.get()); | 362 CHECK(socket_factory_.get()); |
| 280 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode); | 363 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode); |
| 281 uint16 id = base::RandInt(0, kuint16max); | 364 uint16 id = base::RandInt(0, kuint16max); |
| 282 DnsQuery* query = new DnsQuery(id, DomainFromDot(dotted_name), qtype); | 365 scoped_ptr<DnsSocketData> data( |
| 283 queries_.push_back(query); | 366 new DnsSocketData(id, dotted_name, qtype, mode)); |
| 284 | 367 data->AddRcode(rcode, mode); |
| 285 DnsResponse* response = new DnsResponse(query->io_buffer()->data(), | 368 AddSocketData(data.Pass()); |
| 286 query->io_buffer()->size(), | |
| 287 0); | |
| 288 dns_protocol::Header* header = | |
| 289 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data()); | |
| 290 header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode); | |
| 291 responses_.push_back(response); | |
| 292 | |
| 293 writes_.push_back(MockWrite(mode, | |
| 294 query->io_buffer()->data(), | |
| 295 query->io_buffer()->size())); | |
| 296 reads_.push_back(MockRead(mode, | |
| 297 response->io_buffer()->data(), | |
| 298 query->io_buffer()->size())); | |
| 299 transaction_ids_.push_back(id); | |
| 300 } | 369 } |
| 301 | 370 |
| 302 void AddAsyncRcode(const char* dotted_name, uint16 qtype, int rcode) { | 371 void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) { |
| 303 AddRcode(dotted_name, qtype, rcode, ASYNC); | 372 AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC); |
| 304 } | 373 } |
| 305 | 374 |
| 306 // Call after all Add* calls to prepare data for |socket_factory_|. | 375 void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) { |
| 307 // This separation is necessary because the |reads_| and |writes_| vectors | 376 AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS); |
| 308 // could reallocate their data during those calls. | |
| 309 void PrepareSockets() { | |
| 310 CHECK_EQ(writes_.size(), reads_.size()); | |
| 311 for (size_t i = 0; i < writes_.size(); ++i) { | |
| 312 DelayedSocketData* data; | |
| 313 if (reads_[i].data) { | |
| 314 data = new DelayedSocketData(1, &reads_[i], 1, &writes_[i], 1); | |
| 315 } else { | |
| 316 // Timeout. | |
| 317 data = new DelayedSocketData(2, NULL, 0, &writes_[i], 1); | |
| 318 } | |
| 319 socket_data_.push_back(data); | |
| 320 socket_factory_->AddSocketDataProvider(data); | |
| 321 } | |
| 322 } | 377 } |
| 323 | 378 |
| 324 // Checks if the sockets were connected in the order matching the indices in | 379 // Checks if the sockets were connected in the order matching the indices in |
| 325 // |servers|. | 380 // |servers|. |
| 326 void CheckServerOrder(const unsigned* servers, size_t num_attempts) { | 381 void CheckServerOrder(const unsigned* servers, size_t num_attempts) { |
| 327 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints.size()); | 382 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints.size()); |
| 328 for (size_t i = 0; i < num_attempts; ++i) { | 383 for (size_t i = 0; i < num_attempts; ++i) { |
| 329 EXPECT_EQ(socket_factory_->remote_endpoints[i], | 384 EXPECT_EQ(socket_factory_->remote_endpoints[i], |
| 330 session_->config().nameservers[servers[i]]); | 385 session_->config().nameservers[servers[i]]); |
| 331 } | 386 } |
| 332 } | 387 } |
| 333 | 388 |
| 334 void SetUp() OVERRIDE { | 389 void SetUp() OVERRIDE { |
| 335 // By default set one server, | 390 // By default set one server, |
| 336 ConfigureNumServers(1); | 391 ConfigureNumServers(1); |
| 337 // and no retransmissions, | 392 // and no retransmissions, |
| 338 config_.attempts = 1; | 393 config_.attempts = 1; |
| 339 // but long enough timeout for memory tests. | 394 // but long enough timeout for memory tests. |
| 340 config_.timeout = TestTimeouts::action_timeout(); | 395 config_.timeout = TestTimeouts::action_timeout(); |
| 341 ConfigureFactory(); | 396 ConfigureFactory(); |
| 342 } | 397 } |
| 343 | 398 |
| 344 void TearDown() OVERRIDE { | 399 void TearDown() OVERRIDE { |
| 345 // Check that all socket data was at least written to. | 400 // Check that all socket data was at least written to. |
| 346 for (size_t i = 0; i < socket_data_.size(); ++i) { | 401 for (size_t i = 0; i < socket_data_.size(); ++i) { |
| 347 EXPECT_GT(socket_data_[i]->write_index(), 0u); | 402 EXPECT_TRUE(socket_data_[i]->was_written()) << i; |
| 348 } | 403 } |
| 349 } | 404 } |
| 350 | 405 |
| 351 protected: | 406 protected: |
| 352 int GetNextId(int min, int max) { | 407 int GetNextId(int min, int max) { |
| 353 EXPECT_FALSE(transaction_ids_.empty()); | 408 EXPECT_FALSE(transaction_ids_.empty()); |
| 354 int id = transaction_ids_.front(); | 409 int id = transaction_ids_.front(); |
| 355 transaction_ids_.pop_front(); | 410 transaction_ids_.pop_front(); |
| 356 EXPECT_GE(id, min); | 411 EXPECT_GE(id, min); |
| 357 EXPECT_LE(id, max); | 412 EXPECT_LE(id, max); |
| 358 return id; | 413 return id; |
| 359 } | 414 } |
| 360 | 415 |
| 361 DnsConfig config_; | 416 DnsConfig config_; |
| 362 | 417 |
| 363 // Holders for the buffers behind MockRead/MockWrites (they do not own them). | 418 ScopedVector<DnsSocketData> socket_data_; |
| 364 ScopedVector<DnsQuery> queries_; | |
| 365 ScopedVector<DnsResponse> responses_; | |
| 366 | |
| 367 // Holders for MockRead/MockWrites (SocketDataProvider does not own it). | |
| 368 std::vector<MockRead> reads_; | |
| 369 std::vector<MockWrite> writes_; | |
| 370 | |
| 371 // Holder for the socket data (MockClientSocketFactory does not own it). | |
| 372 ScopedVector<DelayedSocketData> socket_data_; | |
| 373 | 419 |
| 374 std::deque<int> transaction_ids_; | 420 std::deque<int> transaction_ids_; |
| 375 scoped_ptr<TestSocketFactory> socket_factory_; | 421 scoped_ptr<TestSocketFactory> socket_factory_; |
| 376 scoped_refptr<DnsSession> session_; | 422 scoped_refptr<DnsSession> session_; |
| 377 scoped_ptr<DnsTransactionFactory> transaction_factory_; | 423 scoped_ptr<DnsTransactionFactory> transaction_factory_; |
| 378 }; | 424 }; |
| 379 | 425 |
| 380 TEST_F(DnsTransactionTest, Lookup) { | 426 TEST_F(DnsTransactionTest, Lookup) { |
| 381 AddAsyncResponse(kT0HostName, | 427 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, |
| 382 kT0Qtype, | 428 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 383 0 /* id */, | |
| 384 reinterpret_cast<const char*>(kT0ResponseDatagram), | |
| 385 arraysize(kT0ResponseDatagram)); | |
| 386 PrepareSockets(); | |
| 387 | 429 |
| 388 TransactionHelper helper0(kT0HostName, | 430 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 389 kT0Qtype, | |
| 390 kT0RecordCount); | |
| 391 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 431 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 392 } | 432 } |
| 393 | 433 |
| 394 // Concurrent lookup tests assume that DnsTransaction::Start immediately | 434 // Concurrent lookup tests assume that DnsTransaction::Start immediately |
| 395 // consumes a socket from ClientSocketFactory. | 435 // consumes a socket from ClientSocketFactory. |
| 396 TEST_F(DnsTransactionTest, ConcurrentLookup) { | 436 TEST_F(DnsTransactionTest, ConcurrentLookup) { |
| 397 AddAsyncResponse(kT0HostName, | 437 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, |
| 398 kT0Qtype, | 438 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 399 0 /* id */, | 439 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype, |
| 400 reinterpret_cast<const char*>(kT0ResponseDatagram), | 440 kT1ResponseDatagram, arraysize(kT1ResponseDatagram)); |
| 401 arraysize(kT0ResponseDatagram)); | |
| 402 AddAsyncResponse(kT1HostName, | |
| 403 kT1Qtype, | |
| 404 1 /* id */, | |
| 405 reinterpret_cast<const char*>(kT1ResponseDatagram), | |
| 406 arraysize(kT1ResponseDatagram)); | |
| 407 PrepareSockets(); | |
| 408 | 441 |
| 409 TransactionHelper helper0(kT0HostName, | 442 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 410 kT0Qtype, | |
| 411 kT0RecordCount); | |
| 412 helper0.StartTransaction(transaction_factory_.get()); | 443 helper0.StartTransaction(transaction_factory_.get()); |
| 413 TransactionHelper helper1(kT1HostName, | 444 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount); |
| 414 kT1Qtype, | |
| 415 kT1RecordCount); | |
| 416 helper1.StartTransaction(transaction_factory_.get()); | 445 helper1.StartTransaction(transaction_factory_.get()); |
| 417 | 446 |
| 418 MessageLoop::current()->RunAllPending(); | 447 MessageLoop::current()->RunAllPending(); |
| 419 | 448 |
| 420 EXPECT_TRUE(helper0.has_completed()); | 449 EXPECT_TRUE(helper0.has_completed()); |
| 421 EXPECT_TRUE(helper1.has_completed()); | 450 EXPECT_TRUE(helper1.has_completed()); |
| 422 } | 451 } |
| 423 | 452 |
| 424 TEST_F(DnsTransactionTest, CancelLookup) { | 453 TEST_F(DnsTransactionTest, CancelLookup) { |
| 425 AddAsyncResponse(kT0HostName, | 454 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, |
| 426 kT0Qtype, | 455 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 427 0 /* id */, | 456 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype, |
| 428 reinterpret_cast<const char*>(kT0ResponseDatagram), | 457 kT1ResponseDatagram, arraysize(kT1ResponseDatagram)); |
| 429 arraysize(kT0ResponseDatagram)); | |
| 430 AddAsyncResponse(kT1HostName, | |
| 431 kT1Qtype, | |
| 432 1 /* id */, | |
| 433 reinterpret_cast<const char*>(kT1ResponseDatagram), | |
| 434 arraysize(kT1ResponseDatagram)); | |
| 435 PrepareSockets(); | |
| 436 | 458 |
| 437 TransactionHelper helper0(kT0HostName, | 459 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 438 kT0Qtype, | |
| 439 kT0RecordCount); | |
| 440 helper0.StartTransaction(transaction_factory_.get()); | 460 helper0.StartTransaction(transaction_factory_.get()); |
| 441 TransactionHelper helper1(kT1HostName, | 461 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount); |
| 442 kT1Qtype, | |
| 443 kT1RecordCount); | |
| 444 helper1.StartTransaction(transaction_factory_.get()); | 462 helper1.StartTransaction(transaction_factory_.get()); |
| 445 | 463 |
| 446 helper0.Cancel(); | 464 helper0.Cancel(); |
| 447 | 465 |
| 448 MessageLoop::current()->RunAllPending(); | 466 MessageLoop::current()->RunAllPending(); |
| 449 | 467 |
| 450 EXPECT_FALSE(helper0.has_completed()); | 468 EXPECT_FALSE(helper0.has_completed()); |
| 451 EXPECT_TRUE(helper1.has_completed()); | 469 EXPECT_TRUE(helper1.has_completed()); |
| 452 } | 470 } |
| 453 | 471 |
| 454 TEST_F(DnsTransactionTest, DestroyFactory) { | 472 TEST_F(DnsTransactionTest, DestroyFactory) { |
| 455 AddAsyncResponse(kT0HostName, | 473 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, |
| 456 kT0Qtype, | 474 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 457 0 /* id */, | |
| 458 reinterpret_cast<const char*>(kT0ResponseDatagram), | |
| 459 arraysize(kT0ResponseDatagram)); | |
| 460 PrepareSockets(); | |
| 461 | 475 |
| 462 TransactionHelper helper0(kT0HostName, | 476 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 463 kT0Qtype, | |
| 464 kT0RecordCount); | |
| 465 helper0.StartTransaction(transaction_factory_.get()); | 477 helper0.StartTransaction(transaction_factory_.get()); |
| 466 | 478 |
| 467 // Destroying the client does not affect running requests. | 479 // Destroying the client does not affect running requests. |
| 468 transaction_factory_.reset(NULL); | 480 transaction_factory_.reset(NULL); |
| 469 | 481 |
| 470 MessageLoop::current()->RunAllPending(); | 482 MessageLoop::current()->RunAllPending(); |
| 471 | 483 |
| 472 EXPECT_TRUE(helper0.has_completed()); | 484 EXPECT_TRUE(helper0.has_completed()); |
| 473 } | 485 } |
| 474 | 486 |
| 475 TEST_F(DnsTransactionTest, CancelFromCallback) { | 487 TEST_F(DnsTransactionTest, CancelFromCallback) { |
| 476 AddAsyncResponse(kT0HostName, | 488 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, |
| 477 kT0Qtype, | 489 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 478 0 /* id */, | |
| 479 reinterpret_cast<const char*>(kT0ResponseDatagram), | |
| 480 arraysize(kT0ResponseDatagram)); | |
| 481 PrepareSockets(); | |
| 482 | 490 |
| 483 TransactionHelper helper0(kT0HostName, | 491 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 484 kT0Qtype, | |
| 485 kT0RecordCount); | |
| 486 helper0.set_cancel_in_callback(); | 492 helper0.set_cancel_in_callback(); |
| 487 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 493 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 488 } | 494 } |
| 489 | 495 |
| 496 TEST_F(DnsTransactionTest, MismatchedResponseSync) { |
| 497 config_.attempts = 2; |
| 498 config_.timeout = TestTimeouts::tiny_timeout(); |
| 499 ConfigureFactory(); |
| 500 |
| 501 // Attempt receives mismatched response followed by valid response. |
| 502 scoped_ptr<DnsSocketData> data( |
| 503 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS)); |
| 504 data->AddResponseData(kT1ResponseDatagram, |
| 505 arraysize(kT1ResponseDatagram), SYNCHRONOUS); |
| 506 data->AddResponseData(kT0ResponseDatagram, |
| 507 arraysize(kT0ResponseDatagram), SYNCHRONOUS); |
| 508 AddSocketData(data.Pass()); |
| 509 |
| 510 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 511 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); |
| 512 } |
| 513 |
| 514 TEST_F(DnsTransactionTest, MismatchedResponseAsync) { |
| 515 config_.attempts = 2; |
| 516 config_.timeout = TestTimeouts::tiny_timeout(); |
| 517 ConfigureFactory(); |
| 518 |
| 519 // First attempt receives mismatched response followed by valid response. |
| 520 // Second attempt times out. |
| 521 scoped_ptr<DnsSocketData> data( |
| 522 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC)); |
| 523 data->AddResponseData(kT1ResponseDatagram, |
| 524 arraysize(kT1ResponseDatagram), ASYNC); |
| 525 data->AddResponseData(kT0ResponseDatagram, |
| 526 arraysize(kT0ResponseDatagram), ASYNC); |
| 527 AddSocketData(data.Pass()); |
| 528 AddQueryAndTimeout(kT0HostName, kT0Qtype); |
| 529 |
| 530 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 531 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); |
| 532 } |
| 533 |
| 534 TEST_F(DnsTransactionTest, MismatchedResponseFail) { |
| 535 config_.timeout = TestTimeouts::tiny_timeout(); |
| 536 ConfigureFactory(); |
| 537 |
| 538 // Attempt receives mismatched response but times out because only one attempt |
| 539 // is allowed. |
| 540 AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype, |
| 541 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 542 |
| 543 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT); |
| 544 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); |
| 545 } |
| 546 |
| 490 TEST_F(DnsTransactionTest, ServerFail) { | 547 TEST_F(DnsTransactionTest, ServerFail) { |
| 491 AddAsyncRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); | 548 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); |
| 492 PrepareSockets(); | |
| 493 | 549 |
| 494 TransactionHelper helper0(kT0HostName, | 550 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED); |
| 495 kT0Qtype, | |
| 496 ERR_DNS_SERVER_FAILED); | |
| 497 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 551 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 498 } | 552 } |
| 499 | 553 |
| 500 TEST_F(DnsTransactionTest, NoDomain) { | 554 TEST_F(DnsTransactionTest, NoDomain) { |
| 501 AddAsyncRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN); | 555 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN); |
| 502 PrepareSockets(); | |
| 503 | 556 |
| 504 TransactionHelper helper0(kT0HostName, | 557 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED); |
| 505 kT0Qtype, | |
| 506 ERR_NAME_NOT_RESOLVED); | |
| 507 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 558 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 508 } | 559 } |
| 509 | 560 |
| 510 TEST_F(DnsTransactionTest, Timeout) { | 561 TEST_F(DnsTransactionTest, Timeout) { |
| 511 config_.attempts = 3; | 562 config_.attempts = 3; |
| 512 // Use short timeout to speed up the test. | 563 // Use short timeout to speed up the test. |
| 513 config_.timeout = TestTimeouts::tiny_timeout(); | 564 config_.timeout = TestTimeouts::tiny_timeout(); |
| 514 ConfigureFactory(); | 565 ConfigureFactory(); |
| 515 | 566 |
| 516 AddTimeout(kT0HostName, kT0Qtype); | 567 AddQueryAndTimeout(kT0HostName, kT0Qtype); |
| 517 AddTimeout(kT0HostName, kT0Qtype); | 568 AddQueryAndTimeout(kT0HostName, kT0Qtype); |
| 518 AddTimeout(kT0HostName, kT0Qtype); | 569 AddQueryAndTimeout(kT0HostName, kT0Qtype); |
| 519 PrepareSockets(); | |
| 520 | 570 |
| 521 TransactionHelper helper0(kT0HostName, | 571 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT); |
| 522 kT0Qtype, | |
| 523 ERR_DNS_TIMED_OUT); | |
| 524 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); | 572 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); |
| 525 MessageLoop::current()->AssertIdle(); | 573 MessageLoop::current()->AssertIdle(); |
| 526 } | 574 } |
| 527 | 575 |
| 528 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) { | 576 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) { |
| 529 // Test that we fallback on both server failure and timeout. | 577 // Test that we fallback on both server failure and timeout. |
| 530 config_.attempts = 2; | 578 config_.attempts = 2; |
| 531 // The next request should start from the next server. | 579 // The next request should start from the next server. |
| 532 config_.rotate = true; | 580 config_.rotate = true; |
| 533 ConfigureNumServers(3); | 581 ConfigureNumServers(3); |
| 534 // Use short timeout to speed up the test. | 582 // Use short timeout to speed up the test. |
| 535 config_.timeout = TestTimeouts::tiny_timeout(); | 583 config_.timeout = TestTimeouts::tiny_timeout(); |
| 536 ConfigureFactory(); | 584 ConfigureFactory(); |
| 537 | 585 |
| 538 // Responses for first request. | 586 // Responses for first request. |
| 539 AddTimeout(kT0HostName, kT0Qtype); | 587 AddQueryAndTimeout(kT0HostName, kT0Qtype); |
| 540 AddAsyncRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); | 588 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); |
| 541 AddTimeout(kT0HostName, kT0Qtype); | 589 AddQueryAndTimeout(kT0HostName, kT0Qtype); |
| 542 AddAsyncRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); | 590 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL); |
| 543 AddAsyncRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN); | 591 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN); |
| 544 // Responses for second request. | 592 // Responses for second request. |
| 545 AddAsyncRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL); | 593 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL); |
| 546 AddAsyncRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN); | 594 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN); |
| 547 PrepareSockets(); | |
| 548 | 595 |
| 549 TransactionHelper helper0(kT0HostName, | 596 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED); |
| 550 kT0Qtype, | 597 TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED); |
| 551 ERR_NAME_NOT_RESOLVED); | |
| 552 TransactionHelper helper1(kT1HostName, | |
| 553 kT1Qtype, | |
| 554 ERR_NAME_NOT_RESOLVED); | |
| 555 | 598 |
| 556 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); | 599 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); |
| 557 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); | 600 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); |
| 558 | 601 |
| 559 unsigned kOrder[] = { | 602 unsigned kOrder[] = { |
| 560 0, 1, 2, 0, 1, // The first transaction. | 603 0, 1, 2, 0, 1, // The first transaction. |
| 561 1, 2, // The second transaction starts from the next server. | 604 1, 2, // The second transaction starts from the next server. |
| 562 }; | 605 }; |
| 563 CheckServerOrder(kOrder, arraysize(kOrder)); | 606 CheckServerOrder(kOrder, arraysize(kOrder)); |
| 564 } | 607 } |
| 565 | 608 |
| 566 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) { | 609 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) { |
| 567 config_.ndots = 2; | 610 config_.ndots = 2; |
| 568 config_.search.push_back("a"); | 611 config_.search.push_back("a"); |
| 569 config_.search.push_back("b"); | 612 config_.search.push_back("b"); |
| 570 config_.search.push_back("c"); | 613 config_.search.push_back("c"); |
| 571 config_.rotate = true; | 614 config_.rotate = true; |
| 572 ConfigureNumServers(2); | 615 ConfigureNumServers(2); |
| 573 ConfigureFactory(); | 616 ConfigureFactory(); |
| 574 | 617 |
| 575 AddAsyncRcode("x.y.z", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 618 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA, |
| 576 AddAsyncRcode("x.y.z.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 619 dns_protocol::kRcodeNXDOMAIN); |
| 577 AddAsyncRcode("x.y.z.b", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 620 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA, |
| 578 AddAsyncRcode("x.y.z.c", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 621 dns_protocol::kRcodeNXDOMAIN); |
| 579 PrepareSockets(); | 622 AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA, |
| 623 dns_protocol::kRcodeNXDOMAIN); |
| 624 AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA, |
| 625 dns_protocol::kRcodeNXDOMAIN); |
| 580 | 626 |
| 581 TransactionHelper helper0("x.y.z", | 627 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, |
| 582 dns_protocol::kTypeA, | |
| 583 ERR_NAME_NOT_RESOLVED); | 628 ERR_NAME_NOT_RESOLVED); |
| 584 | 629 |
| 585 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 630 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 586 | 631 |
| 587 // Also check if suffix search causes server rotation. | 632 // Also check if suffix search causes server rotation. |
| 588 unsigned kOrder0[] = { 0, 1, 0, 1 }; | 633 unsigned kOrder0[] = { 0, 1, 0, 1 }; |
| 589 CheckServerOrder(kOrder0, arraysize(kOrder0)); | 634 CheckServerOrder(kOrder0, arraysize(kOrder0)); |
| 590 } | 635 } |
| 591 | 636 |
| 592 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) { | 637 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) { |
| 593 config_.ndots = 2; | 638 config_.ndots = 2; |
| 594 config_.search.push_back("a"); | 639 config_.search.push_back("a"); |
| 595 config_.search.push_back("b"); | 640 config_.search.push_back("b"); |
| 596 config_.search.push_back("c"); | 641 config_.search.push_back("c"); |
| 597 ConfigureFactory(); | 642 ConfigureFactory(); |
| 598 | 643 |
| 599 // Responses for first transaction. | 644 // Responses for first transaction. |
| 600 AddAsyncRcode("x.y.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 645 AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA, |
| 601 AddAsyncRcode("x.y.b", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 646 dns_protocol::kRcodeNXDOMAIN); |
| 602 AddAsyncRcode("x.y.c", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 647 AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA, |
| 603 AddAsyncRcode("x.y", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 648 dns_protocol::kRcodeNXDOMAIN); |
| 649 AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA, |
| 650 dns_protocol::kRcodeNXDOMAIN); |
| 651 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA, |
| 652 dns_protocol::kRcodeNXDOMAIN); |
| 604 // Responses for second transaction. | 653 // Responses for second transaction. |
| 605 AddAsyncRcode("x.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 654 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA, |
| 606 AddAsyncRcode("x.b", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 655 dns_protocol::kRcodeNXDOMAIN); |
| 607 AddAsyncRcode("x.c", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 656 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA, |
| 657 dns_protocol::kRcodeNXDOMAIN); |
| 658 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA, |
| 659 dns_protocol::kRcodeNXDOMAIN); |
| 608 // Responses for third transaction. | 660 // Responses for third transaction. |
| 609 AddAsyncRcode("x", dns_protocol::kTypeAAAA, dns_protocol::kRcodeNXDOMAIN); | 661 AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA, |
| 610 PrepareSockets(); | 662 dns_protocol::kRcodeNXDOMAIN); |
| 611 | 663 |
| 612 TransactionHelper helper0("x.y", | 664 TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); |
| 613 dns_protocol::kTypeA, | |
| 614 ERR_NAME_NOT_RESOLVED); | |
| 615 | 665 |
| 616 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 666 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 617 | 667 |
| 618 // A single-label name. | 668 // A single-label name. |
| 619 TransactionHelper helper1("x", | 669 TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); |
| 620 dns_protocol::kTypeA, | |
| 621 ERR_NAME_NOT_RESOLVED); | |
| 622 | 670 |
| 623 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); | 671 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); |
| 624 | 672 |
| 625 // A fully-qualified name. | 673 // A fully-qualified name. |
| 626 TransactionHelper helper2("x.", | 674 TransactionHelper helper2("x.", dns_protocol::kTypeAAAA, |
| 627 dns_protocol::kTypeAAAA, | |
| 628 ERR_NAME_NOT_RESOLVED); | 675 ERR_NAME_NOT_RESOLVED); |
| 629 | 676 |
| 630 EXPECT_TRUE(helper2.Run(transaction_factory_.get())); | 677 EXPECT_TRUE(helper2.Run(transaction_factory_.get())); |
| 631 } | 678 } |
| 632 | 679 |
| 633 TEST_F(DnsTransactionTest, EmptySuffixSearch) { | 680 TEST_F(DnsTransactionTest, EmptySuffixSearch) { |
| 634 // Responses for first transaction. | 681 // Responses for first transaction. |
| 635 AddAsyncRcode("x", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 682 AddAsyncQueryAndRcode("x", dns_protocol::kTypeA, |
| 636 PrepareSockets(); | 683 dns_protocol::kRcodeNXDOMAIN); |
| 637 | 684 |
| 638 // A fully-qualified name. | 685 // A fully-qualified name. |
| 639 TransactionHelper helper0("x.", | 686 TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); |
| 640 dns_protocol::kTypeA, | |
| 641 ERR_NAME_NOT_RESOLVED); | |
| 642 | 687 |
| 643 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 688 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 644 | 689 |
| 645 // A single label name is not even attempted. | 690 // A single label name is not even attempted. |
| 646 TransactionHelper helper1("singlelabel", | 691 TransactionHelper helper1("singlelabel", dns_protocol::kTypeA, |
| 647 dns_protocol::kTypeA, | |
| 648 ERR_DNS_SEARCH_EMPTY); | 692 ERR_DNS_SEARCH_EMPTY); |
| 649 | 693 |
| 650 helper1.StartTransaction(transaction_factory_.get()); | 694 helper1.StartTransaction(transaction_factory_.get()); |
| 651 EXPECT_TRUE(helper1.has_completed()); | 695 EXPECT_TRUE(helper1.has_completed()); |
| 652 } | 696 } |
| 653 | 697 |
| 654 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) { | 698 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) { |
| 655 config_.search.push_back("a"); | 699 config_.search.push_back("a"); |
| 656 config_.search.push_back("b"); | 700 config_.search.push_back("b"); |
| 657 config_.search.push_back("c"); | 701 config_.search.push_back("c"); |
| 658 config_.append_to_multi_label_name = false; | 702 config_.append_to_multi_label_name = false; |
| 659 ConfigureFactory(); | 703 ConfigureFactory(); |
| 660 | 704 |
| 661 // Responses for first transaction. | 705 // Responses for first transaction. |
| 662 AddAsyncRcode("x.y.z", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 706 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA, |
| 707 dns_protocol::kRcodeNXDOMAIN); |
| 663 // Responses for second transaction. | 708 // Responses for second transaction. |
| 664 AddAsyncRcode("x.y", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 709 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA, |
| 710 dns_protocol::kRcodeNXDOMAIN); |
| 665 // Responses for third transaction. | 711 // Responses for third transaction. |
| 666 AddAsyncRcode("x.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 712 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA, |
| 667 AddAsyncRcode("x.b", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 713 dns_protocol::kRcodeNXDOMAIN); |
| 668 AddAsyncRcode("x.c", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 714 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA, |
| 669 PrepareSockets(); | 715 dns_protocol::kRcodeNXDOMAIN); |
| 716 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA, |
| 717 dns_protocol::kRcodeNXDOMAIN); |
| 670 | 718 |
| 671 TransactionHelper helper0("x.y.z", | 719 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, |
| 672 dns_protocol::kTypeA, | |
| 673 ERR_NAME_NOT_RESOLVED); | 720 ERR_NAME_NOT_RESOLVED); |
| 674 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 721 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 675 | 722 |
| 676 TransactionHelper helper1("x.y", | 723 TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); |
| 677 dns_protocol::kTypeA, | |
| 678 ERR_NAME_NOT_RESOLVED); | |
| 679 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); | 724 EXPECT_TRUE(helper1.Run(transaction_factory_.get())); |
| 680 | 725 |
| 681 TransactionHelper helper2("x", | 726 TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED); |
| 682 dns_protocol::kTypeA, | |
| 683 ERR_NAME_NOT_RESOLVED); | |
| 684 EXPECT_TRUE(helper2.Run(transaction_factory_.get())); | 727 EXPECT_TRUE(helper2.Run(transaction_factory_.get())); |
| 685 } | 728 } |
| 686 | 729 |
| 687 const uint8 kResponseNoData[] = { | 730 const uint8 kResponseNoData[] = { |
| 688 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, | 731 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, |
| 689 // Question | 732 // Question |
| 690 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, | 733 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, |
| 691 // Authority section, SOA record, TTL 0x3E6 | 734 // Authority section, SOA record, TTL 0x3E6 |
| 692 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6, | 735 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6, |
| 693 // Minimal RDATA, 18 bytes | 736 // Minimal RDATA, 18 bytes |
| 694 0x00, 0x12, | 737 0x00, 0x12, |
| 695 0x00, 0x00, | 738 0x00, 0x00, |
| 696 0x00, 0x00, 0x00, 0x00, | 739 0x00, 0x00, 0x00, 0x00, |
| 697 0x00, 0x00, 0x00, 0x00, | 740 0x00, 0x00, 0x00, 0x00, |
| 698 0x00, 0x00, 0x00, 0x00, | 741 0x00, 0x00, 0x00, 0x00, |
| 699 0x00, 0x00, 0x00, 0x00, | 742 0x00, 0x00, 0x00, 0x00, |
| 700 }; | 743 }; |
| 701 | 744 |
| 702 TEST_F(DnsTransactionTest, SuffixSearchStop) { | 745 TEST_F(DnsTransactionTest, SuffixSearchStop) { |
| 703 config_.ndots = 2; | 746 config_.ndots = 2; |
| 704 config_.search.push_back("a"); | 747 config_.search.push_back("a"); |
| 705 config_.search.push_back("b"); | 748 config_.search.push_back("b"); |
| 706 config_.search.push_back("c"); | 749 config_.search.push_back("c"); |
| 707 ConfigureFactory(); | 750 ConfigureFactory(); |
| 708 | 751 |
| 709 AddAsyncRcode("x.y.z", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 752 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA, |
| 710 AddAsyncRcode("x.y.z.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN); | 753 dns_protocol::kRcodeNXDOMAIN); |
| 711 AddAsyncResponse("x.y.z.b", | 754 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA, |
| 712 dns_protocol::kTypeA, | 755 dns_protocol::kRcodeNXDOMAIN); |
| 713 0 /* id */, | 756 AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA, |
| 714 reinterpret_cast<const char*>(kResponseNoData), | 757 kResponseNoData, arraysize(kResponseNoData)); |
| 715 arraysize(kResponseNoData)); | |
| 716 PrepareSockets(); | |
| 717 | 758 |
| 718 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */); | 759 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */); |
| 719 | 760 |
| 720 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 761 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 721 } | 762 } |
| 722 | 763 |
| 723 TEST_F(DnsTransactionTest, SyncFirstQuery) { | 764 TEST_F(DnsTransactionTest, SyncFirstQuery) { |
| 724 config_.search.push_back("lab.ccs.neu.edu"); | 765 config_.search.push_back("lab.ccs.neu.edu"); |
| 725 config_.search.push_back("ccs.neu.edu"); | 766 config_.search.push_back("ccs.neu.edu"); |
| 726 ConfigureFactory(); | 767 ConfigureFactory(); |
| 727 | 768 |
| 728 AddResponse(kT0HostName, | 769 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, |
| 729 kT0Qtype, | 770 kT0ResponseDatagram, arraysize(kT0ResponseDatagram)); |
| 730 0 /* id */, | |
| 731 reinterpret_cast<const char*>(kT0ResponseDatagram), | |
| 732 arraysize(kT0ResponseDatagram), | |
| 733 SYNCHRONOUS); | |
| 734 PrepareSockets(); | |
| 735 | 771 |
| 736 TransactionHelper helper0(kT0HostName, | 772 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount); |
| 737 kT0Qtype, | |
| 738 kT0RecordCount); | |
| 739 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 773 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 740 } | 774 } |
| 741 | 775 |
| 742 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) { | 776 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) { |
| 743 config_.search.push_back("lab.ccs.neu.edu"); | 777 config_.search.push_back("lab.ccs.neu.edu"); |
| 744 config_.search.push_back("ccs.neu.edu"); | 778 config_.search.push_back("ccs.neu.edu"); |
| 745 ConfigureFactory(); | 779 ConfigureFactory(); |
| 746 | 780 |
| 747 AddRcode("www.lab.ccs.neu.edu", | 781 AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype, |
| 748 kT2Qtype, | 782 dns_protocol::kRcodeNXDOMAIN); |
| 749 dns_protocol::kRcodeNXDOMAIN, | 783 // "www.ccs.neu.edu" |
| 750 SYNCHRONOUS); | 784 AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype, |
| 751 AddResponse(kT2HostName, // "www.ccs.neu.edu" | 785 kT2ResponseDatagram, arraysize(kT2ResponseDatagram)); |
| 752 kT2Qtype, | |
| 753 2 /* id */, | |
| 754 reinterpret_cast<const char*>(kT2ResponseDatagram), | |
| 755 arraysize(kT2ResponseDatagram), | |
| 756 ASYNC); | |
| 757 PrepareSockets(); | |
| 758 | 786 |
| 759 TransactionHelper helper0("www", | 787 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount); |
| 760 kT2Qtype, | |
| 761 kT2RecordCount); | |
| 762 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 788 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 763 } | 789 } |
| 764 | 790 |
| 765 TEST_F(DnsTransactionTest, SyncSearchQuery) { | 791 TEST_F(DnsTransactionTest, SyncSearchQuery) { |
| 766 config_.search.push_back("lab.ccs.neu.edu"); | 792 config_.search.push_back("lab.ccs.neu.edu"); |
| 767 config_.search.push_back("ccs.neu.edu"); | 793 config_.search.push_back("ccs.neu.edu"); |
| 768 ConfigureFactory(); | 794 ConfigureFactory(); |
| 769 | 795 |
| 770 AddRcode("www.lab.ccs.neu.edu", | 796 AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA, |
| 771 dns_protocol::kTypeA, | 797 dns_protocol::kRcodeNXDOMAIN); |
| 772 dns_protocol::kRcodeNXDOMAIN, | 798 AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype, |
| 773 ASYNC); | 799 kT2ResponseDatagram, arraysize(kT2ResponseDatagram)); |
| 774 AddResponse(kT2HostName, | |
| 775 kT2Qtype, | |
| 776 2 /* id */, | |
| 777 reinterpret_cast<const char*>(kT2ResponseDatagram), | |
| 778 arraysize(kT2ResponseDatagram), | |
| 779 SYNCHRONOUS); | |
| 780 PrepareSockets(); | |
| 781 | 800 |
| 782 TransactionHelper helper0("www", | 801 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount); |
| 783 kT2Qtype, | |
| 784 kT2RecordCount); | |
| 785 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); | 802 EXPECT_TRUE(helper0.Run(transaction_factory_.get())); |
| 786 } | 803 } |
| 787 | 804 |
| 788 } // namespace | 805 } // namespace |
| 789 | 806 |
| 790 } // namespace net | 807 } // namespace net |
| OLD | NEW |