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

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

Powered by Google App Engine
This is Rietveld 408576698