Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(378)

Side by Side Diff: net/dns/dns_transaction_unittest.cc

Issue 9190031: DnsClient refactoring + features (timeout, suffix search, server rotation). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed code review. Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <deque>
8 #include <vector>
9
10 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/rand_util.h"
11 #include "base/test/test_timeouts.h" 11 #include "base/test/test_timeouts.h"
12 #include "base/time.h" 12 #include "net/base/big_endian.h"
13 #include "net/base/net_log.h"
14 #include "net/base/sys_addrinfo.h"
15 #include "net/base/dns_util.h"
16 #include "net/base/net_log.h"
13 #include "net/dns/dns_protocol.h" 17 #include "net/dns/dns_protocol.h"
14 #include "net/dns/dns_query.h" 18 #include "net/dns/dns_query.h"
15 #include "net/dns/dns_response.h" 19 #include "net/dns/dns_response.h"
16 #include "net/dns/dns_session.h" 20 #include "net/dns/dns_session.h"
17 #include "net/dns/dns_test_util.h" 21 #include "net/dns/dns_test_util.h"
18 #include "net/socket/socket_test_util.h" 22 #include "net/socket/socket_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
20 24
21 namespace net { 25 namespace net {
22 26
23 namespace { 27 namespace {
24 28
25 // A mock for RandIntCallback that always returns 0. 29 std::string DomainFromDot(const base::StringPiece& dotted) {
26 int ReturnZero(int min, int max) { 30 std::string out;
27 return 0; 31 EXPECT_TRUE(DNSDomainFromDot(dotted, &out));
28 } 32 return out;
33 }
34
35 class TestSocketFactory;
36
37 // A variant of MockUDPClientSocket which notifies the factory OnConnect.
38 class TestUDPClientSocket : public MockUDPClientSocket {
cbentzel 2012/01/21 03:41:16 I wonder if it would make more sense to add a peer
szym 2012/01/25 18:04:38 I'll put it on my list. I would actually like to r
39 public:
40 TestUDPClientSocket(TestSocketFactory* factory,
41 SocketDataProvider* data,
42 net::NetLog* net_log)
43 : MockUDPClientSocket(data, net_log), factory_(factory) {
44 }
45 virtual ~TestUDPClientSocket() {}
46 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE;
47 private:
48 TestSocketFactory* factory_;
49 };
50
51 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
52 class TestSocketFactory : public MockClientSocketFactory {
53 public:
54 TestSocketFactory() {}
55 virtual ~TestSocketFactory() {}
56
57 virtual DatagramClientSocket* CreateDatagramClientSocket(
58 DatagramSocket::BindType bind_type,
59 const RandIntCallback& rand_int_cb,
60 net::NetLog* net_log,
61 const net::NetLog::Source& source) OVERRIDE {
62 SocketDataProvider* data_provider = mock_data().GetNext();
63 TestUDPClientSocket* socket = new TestUDPClientSocket(this,
64 data_provider,
65 net_log);
66 data_provider->set_socket(socket);
67 return socket;
68 }
69
70 void OnConnect(const IPEndPoint& endpoint) {
71 remote_endpoints.push_back(endpoint);
72 }
73
74 std::vector<IPEndPoint> remote_endpoints;
75 };
76
77 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
78 factory_->OnConnect(endpoint);
79 return MockUDPClientSocket::Connect(endpoint);
80 }
81
82 // Helper class that holds a DnsTransaction and handles OnTransactionComplete.
83 class TransactionHelper {
84 public:
85 // If |expected_answer_count| < 0 then it is the expected net error.
86 TransactionHelper(const char* hostname,
87 uint16 qtype,
88 int expected_answer_count)
89 : hostname_(hostname),
90 qtype_(qtype),
91 expected_answer_count_(expected_answer_count),
92 cancel_in_callback_(false),
93 quit_in_callback_(false),
94 completed_(false) {
95 }
96
97 // Mark that the transaction shall be destroyed immediately upon callback.
98 void set_cancel_in_callback() {
99 cancel_in_callback_ = true;
100 }
101
102 // Mark to call MessageLoop::Quit() upon callback.
103 void set_quit_in_callback() {
104 quit_in_callback_ = true;
105 }
106
107 void StartTransaction(DnsTransactionFactory* factory) {
108 EXPECT_EQ(NULL, transaction_.get());
109 transaction_ = factory->CreateTransaction(
110 hostname_,
111 qtype_,
112 base::Bind(&TransactionHelper::OnTransactionComplete,
113 base::Unretained(this)),
114 BoundNetLog());
115 EXPECT_EQ(hostname_, transaction_->GetHostname());
116 EXPECT_EQ(qtype_, transaction_->GetType());
117 int rv = transaction_->Start();
118 if (rv != ERR_IO_PENDING) {
119 EXPECT_NE(OK, rv);
120 EXPECT_EQ(expected_answer_count_, rv);
121 }
122 }
123
124 void Cancel() {
125 ASSERT_TRUE(transaction_.get() != NULL);
126 transaction_.reset(NULL);
127 }
128
129 void OnTransactionComplete(DnsTransaction* t,
130 int rv,
131 const DnsResponse* response) {
132 EXPECT_FALSE(completed_);
133 EXPECT_EQ(transaction_.get(), t);
134
135 completed_ = true;
136
137 if (cancel_in_callback_) {
138 Cancel();
139 return;
140 }
141
142 if (expected_answer_count_ >= 0) {
143 EXPECT_EQ(OK, rv);
144 EXPECT_EQ(expected_answer_count_, response->answer_count());
145 EXPECT_EQ(qtype_, response->qtype());
146
147 DnsRecordParser parser = response->Parser();
148 DnsResourceRecord record;
149 for (int i = 0; i < expected_answer_count_; ++i) {
150 EXPECT_TRUE(parser.ParseRecord(&record));
151 }
152 EXPECT_TRUE(parser.AtEnd());
153 } else {
154 EXPECT_EQ(expected_answer_count_, rv);
155 EXPECT_EQ(NULL, response);
156 }
157
158 if (quit_in_callback_)
159 MessageLoop::current()->Quit();
160 }
161
162 bool has_completed() const {
163 return completed_;
164 }
165
166 private:
167 std::string hostname_;
168 uint16 qtype_;
169 scoped_ptr<DnsTransaction> transaction_;
170 int expected_answer_count_;
171 bool cancel_in_callback_;
172 bool quit_in_callback_;
173
174 bool completed_;
175 };
29 176
30 class DnsTransactionTest : public testing::Test { 177 class DnsTransactionTest : public testing::Test {
178 public:
179 DnsTransactionTest() : socket_factory_(NULL) {}
180
181 // Generates |nameservers| for DnsConfig.
182 void ConfigureNumServers(unsigned num_servers) {
183 DCHECK_LT(num_servers, 255u);
184 config_.nameservers.clear();
185 IPAddressNumber dns_ip;
186 {
187 bool rv = ParseIPLiteralToNumber("192.128.1.0", &dns_ip);
188 EXPECT_TRUE(rv);
189 }
190 for (unsigned i = 0; i < num_servers; ++i) {
191 dns_ip[3] = i;
192 config_.nameservers.push_back(IPEndPoint(dns_ip, kDnsPort));
193 }
194 }
195
196 // Called after fully configuring |config|.
197 void ConfigureFactory() {
198 socket_factory_ = new TestSocketFactory();
199 session_ = new DnsSession(
200 config_,
201 socket_factory_,
202 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)),
203 NULL /* NetLog */);
204 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
205 }
206
207 // Each socket used by a DnsTransaction expects only one write and zero or one
208 // reads.
209
210 // Add expected query for |dotted_name| and |qtype| with |id| and response
211 // taken verbatim from |data| of |data_length| bytes. The transaction id in
212 // |data| should equal |id|, unless testing mismatched response.
213 void AddResponse(const char* dotted_name,
cbentzel 2012/01/21 03:41:16 Why not std::string instead?
214 uint16 qtype,
215 uint16 id,
216 const char* data,
217 size_t data_length) {
218 DCHECK(socket_factory_);
219 DnsQuery* query = new DnsQuery(id, DomainFromDot(dotted_name), qtype);
220 queries_.push_back(query);
221
222 // The response is only used to hold the IOBuffer.
223 DnsResponse* response = new DnsResponse(data, data_length, 0);
224 responses_.push_back(response);
225
226 writes_.push_back(MockWrite(true,
227 query->io_buffer()->data(),
228 query->io_buffer()->size()));
229 reads_.push_back(MockRead(true,
230 response->io_buffer()->data(),
231 data_length));
232
233 transaction_ids_.push_back(id);
234 }
235
236 // Add expected query of |dotted_name| and |qtype| and no response.
237 void AddTimeout(const char* dotted_name, uint16 qtype) {
238 DCHECK(socket_factory_);
239 uint16 id = base::RandInt(0, kuint16max);
240 DnsQuery* query = new DnsQuery(id, DomainFromDot(dotted_name), qtype);
241 queries_.push_back(query);
242
243 writes_.push_back(MockWrite(true,
244 query->io_buffer()->data(),
245 query->io_buffer()->size()));
246 // Empty MockRead indicates no data.
247 reads_.push_back(MockRead());
248 transaction_ids_.push_back(id);
249 }
250
251 // Add expected query of |dotted_name| and |qtype| and response with no answer
252 // and rcode set to |rcode|.
253 void AddRcode(const char* dotted_name, uint16 qtype, int rcode) {
254 DCHECK(socket_factory_);
255 DCHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
256 uint16 id = base::RandInt(0, kuint16max);
257 DnsQuery* query = new DnsQuery(id, DomainFromDot(dotted_name), qtype);
258 queries_.push_back(query);
259
260 DnsResponse* response = new DnsResponse(query->io_buffer()->data(),
261 query->io_buffer()->size(),
262 0);
263 dns_protocol::Header* header =
264 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data());
265 header->flags |= htons(dns_protocol::kFlagResponse | rcode);
266 responses_.push_back(response);
267
268 writes_.push_back(MockWrite(true,
269 query->io_buffer()->data(),
270 query->io_buffer()->size()));
271 reads_.push_back(MockRead(true,
272 response->io_buffer()->data(),
273 query->io_buffer()->size()));
274 transaction_ids_.push_back(id);
275 }
276
277 // Call after all Add* calls to prepare data for |socket_factory_|.
278 // This separation is necessary because the |reads_| and |writes_| vectors
279 // could reallocate their data during those calls.
280 void PrepareSockets() {
281 DCHECK_EQ(writes_.size(), reads_.size());
282 for (size_t i = 0; i < writes_.size(); ++i) {
283 SocketDataProvider *data;
284 if (reads_[i].data) {
285 data = new DelayedSocketData(1, &reads_[i], 1, &writes_[i], 1);
286 } else {
287 data = new DelayedSocketData(2, NULL, 0, &writes_[i], 1);
288 }
289 socket_data_.push_back(data);
290 socket_factory_->AddSocketDataProvider(data);
291 }
292 }
293
294 // Checks if the sockets were connected in the order matching the indices in
295 // |servers|.
296 void CheckServerOrder(const unsigned* servers, size_t num_attempts) {
297 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints.size());
298 for (size_t i = 0; i < num_attempts; ++i) {
299 EXPECT_EQ(socket_factory_->remote_endpoints[i],
300 session_->config().nameservers[servers[i]]);
301 }
302 }
303
304 void SetUp() OVERRIDE {
305 // By default set one server,
306 ConfigureNumServers(1);
307 // and no retransmissions,
308 config_.attempts = 1;
309 // but long enough timeout for memory tests.
310 config_.timeout = TestTimeouts::action_timeout();
311 ConfigureFactory();
312 }
313
31 protected: 314 protected:
32 virtual void SetUp() OVERRIDE { 315 int GetNextId(int min, int max) {
33 callback_ = base::Bind(&DnsTransactionTest::OnTransactionComplete, 316 EXPECT_FALSE(transaction_ids_.empty());
34 base::Unretained(this)); 317 int id = transaction_ids_.front();
35 qname_ = std::string(kT0DnsName, arraysize(kT0DnsName)); 318 transaction_ids_.pop_front();
36 // Use long timeout to prevent timing out on slow bots. 319 EXPECT_GE(id, min);
37 ConfigureSession(base::TimeDelta::FromMilliseconds( 320 EXPECT_LE(id, max);
38 TestTimeouts::action_timeout_ms())); 321 return id;
39 } 322 }
40 323
41 void ConfigureSession(const base::TimeDelta& timeout) { 324 DnsConfig config_;
42 IPEndPoint dns_server; 325
43 bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); 326 // Holders for the buffers behind MockRead/MockWrites (they do not own them).
44 ASSERT_TRUE(rv); 327 ScopedVector<DnsQuery> queries_;
45 328 ScopedVector<DnsResponse> responses_;
46 DnsConfig config; 329
47 config.nameservers.push_back(dns_server); 330 // Holders for MockRead/MockWrites (SocketDataProvider does not own it).
48 config.attempts = 3; 331 std::vector<MockRead> reads_;
49 config.timeout = timeout; 332 std::vector<MockWrite> writes_;
50 333
51 session_ = new DnsSession(config, 334 // Holder for the socket data (MockClientSocketFactory does not own it).
52 new MockClientSocketFactory(), 335 ScopedVector<SocketDataProvider> socket_data_;
53 base::Bind(&ReturnZero), 336
54 NULL /* NetLog */); 337 std::deque<int> transaction_ids_;
55 } 338 // Owned by |session_|.
56 339 TestSocketFactory* socket_factory_;
57 void StartTransaction() {
58 transaction_.reset(new DnsTransaction(session_.get(),
59 qname_,
60 kT0Qtype,
61 callback_,
62 BoundNetLog()));
63
64 int rv0 = transaction_->Start();
65 EXPECT_EQ(ERR_IO_PENDING, rv0);
66 }
67
68 void OnTransactionComplete(DnsTransaction* transaction, int rv) {
69 EXPECT_EQ(transaction_.get(), transaction);
70 EXPECT_EQ(qname_, transaction->query()->qname().as_string());
71 EXPECT_EQ(kT0Qtype, transaction->query()->qtype());
72 rv_ = rv;
73 MessageLoop::current()->Quit();
74 }
75
76 MockClientSocketFactory& factory() {
77 return *static_cast<MockClientSocketFactory*>(session_->socket_factory());
78 }
79
80 int rv() const { return rv_; }
81
82 private:
83 DnsTransaction::ResultCallback callback_;
84 std::string qname_;
85 scoped_refptr<DnsSession> session_; 340 scoped_refptr<DnsSession> session_;
86 scoped_ptr<DnsTransaction> transaction_; 341 scoped_ptr<DnsTransactionFactory> transaction_factory_;
87
88 int rv_;
89 }; 342 };
90 343
91 TEST_F(DnsTransactionTest, NormalQueryResponseTest) { 344 TEST_F(DnsTransactionTest, Lookup) {
92 MockWrite writes0[] = { 345 AddResponse(kT0HostName,
93 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), 346 kT0Qtype,
94 arraysize(kT0QueryDatagram)) 347 0 /* id */,
348 reinterpret_cast<const char*>(kT0ResponseDatagram),
349 arraysize(kT0ResponseDatagram));
350 PrepareSockets();
351
352 TransactionHelper helper0(kT0HostName,
353 kT0Qtype,
354 arraysize(kT0IpAddresses) + 1);
355 helper0.StartTransaction(transaction_factory_.get());
356
357 // Wait until result.
358 MessageLoop::current()->RunAllPending();
359
360 EXPECT_TRUE(helper0.has_completed());
361 }
362
363 // Concurrent lookup tests assume that DnsTransaction::Start immediately
364 // consumes a socket from ClientSocketFactory.
365 TEST_F(DnsTransactionTest, ConcurrentLookup) {
366 AddResponse(kT0HostName,
367 kT0Qtype,
368 0 /* id */,
369 reinterpret_cast<const char*>(kT0ResponseDatagram),
370 arraysize(kT0ResponseDatagram));
371 AddResponse(kT1HostName,
372 kT1Qtype,
373 1 /* id */,
374 reinterpret_cast<const char*>(kT1ResponseDatagram),
375 arraysize(kT1ResponseDatagram));
376 PrepareSockets();
377
378 TransactionHelper helper0(kT0HostName,
379 kT0Qtype,
380 arraysize(kT0IpAddresses) + 1);
381 helper0.StartTransaction(transaction_factory_.get());
382 TransactionHelper helper1(kT1HostName,
383 kT1Qtype,
384 arraysize(kT1IpAddresses) + 1);
385 helper1.StartTransaction(transaction_factory_.get());
386
387 MessageLoop::current()->RunAllPending();
388
389 EXPECT_TRUE(helper0.has_completed());
390 EXPECT_TRUE(helper1.has_completed());
391 }
392
393 TEST_F(DnsTransactionTest, CancelLookup) {
394 AddResponse(kT0HostName,
395 kT0Qtype,
396 0 /* id */,
397 reinterpret_cast<const char*>(kT0ResponseDatagram),
398 arraysize(kT0ResponseDatagram));
399 AddResponse(kT1HostName,
400 kT1Qtype,
401 1 /* id */,
402 reinterpret_cast<const char*>(kT1ResponseDatagram),
403 arraysize(kT1ResponseDatagram));
404 PrepareSockets();
405
406 TransactionHelper helper0(kT0HostName,
407 kT0Qtype,
408 arraysize(kT0IpAddresses) + 1);
409 helper0.StartTransaction(transaction_factory_.get());
410 TransactionHelper helper1(kT1HostName,
411 kT1Qtype,
412 arraysize(kT1IpAddresses) + 1);
413 helper1.StartTransaction(transaction_factory_.get());
414
415 helper0.Cancel();
416
417 MessageLoop::current()->RunAllPending();
418
419 EXPECT_FALSE(helper0.has_completed());
420 EXPECT_TRUE(helper1.has_completed());
421 }
422
423 TEST_F(DnsTransactionTest, DestroyFactory) {
424 AddResponse(kT0HostName,
425 kT0Qtype,
426 0 /* id */,
427 reinterpret_cast<const char*>(kT0ResponseDatagram),
428 arraysize(kT0ResponseDatagram));
429 PrepareSockets();
430
431 TransactionHelper helper0(kT0HostName,
432 kT0Qtype,
433 arraysize(kT0IpAddresses) + 1);
434 helper0.StartTransaction(transaction_factory_.get());
435
436 // Destroying the client does not affect running requests.
437 transaction_factory_.reset(NULL);
438
439 MessageLoop::current()->RunAllPending();
440
441 EXPECT_TRUE(helper0.has_completed());
442 }
443
444 TEST_F(DnsTransactionTest, CancelFromCallback) {
445 AddResponse(kT0HostName,
446 kT0Qtype,
447 0 /* id */,
448 reinterpret_cast<const char*>(kT0ResponseDatagram),
449 arraysize(kT0ResponseDatagram));
450 PrepareSockets();
451
452 TransactionHelper helper0(kT0HostName,
453 kT0Qtype,
454 arraysize(kT0IpAddresses) + 1);
455 helper0.set_cancel_in_callback();
456 helper0.StartTransaction(transaction_factory_.get());
457
458 MessageLoop::current()->RunAllPending();
459
460 EXPECT_TRUE(helper0.has_completed());
461 }
462
463 TEST_F(DnsTransactionTest, ServerFail) {
464 AddRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
465 PrepareSockets();
466
467 TransactionHelper helper0(kT0HostName,
468 kT0Qtype,
469 ERR_DNS_SERVER_FAILED);
470 helper0.StartTransaction(transaction_factory_.get());
471
472 MessageLoop::current()->RunAllPending();
473
474 EXPECT_TRUE(helper0.has_completed());
475 }
476
477 TEST_F(DnsTransactionTest, NoDomain) {
478 AddRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
479 PrepareSockets();
480
481 TransactionHelper helper0(kT0HostName,
482 kT0Qtype,
483 ERR_NAME_NOT_RESOLVED);
484 helper0.StartTransaction(transaction_factory_.get());
485
486 MessageLoop::current()->RunAllPending();
487
488 EXPECT_TRUE(helper0.has_completed());
489 }
490
491 TEST_F(DnsTransactionTest, Timeout) {
492 config_.attempts = 3;
493 // Use short timeout to speed up the test.
494 config_.timeout = base::TimeDelta::FromMilliseconds(
495 TestTimeouts::tiny_timeout_ms());
496 ConfigureFactory();
497
498 AddTimeout(kT0HostName, kT0Qtype);
499 AddTimeout(kT0HostName, kT0Qtype);
500 AddTimeout(kT0HostName, kT0Qtype);
501 PrepareSockets();
502
503 TransactionHelper helper0(kT0HostName,
504 kT0Qtype,
505 ERR_DNS_TIMED_OUT);
506 helper0.set_quit_in_callback();
507 helper0.StartTransaction(transaction_factory_.get());
508
509 MessageLoop::current()->Run();
510
511 EXPECT_TRUE(helper0.has_completed());
512 MessageLoop::current()->AssertIdle();
513 }
514
515 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) {
516 // Test that we fallback on both server failure and timeout.
517 config_.attempts = 2;
518 // The next request should start from the next server.
519 config_.rotate = true;
520 ConfigureNumServers(3);
521 // Use short timeout to speed up the test.
522 config_.timeout = base::TimeDelta::FromMilliseconds(
523 TestTimeouts::tiny_timeout_ms());
524 ConfigureFactory();
525
526 // Responses for first request.
527 AddTimeout(kT0HostName, kT0Qtype);
528 AddRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
529 AddTimeout(kT0HostName, kT0Qtype);
530 AddRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
531 AddRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
532 // Responses for second request.
533 AddRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
534 AddRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN);
535 PrepareSockets();
536
537 TransactionHelper helper0(kT0HostName,
538 kT0Qtype,
539 ERR_NAME_NOT_RESOLVED);
540 TransactionHelper helper1(kT1HostName,
541 kT1Qtype,
542 ERR_NAME_NOT_RESOLVED);
543 helper0.set_quit_in_callback();
544 helper0.StartTransaction(transaction_factory_.get());
545
546 MessageLoop::current()->Run();
547
548 EXPECT_TRUE(helper0.has_completed());
549
550 helper1.StartTransaction(transaction_factory_.get());
551
552 MessageLoop::current()->RunAllPending();
553
554 EXPECT_TRUE(helper1.has_completed());
555
556 unsigned kOrder[] = {
557 0, 1, 2, 0, 1, // The first transaction.
558 1, 2, // The second transaction starts from the next server.
95 }; 559 };
96 560 CheckServerOrder(kOrder, arraysize(kOrder));
97 MockRead reads0[] = { 561 }
98 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), 562
99 arraysize(kT0ResponseDatagram)) 563 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {
100 }; 564 config_.ndots = 2;
101 565 config_.search.push_back("a");
102 StaticSocketDataProvider data(reads0, arraysize(reads0), 566 config_.search.push_back("b");
103 writes0, arraysize(writes0)); 567 config_.search.push_back("c");
104 factory().AddSocketDataProvider(&data); 568 config_.rotate = true;
105 569 ConfigureNumServers(2);
106 StartTransaction(); 570 ConfigureFactory();
107 MessageLoop::current()->Run(); 571
108 572 AddRcode("x.y.z", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
109 EXPECT_EQ(OK, rv()); 573 AddRcode("x.y.z.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
110 // TODO(szym): test fields of |transaction_->response()| 574 AddRcode("x.y.z.b", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
111 575 AddRcode("x.y.z.c", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
112 EXPECT_TRUE(data.at_read_eof()); 576 PrepareSockets();
113 EXPECT_TRUE(data.at_write_eof()); 577
114 } 578 TransactionHelper helper0("x.y.z",
115 579 dns_protocol::kTypeA,
116 TEST_F(DnsTransactionTest, MismatchedQueryResponseTest) { 580 ERR_NAME_NOT_RESOLVED);
117 MockWrite writes0[] = { 581
118 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), 582 helper0.StartTransaction(transaction_factory_.get());
119 arraysize(kT0QueryDatagram)) 583
120 }; 584 MessageLoop::current()->RunAllPending();
121 585
122 MockRead reads1[] = { 586 EXPECT_TRUE(helper0.has_completed());
123 MockRead(true, reinterpret_cast<const char*>(kT1ResponseDatagram), 587
124 arraysize(kT1ResponseDatagram)) 588 // Also check if suffix search causes server rotation.
125 }; 589 unsigned kOrder0[] = { 0, 1, 0, 1 };
126 590 CheckServerOrder(kOrder0, arraysize(kOrder0));
127 StaticSocketDataProvider data(reads1, arraysize(reads1), 591 }
128 writes0, arraysize(writes0)); 592
129 factory().AddSocketDataProvider(&data); 593 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {
130 594 config_.ndots = 2;
131 StartTransaction(); 595 config_.search.push_back("a");
132 MessageLoop::current()->Run(); 596 config_.search.push_back("b");
133 597 config_.search.push_back("c");
134 EXPECT_EQ(ERR_DNS_MALFORMED_RESPONSE, rv()); 598 ConfigureFactory();
135 599
136 EXPECT_TRUE(data.at_read_eof()); 600 // Responses for first transaction.
137 EXPECT_TRUE(data.at_write_eof()); 601 AddRcode("x.y.a", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
138 } 602 AddRcode("x.y.b", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
139 603 AddRcode("x.y.c", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
140 // Test that after the first timeout we do a fresh connection and if we get 604 AddRcode("x.y", dns_protocol::kTypeA, dns_protocol::kRcodeNXDOMAIN);
141 // a response on the new connection, we return it. 605 // Responses for second transaction.
142 TEST_F(DnsTransactionTest, FirstTimeoutTest) { 606 AddRcode("x", dns_protocol::kTypeAAAA, dns_protocol::kRcodeNXDOMAIN);
143 MockWrite writes0[] = { 607 PrepareSockets();
144 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), 608
145 arraysize(kT0QueryDatagram)) 609 TransactionHelper helper0("x.y",
146 }; 610 dns_protocol::kTypeA,
147 611 ERR_NAME_NOT_RESOLVED);
148 MockRead reads0[] = { 612
149 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), 613 helper0.StartTransaction(transaction_factory_.get());
150 arraysize(kT0ResponseDatagram)) 614
151 }; 615 MessageLoop::current()->RunAllPending();
152 616
153 scoped_ptr<DelayedSocketData> socket0_data( 617 EXPECT_TRUE(helper0.has_completed());
154 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); 618
155 scoped_ptr<DelayedSocketData> socket1_data( 619 // Test fully-qualified name.
156 new DelayedSocketData(0, reads0, arraysize(reads0), 620 TransactionHelper helper1("x.",
157 writes0, arraysize(writes0))); 621 dns_protocol::kTypeAAAA,
158 622 ERR_NAME_NOT_RESOLVED);
159 // Use short timeout to speed up the test. 623
160 ConfigureSession(base::TimeDelta::FromMilliseconds( 624 helper1.StartTransaction(transaction_factory_.get());
161 TestTimeouts::tiny_timeout_ms())); 625
162 factory().AddSocketDataProvider(socket0_data.get()); 626 MessageLoop::current()->RunAllPending();
163 factory().AddSocketDataProvider(socket1_data.get()); 627
164 628 EXPECT_TRUE(helper1.has_completed());
165 StartTransaction();
166
167 MessageLoop::current()->Run();
168
169 EXPECT_EQ(OK, rv());
170
171 EXPECT_TRUE(socket0_data->at_read_eof());
172 EXPECT_TRUE(socket0_data->at_write_eof());
173 EXPECT_TRUE(socket1_data->at_read_eof());
174 EXPECT_TRUE(socket1_data->at_write_eof());
175 }
176
177 // Test that after the first timeout we do a fresh connection, and after
178 // the second timeout we do another fresh connection, and if we get a
179 // response on the second connection, we return it.
180 TEST_F(DnsTransactionTest, SecondTimeoutTest) {
181 MockWrite writes0[] = {
182 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram),
183 arraysize(kT0QueryDatagram))
184 };
185
186 MockRead reads0[] = {
187 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram),
188 arraysize(kT0ResponseDatagram))
189 };
190
191 scoped_ptr<DelayedSocketData> socket0_data(
192 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0)));
193 scoped_ptr<DelayedSocketData> socket1_data(
194 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0)));
195 scoped_ptr<DelayedSocketData> socket2_data(
196 new DelayedSocketData(0, reads0, arraysize(reads0),
197 writes0, arraysize(writes0)));
198
199 // Use short timeout to speed up the test.
200 ConfigureSession(base::TimeDelta::FromMilliseconds(
201 TestTimeouts::tiny_timeout_ms()));
202 factory().AddSocketDataProvider(socket0_data.get());
203 factory().AddSocketDataProvider(socket1_data.get());
204 factory().AddSocketDataProvider(socket2_data.get());
205
206 StartTransaction();
207
208 MessageLoop::current()->Run();
209
210 EXPECT_EQ(OK, rv());
211
212 EXPECT_TRUE(socket0_data->at_read_eof());
213 EXPECT_TRUE(socket0_data->at_write_eof());
214 EXPECT_TRUE(socket1_data->at_read_eof());
215 EXPECT_TRUE(socket1_data->at_write_eof());
216 EXPECT_TRUE(socket2_data->at_read_eof());
217 EXPECT_TRUE(socket2_data->at_write_eof());
218 }
219
220 // Test that after the first timeout we do a fresh connection, and after
221 // the second timeout we do another fresh connection and after the third
222 // timeout we give up and return a timeout error.
223 TEST_F(DnsTransactionTest, ThirdTimeoutTest) {
224 MockWrite writes0[] = {
225 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram),
226 arraysize(kT0QueryDatagram))
227 };
228
229 scoped_ptr<DelayedSocketData> socket0_data(
230 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0)));
231 scoped_ptr<DelayedSocketData> socket1_data(
232 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0)));
233 scoped_ptr<DelayedSocketData> socket2_data(
234 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0)));
235
236 // Use short timeout to speed up the test.
237 ConfigureSession(base::TimeDelta::FromMilliseconds(
238 TestTimeouts::tiny_timeout_ms()));
239 factory().AddSocketDataProvider(socket0_data.get());
240 factory().AddSocketDataProvider(socket1_data.get());
241 factory().AddSocketDataProvider(socket2_data.get());
242
243 StartTransaction();
244
245 MessageLoop::current()->Run();
246
247 EXPECT_EQ(ERR_DNS_TIMED_OUT, rv());
248
249 EXPECT_TRUE(socket0_data->at_read_eof());
250 EXPECT_TRUE(socket0_data->at_write_eof());
251 EXPECT_TRUE(socket1_data->at_read_eof());
252 EXPECT_TRUE(socket1_data->at_write_eof());
253 EXPECT_TRUE(socket2_data->at_read_eof());
254 EXPECT_TRUE(socket2_data->at_write_eof());
255 } 629 }
256 630
257 } // namespace 631 } // namespace
258 632
259 } // namespace net 633 } // namespace net
634
OLDNEW
« net/dns/dns_transaction.h ('K') | « net/dns/dns_transaction.cc ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698