1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/dns/dns_transaction.h"
6
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/sys_byteorder.h"
12 #include "base/test/test_timeouts.h"
13 #include "net/base/dns_util.h"
14 #include "net/base/net_log.h"
15 #include "net/dns/dns_protocol.h"
16 #include "net/dns/dns_query.h"
17 #include "net/dns/dns_response.h"
18 #include "net/dns/dns_session.h"
19 #include "net/dns/dns_test_util.h"
20 #include "net/socket/socket_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace net {
24
25 namespace {
26
DomainFromDot(const base::StringPiece & dotted)27 std::string DomainFromDot(const base::StringPiece& dotted) {
28 std::string out;
29 EXPECT_TRUE(DNSDomainFromDot(dotted, &out));
30 return out;
31 }
32
33 // A SocketDataProvider builder.
34 class DnsSocketData {
35 public:
36 // The ctor takes parameters for the DnsQuery.
DnsSocketData(uint16 id,const char * dotted_name,uint16 qtype,IoMode mode,bool use_tcp)37 DnsSocketData(uint16 id,
38 const char* dotted_name,
39 uint16 qtype,
40 IoMode mode,
41 bool use_tcp)
42 : query_(new DnsQuery(id, DomainFromDot(dotted_name), qtype)),
43 use_tcp_(use_tcp) {
44 if (use_tcp_) {
45 scoped_ptr<uint16> length(new uint16);
46 *length = base::HostToNet16(query_->io_buffer()->size());
47 writes_.push_back(MockWrite(mode,
48 reinterpret_cast<const char*>(length.get()),
49 sizeof(uint16)));
50 lengths_.push_back(length.release());
51 }
52 writes_.push_back(MockWrite(mode,
53 query_->io_buffer()->data(),
54 query_->io_buffer()->size()));
55 }
~DnsSocketData()56 ~DnsSocketData() {}
57
58 // All responses must be added before GetProvider.
59
60 // Adds pre-built DnsResponse. |tcp_length| will be used in TCP mode only.
AddResponseWithLength(scoped_ptr<DnsResponse> response,IoMode mode,uint16 tcp_length)61 void AddResponseWithLength(scoped_ptr<DnsResponse> response, IoMode mode,
62 uint16 tcp_length) {
63 CHECK(!provider_.get());
64 if (use_tcp_) {
65 scoped_ptr<uint16> length(new uint16);
66 *length = base::HostToNet16(tcp_length);
67 reads_.push_back(MockRead(mode,
68 reinterpret_cast<const char*>(length.get()),
69 sizeof(uint16)));
70 lengths_.push_back(length.release());
71 }
72 reads_.push_back(MockRead(mode,
73 response->io_buffer()->data(),
74 response->io_buffer()->size()));
75 responses_.push_back(response.release());
76 }
77
78 // Adds pre-built DnsResponse.
AddResponse(scoped_ptr<DnsResponse> response,IoMode mode)79 void AddResponse(scoped_ptr<DnsResponse> response, IoMode mode) {
80 uint16 tcp_length = response->io_buffer()->size();
81 AddResponseWithLength(response.Pass(), mode, tcp_length);
82 }
83
84 // Adds pre-built response from |data| buffer.
AddResponseData(const uint8 * data,size_t length,IoMode mode)85 void AddResponseData(const uint8* data, size_t length, IoMode mode) {
86 CHECK(!provider_.get());
87 AddResponse(make_scoped_ptr(
88 new DnsResponse(reinterpret_cast<const char*>(data), length, 0)), mode);
89 }
90
91 // Add no-answer (RCODE only) response matching the query.
AddRcode(int rcode,IoMode mode)92 void AddRcode(int rcode, IoMode mode) {
93 scoped_ptr<DnsResponse> response(
94 new DnsResponse(query_->io_buffer()->data(),
95 query_->io_buffer()->size(),
96 0));
97 dns_protocol::Header* header =
98 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data());
99 header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode);
100 AddResponse(response.Pass(), mode);
101 }
102
103 // Add error response.
AddReadError(int error,IoMode mode)104 void AddReadError(int error, IoMode mode) {
105 reads_.push_back(MockRead(mode, error));
106 }
107
108 // Build, if needed, and return the SocketDataProvider. No new responses
109 // should be added afterwards.
GetProvider()110 SocketDataProvider* GetProvider() {
111 if (provider_.get())
112 return provider_.get();
113 // Terminate the reads with ERR_IO_PENDING to prevent overrun and default to
114 // timeout.
115 reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING));
116 provider_.reset(new DelayedSocketData(1, &reads_[0], reads_.size(),
117 &writes_[0], writes_.size()));
118 if (use_tcp_) {
119 provider_->set_connect_data(MockConnect(reads_[0].mode, OK));
120 }
121 return provider_.get();
122 }
123
query_id() const124 uint16 query_id() const {
125 return query_->id();
126 }
127
128 // Returns true if the expected query was written to the socket.
was_written() const129 bool was_written() const {
130 CHECK(provider_.get());
131 return provider_->write_index() > 0;
132 }
133
134 private:
135 scoped_ptr<DnsQuery> query_;
136 bool use_tcp_;
137 ScopedVector<uint16> lengths_;
138 ScopedVector<DnsResponse> responses_;
139 std::vector<MockWrite> writes_;
140 std::vector<MockRead> reads_;
141 scoped_ptr<DelayedSocketData> provider_;
142
143 DISALLOW_COPY_AND_ASSIGN(DnsSocketData);
144 };
145
146 class TestSocketFactory;
147
148 // A variant of MockUDPClientSocket which always fails to Connect.
149 class FailingUDPClientSocket : public MockUDPClientSocket {
150 public:
FailingUDPClientSocket(SocketDataProvider * data,net::NetLog * net_log)151 FailingUDPClientSocket(SocketDataProvider* data,
152 net::NetLog* net_log)
153 : MockUDPClientSocket(data, net_log) {
154 }
~FailingUDPClientSocket()155 virtual ~FailingUDPClientSocket() {}
Connect(const IPEndPoint & endpoint)156 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE {
157 return ERR_CONNECTION_REFUSED;
158 }
159
160 private:
161 DISALLOW_COPY_AND_ASSIGN(FailingUDPClientSocket);
162 };
163
164 // A variant of MockUDPClientSocket which notifies the factory OnConnect.
165 class TestUDPClientSocket : public MockUDPClientSocket {
166 public:
TestUDPClientSocket(TestSocketFactory * factory,SocketDataProvider * data,net::NetLog * net_log)167 TestUDPClientSocket(TestSocketFactory* factory,
168 SocketDataProvider* data,
169 net::NetLog* net_log)
170 : MockUDPClientSocket(data, net_log), factory_(factory) {
171 }
~TestUDPClientSocket()172 virtual ~TestUDPClientSocket() {}
173 virtual int Connect(const IPEndPoint& endpoint) OVERRIDE;
174
175 private:
176 TestSocketFactory* factory_;
177
178 DISALLOW_COPY_AND_ASSIGN(TestUDPClientSocket);
179 };
180
181 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
182 class TestSocketFactory : public MockClientSocketFactory {
183 public:
TestSocketFactory()184 TestSocketFactory() : fail_next_socket_(false) {}
~TestSocketFactory()185 virtual ~TestSocketFactory() {}
186
CreateDatagramClientSocket(DatagramSocket::BindType bind_type,const RandIntCallback & rand_int_cb,net::NetLog * net_log,const net::NetLog::Source & source)187 virtual scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket(
188 DatagramSocket::BindType bind_type,
189 const RandIntCallback& rand_int_cb,
190 net::NetLog* net_log,
191 const net::NetLog::Source& source) OVERRIDE {
192 if (fail_next_socket_) {
193 fail_next_socket_ = false;
194 return scoped_ptr<DatagramClientSocket>(
195 new FailingUDPClientSocket(&empty_data_, net_log));
196 }
197 SocketDataProvider* data_provider = mock_data().GetNext();
198 scoped_ptr<TestUDPClientSocket> socket(
199 new TestUDPClientSocket(this, data_provider, net_log));
200 data_provider->set_socket(socket.get());
201 return socket.PassAs<DatagramClientSocket>();
202 }
203
OnConnect(const IPEndPoint & endpoint)204 void OnConnect(const IPEndPoint& endpoint) {
205 remote_endpoints_.push_back(endpoint);
206 }
207
208 std::vector<IPEndPoint> remote_endpoints_;
209 bool fail_next_socket_;
210
211 private:
212 StaticSocketDataProvider empty_data_;
213
214 DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
215 };
216
Connect(const IPEndPoint & endpoint)217 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
218 factory_->OnConnect(endpoint);
219 return MockUDPClientSocket::Connect(endpoint);
220 }
221
222 // Helper class that holds a DnsTransaction and handles OnTransactionComplete.
223 class TransactionHelper {
224 public:
225 // If |expected_answer_count| < 0 then it is the expected net error.
TransactionHelper(const char * hostname,uint16 qtype,int expected_answer_count)226 TransactionHelper(const char* hostname,
227 uint16 qtype,
228 int expected_answer_count)
229 : hostname_(hostname),
230 qtype_(qtype),
231 expected_answer_count_(expected_answer_count),
232 cancel_in_callback_(false),
233 quit_in_callback_(false),
234 completed_(false) {
235 }
236
237 // Mark that the transaction shall be destroyed immediately upon callback.
set_cancel_in_callback()238 void set_cancel_in_callback() {
239 cancel_in_callback_ = true;
240 }
241
242 // Mark to call MessageLoop::Quit() upon callback.
set_quit_in_callback()243 void set_quit_in_callback() {
244 quit_in_callback_ = true;
245 }
246
StartTransaction(DnsTransactionFactory * factory)247 void StartTransaction(DnsTransactionFactory* factory) {
248 EXPECT_EQ(NULL, transaction_.get());
249 transaction_ = factory->CreateTransaction(
250 hostname_,
251 qtype_,
252 base::Bind(&TransactionHelper::OnTransactionComplete,
253 base::Unretained(this)),
254 BoundNetLog());
255 EXPECT_EQ(hostname_, transaction_->GetHostname());
256 EXPECT_EQ(qtype_, transaction_->GetType());
257 transaction_->Start();
258 }
259
Cancel()260 void Cancel() {
261 ASSERT_TRUE(transaction_.get() != NULL);
262 transaction_.reset(NULL);
263 }
264
OnTransactionComplete(DnsTransaction * t,int rv,const DnsResponse * response)265 void OnTransactionComplete(DnsTransaction* t,
266 int rv,
267 const DnsResponse* response) {
268 EXPECT_FALSE(completed_);
269 EXPECT_EQ(transaction_.get(), t);
270
271 completed_ = true;
272
273 if (cancel_in_callback_) {
274 Cancel();
275 return;
276 }
277
278 // Tell MessageLoop to quit now, in case any ASSERT_* fails.
279 if (quit_in_callback_)
280 base::MessageLoop::current()->Quit();
281
282 if (expected_answer_count_ >= 0) {
283 ASSERT_EQ(OK, rv);
284 ASSERT_TRUE(response != NULL);
285 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_),
286 response->answer_count());
287 EXPECT_EQ(qtype_, response->qtype());
288
289 DnsRecordParser parser = response->Parser();
290 DnsResourceRecord record;
291 for (int i = 0; i < expected_answer_count_; ++i) {
292 EXPECT_TRUE(parser.ReadRecord(&record));
293 }
294 } else {
295 EXPECT_EQ(expected_answer_count_, rv);
296 }
297 }
298
has_completed() const299 bool has_completed() const {
300 return completed_;
301 }
302
303 // Shorthands for commonly used commands.
304
Run(DnsTransactionFactory * factory)305 bool Run(DnsTransactionFactory* factory) {
306 StartTransaction(factory);
307 base::MessageLoop::current()->RunUntilIdle();
308 return has_completed();
309 }
310
311 // Use when some of the responses are timeouts.
RunUntilDone(DnsTransactionFactory * factory)312 bool RunUntilDone(DnsTransactionFactory* factory) {
313 set_quit_in_callback();
314 StartTransaction(factory);
315 base::MessageLoop::current()->Run();
316 return has_completed();
317 }
318
319 private:
320 std::string hostname_;
321 uint16 qtype_;
322 scoped_ptr<DnsTransaction> transaction_;
323 int expected_answer_count_;
324 bool cancel_in_callback_;
325 bool quit_in_callback_;
326
327 bool completed_;
328 };
329
330 class DnsTransactionTest : public testing::Test {
331 public:
DnsTransactionTest()332 DnsTransactionTest() {}
333
334 // Generates |nameservers| for DnsConfig.
ConfigureNumServers(unsigned num_servers)335 void ConfigureNumServers(unsigned num_servers) {
336 CHECK_LE(num_servers, 255u);
337 config_.nameservers.clear();
338 IPAddressNumber dns_ip;
339 {
340 bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
341 EXPECT_TRUE(rv);
342 }
343 for (unsigned i = 0; i < num_servers; ++i) {
344 dns_ip[3] = i;
345 config_.nameservers.push_back(IPEndPoint(dns_ip,
346 dns_protocol::kDefaultPort));
347 }
348 }
349
350 // Called after fully configuring |config|.
ConfigureFactory()351 void ConfigureFactory() {
352 socket_factory_.reset(new TestSocketFactory());
353 session_ = new DnsSession(
354 config_,
355 DnsSocketPool::CreateNull(socket_factory_.get()),
356 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)),
357 NULL /* NetLog */);
358 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
359 }
360
AddSocketData(scoped_ptr<DnsSocketData> data)361 void AddSocketData(scoped_ptr<DnsSocketData> data) {
362 CHECK(socket_factory_.get());
363 transaction_ids_.push_back(data->query_id());
364 socket_factory_->AddSocketDataProvider(data->GetProvider());
365 socket_data_.push_back(data.release());
366 }
367
368 // Add expected query for |dotted_name| and |qtype| with |id| and response
369 // taken verbatim from |data| of |data_length| bytes. The transaction id in
370 // |data| should equal |id|, unless testing mismatched response.
AddQueryAndResponse(uint16 id,const char * dotted_name,uint16 qtype,const uint8 * response_data,size_t response_length,IoMode mode,bool use_tcp)371 void AddQueryAndResponse(uint16 id,
372 const char* dotted_name,
373 uint16 qtype,
374 const uint8* response_data,
375 size_t response_length,
376 IoMode mode,
377 bool use_tcp) {
378 CHECK(socket_factory_.get());
379 scoped_ptr<DnsSocketData> data(
380 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
381 data->AddResponseData(response_data, response_length, mode);
382 AddSocketData(data.Pass());
383 }
384
AddAsyncQueryAndResponse(uint16 id,const char * dotted_name,uint16 qtype,const uint8 * data,size_t data_length)385 void AddAsyncQueryAndResponse(uint16 id,
386 const char* dotted_name,
387 uint16 qtype,
388 const uint8* data,
389 size_t data_length) {
390 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC,
391 false);
392 }
393
AddSyncQueryAndResponse(uint16 id,const char * dotted_name,uint16 qtype,const uint8 * data,size_t data_length)394 void AddSyncQueryAndResponse(uint16 id,
395 const char* dotted_name,
396 uint16 qtype,
397 const uint8* data,
398 size_t data_length) {
399 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS,
400 false);
401 }
402
403 // Add expected query of |dotted_name| and |qtype| and no response.
AddQueryAndTimeout(const char * dotted_name,uint16 qtype)404 void AddQueryAndTimeout(const char* dotted_name, uint16 qtype) {
405 uint16 id = base::RandInt(0, kuint16max);
406 scoped_ptr<DnsSocketData> data(
407 new DnsSocketData(id, dotted_name, qtype, ASYNC, false));
408 AddSocketData(data.Pass());
409 }
410
411 // Add expected query of |dotted_name| and |qtype| and matching response with
412 // no answer and RCODE set to |rcode|. The id will be generated randomly.
AddQueryAndRcode(const char * dotted_name,uint16 qtype,int rcode,IoMode mode,bool use_tcp)413 void AddQueryAndRcode(const char* dotted_name,
414 uint16 qtype,
415 int rcode,
416 IoMode mode,
417 bool use_tcp) {
418 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
419 uint16 id = base::RandInt(0, kuint16max);
420 scoped_ptr<DnsSocketData> data(
421 new DnsSocketData(id, dotted_name, qtype, mode, use_tcp));
422 data->AddRcode(rcode, mode);
423 AddSocketData(data.Pass());
424 }
425
AddAsyncQueryAndRcode(const char * dotted_name,uint16 qtype,int rcode)426 void AddAsyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
427 AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, false);
428 }
429
AddSyncQueryAndRcode(const char * dotted_name,uint16 qtype,int rcode)430 void AddSyncQueryAndRcode(const char* dotted_name, uint16 qtype, int rcode) {
431 AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, false);
432 }
433
434 // Checks if the sockets were connected in the order matching the indices in
435 // |servers|.
CheckServerOrder(const unsigned * servers,size_t num_attempts)436 void CheckServerOrder(const unsigned* servers, size_t num_attempts) {
437 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size());
438 for (size_t i = 0; i < num_attempts; ++i) {
439 EXPECT_EQ(socket_factory_->remote_endpoints_[i],
440 session_->config().nameservers[servers[i]]);
441 }
442 }
443
SetUp()444 virtual void SetUp() OVERRIDE {
445 // By default set one server,
446 ConfigureNumServers(1);
447 // and no retransmissions,
448 config_.attempts = 1;
449 // but long enough timeout for memory tests.
450 config_.timeout = TestTimeouts::action_timeout();
451 ConfigureFactory();
452 }
453
TearDown()454 virtual void TearDown() OVERRIDE {
455 // Check that all socket data was at least written to.
456 for (size_t i = 0; i < socket_data_.size(); ++i) {
457 EXPECT_TRUE(socket_data_[i]->was_written()) << i;
458 }
459 }
460
461 protected:
GetNextId(int min,int max)462 int GetNextId(int min, int max) {
463 EXPECT_FALSE(transaction_ids_.empty());
464 int id = transaction_ids_.front();
465 transaction_ids_.pop_front();
466 EXPECT_GE(id, min);
467 EXPECT_LE(id, max);
468 return id;
469 }
470
471 DnsConfig config_;
472
473 ScopedVector<DnsSocketData> socket_data_;
474
475 std::deque<int> transaction_ids_;
476 scoped_ptr<TestSocketFactory> socket_factory_;
477 scoped_refptr<DnsSession> session_;
478 scoped_ptr<DnsTransactionFactory> transaction_factory_;
479 };
480
TEST_F(DnsTransactionTest,Lookup)481 TEST_F(DnsTransactionTest, Lookup) {
482 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
483 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
484
485 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
486 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
487 }
488
489 // Concurrent lookup tests assume that DnsTransaction::Start immediately
490 // consumes a socket from ClientSocketFactory.
TEST_F(DnsTransactionTest,ConcurrentLookup)491 TEST_F(DnsTransactionTest, ConcurrentLookup) {
492 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
493 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
494 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
495 kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
496
497 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
498 helper0.StartTransaction(transaction_factory_.get());
499 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
500 helper1.StartTransaction(transaction_factory_.get());
501
502 base::MessageLoop::current()->RunUntilIdle();
503
504 EXPECT_TRUE(helper0.has_completed());
505 EXPECT_TRUE(helper1.has_completed());
506 }
507
TEST_F(DnsTransactionTest,CancelLookup)508 TEST_F(DnsTransactionTest, CancelLookup) {
509 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
510 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
511 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
512 kT1ResponseDatagram, arraysize(kT1ResponseDatagram));
513
514 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
515 helper0.StartTransaction(transaction_factory_.get());
516 TransactionHelper helper1(kT1HostName, kT1Qtype, kT1RecordCount);
517 helper1.StartTransaction(transaction_factory_.get());
518
519 helper0.Cancel();
520
521 base::MessageLoop::current()->RunUntilIdle();
522
523 EXPECT_FALSE(helper0.has_completed());
524 EXPECT_TRUE(helper1.has_completed());
525 }
526
TEST_F(DnsTransactionTest,DestroyFactory)527 TEST_F(DnsTransactionTest, DestroyFactory) {
528 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
529 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
530
531 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
532 helper0.StartTransaction(transaction_factory_.get());
533
534 // Destroying the client does not affect running requests.
535 transaction_factory_.reset(NULL);
536
537 base::MessageLoop::current()->RunUntilIdle();
538
539 EXPECT_TRUE(helper0.has_completed());
540 }
541
TEST_F(DnsTransactionTest,CancelFromCallback)542 TEST_F(DnsTransactionTest, CancelFromCallback) {
543 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
544 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
545
546 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
547 helper0.set_cancel_in_callback();
548 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
549 }
550
TEST_F(DnsTransactionTest,MismatchedResponseSync)551 TEST_F(DnsTransactionTest, MismatchedResponseSync) {
552 config_.attempts = 2;
553 config_.timeout = TestTimeouts::tiny_timeout();
554 ConfigureFactory();
555
556 // Attempt receives mismatched response followed by valid response.
557 scoped_ptr<DnsSocketData> data(
558 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS, false));
559 data->AddResponseData(kT1ResponseDatagram,
560 arraysize(kT1ResponseDatagram), SYNCHRONOUS);
561 data->AddResponseData(kT0ResponseDatagram,
562 arraysize(kT0ResponseDatagram), SYNCHRONOUS);
563 AddSocketData(data.Pass());
564
565 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
566 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
567 }
568
TEST_F(DnsTransactionTest,MismatchedResponseAsync)569 TEST_F(DnsTransactionTest, MismatchedResponseAsync) {
570 config_.attempts = 2;
571 config_.timeout = TestTimeouts::tiny_timeout();
572 ConfigureFactory();
573
574 // First attempt receives mismatched response followed by valid response.
575 // Second attempt times out.
576 scoped_ptr<DnsSocketData> data(
577 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, false));
578 data->AddResponseData(kT1ResponseDatagram,
579 arraysize(kT1ResponseDatagram), ASYNC);
580 data->AddResponseData(kT0ResponseDatagram,
581 arraysize(kT0ResponseDatagram), ASYNC);
582 AddSocketData(data.Pass());
583 AddQueryAndTimeout(kT0HostName, kT0Qtype);
584
585 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
586 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
587 }
588
TEST_F(DnsTransactionTest,MismatchedResponseFail)589 TEST_F(DnsTransactionTest, MismatchedResponseFail) {
590 config_.timeout = TestTimeouts::tiny_timeout();
591 ConfigureFactory();
592
593 // Attempt receives mismatched response but times out because only one attempt
594 // is allowed.
595 AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype,
596 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
597
598 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
599 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
600 }
601
TEST_F(DnsTransactionTest,ServerFail)602 TEST_F(DnsTransactionTest, ServerFail) {
603 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
604
605 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
606 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
607 }
608
TEST_F(DnsTransactionTest,NoDomain)609 TEST_F(DnsTransactionTest, NoDomain) {
610 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
611
612 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
613 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
614 }
615
TEST_F(DnsTransactionTest,Timeout)616 TEST_F(DnsTransactionTest, Timeout) {
617 config_.attempts = 3;
618 // Use short timeout to speed up the test.
619 config_.timeout = TestTimeouts::tiny_timeout();
620 ConfigureFactory();
621
622 AddQueryAndTimeout(kT0HostName, kT0Qtype);
623 AddQueryAndTimeout(kT0HostName, kT0Qtype);
624 AddQueryAndTimeout(kT0HostName, kT0Qtype);
625
626 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
627 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
628 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
629 }
630
TEST_F(DnsTransactionTest,ServerFallbackAndRotate)631 TEST_F(DnsTransactionTest, ServerFallbackAndRotate) {
632 // Test that we fallback on both server failure and timeout.
633 config_.attempts = 2;
634 // The next request should start from the next server.
635 config_.rotate = true;
636 ConfigureNumServers(3);
637 // Use short timeout to speed up the test.
638 config_.timeout = TestTimeouts::tiny_timeout();
639 ConfigureFactory();
640
641 // Responses for first request.
642 AddQueryAndTimeout(kT0HostName, kT0Qtype);
643 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
644 AddQueryAndTimeout(kT0HostName, kT0Qtype);
645 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
646 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
647 // Responses for second request.
648 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
649 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
650 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN);
651
652 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_NAME_NOT_RESOLVED);
653 TransactionHelper helper1(kT1HostName, kT1Qtype, ERR_NAME_NOT_RESOLVED);
654
655 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
656 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
657
658 unsigned kOrder[] = {
659 0, 1, 2, 0, 1, // The first transaction.
660 1, 2, 0, // The second transaction starts from the next server.
661 };
662 CheckServerOrder(kOrder, arraysize(kOrder));
663 }
664
TEST_F(DnsTransactionTest,SuffixSearchAboveNdots)665 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {
666 config_.ndots = 2;
667 config_.search.push_back("a");
668 config_.search.push_back("b");
669 config_.search.push_back("c");
670 config_.rotate = true;
671 ConfigureNumServers(2);
672 ConfigureFactory();
673
674 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
675 dns_protocol::kRcodeNXDOMAIN);
676 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
677 dns_protocol::kRcodeNXDOMAIN);
678 AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA,
679 dns_protocol::kRcodeNXDOMAIN);
680 AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA,
681 dns_protocol::kRcodeNXDOMAIN);
682
683 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
684 ERR_NAME_NOT_RESOLVED);
685
686 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
687
688 // Also check if suffix search causes server rotation.
689 unsigned kOrder0[] = { 0, 1, 0, 1 };
690 CheckServerOrder(kOrder0, arraysize(kOrder0));
691 }
692
TEST_F(DnsTransactionTest,SuffixSearchBelowNdots)693 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {
694 config_.ndots = 2;
695 config_.search.push_back("a");
696 config_.search.push_back("b");
697 config_.search.push_back("c");
698 ConfigureFactory();
699
700 // Responses for first transaction.
701 AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA,
702 dns_protocol::kRcodeNXDOMAIN);
703 AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA,
704 dns_protocol::kRcodeNXDOMAIN);
705 AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA,
706 dns_protocol::kRcodeNXDOMAIN);
707 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
708 dns_protocol::kRcodeNXDOMAIN);
709 // Responses for second transaction.
710 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
711 dns_protocol::kRcodeNXDOMAIN);
712 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
713 dns_protocol::kRcodeNXDOMAIN);
714 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
715 dns_protocol::kRcodeNXDOMAIN);
716 // Responses for third transaction.
717 AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA,
718 dns_protocol::kRcodeNXDOMAIN);
719
720 TransactionHelper helper0("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
721
722 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
723
724 // A single-label name.
725 TransactionHelper helper1("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
726
727 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
728
729 // A fully-qualified name.
730 TransactionHelper helper2("x.", dns_protocol::kTypeAAAA,
731 ERR_NAME_NOT_RESOLVED);
732
733 EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
734 }
735
TEST_F(DnsTransactionTest,EmptySuffixSearch)736 TEST_F(DnsTransactionTest, EmptySuffixSearch) {
737 // Responses for first transaction.
738 AddAsyncQueryAndRcode("x", dns_protocol::kTypeA,
739 dns_protocol::kRcodeNXDOMAIN);
740
741 // A fully-qualified name.
742 TransactionHelper helper0("x.", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
743
744 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
745
746 // A single label name is not even attempted.
747 TransactionHelper helper1("singlelabel", dns_protocol::kTypeA,
748 ERR_DNS_SEARCH_EMPTY);
749
750 helper1.Run(transaction_factory_.get());
751 EXPECT_TRUE(helper1.has_completed());
752 }
753
TEST_F(DnsTransactionTest,DontAppendToMultiLabelName)754 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) {
755 config_.search.push_back("a");
756 config_.search.push_back("b");
757 config_.search.push_back("c");
758 config_.append_to_multi_label_name = false;
759 ConfigureFactory();
760
761 // Responses for first transaction.
762 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
763 dns_protocol::kRcodeNXDOMAIN);
764 // Responses for second transaction.
765 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
766 dns_protocol::kRcodeNXDOMAIN);
767 // Responses for third transaction.
768 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
769 dns_protocol::kRcodeNXDOMAIN);
770 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
771 dns_protocol::kRcodeNXDOMAIN);
772 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
773 dns_protocol::kRcodeNXDOMAIN);
774
775 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA,
776 ERR_NAME_NOT_RESOLVED);
777 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
778
779 TransactionHelper helper1("x.y", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
780 EXPECT_TRUE(helper1.Run(transaction_factory_.get()));
781
782 TransactionHelper helper2("x", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED);
783 EXPECT_TRUE(helper2.Run(transaction_factory_.get()));
784 }
785
786 const uint8 kResponseNoData[] = {
787 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
788 // Question
789 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01,
790 // Authority section, SOA record, TTL 0x3E6
791 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6,
792 // Minimal RDATA, 18 bytes
793 0x00, 0x12,
794 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00,
799 };
800
TEST_F(DnsTransactionTest,SuffixSearchStop)801 TEST_F(DnsTransactionTest, SuffixSearchStop) {
802 config_.ndots = 2;
803 config_.search.push_back("a");
804 config_.search.push_back("b");
805 config_.search.push_back("c");
806 ConfigureFactory();
807
808 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
809 dns_protocol::kRcodeNXDOMAIN);
810 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
811 dns_protocol::kRcodeNXDOMAIN);
812 AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA,
813 kResponseNoData, arraysize(kResponseNoData));
814
815 TransactionHelper helper0("x.y.z", dns_protocol::kTypeA, 0 /* answers */);
816
817 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
818 }
819
TEST_F(DnsTransactionTest,SyncFirstQuery)820 TEST_F(DnsTransactionTest, SyncFirstQuery) {
821 config_.search.push_back("lab.ccs.neu.edu");
822 config_.search.push_back("ccs.neu.edu");
823 ConfigureFactory();
824
825 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
826 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
827
828 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
829 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
830 }
831
TEST_F(DnsTransactionTest,SyncFirstQueryWithSearch)832 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {
833 config_.search.push_back("lab.ccs.neu.edu");
834 config_.search.push_back("ccs.neu.edu");
835 ConfigureFactory();
836
837 AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype,
838 dns_protocol::kRcodeNXDOMAIN);
839 // "www.ccs.neu.edu"
840 AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
841 kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
842
843 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
844 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
845 }
846
TEST_F(DnsTransactionTest,SyncSearchQuery)847 TEST_F(DnsTransactionTest, SyncSearchQuery) {
848 config_.search.push_back("lab.ccs.neu.edu");
849 config_.search.push_back("ccs.neu.edu");
850 ConfigureFactory();
851
852 AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA,
853 dns_protocol::kRcodeNXDOMAIN);
854 AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
855 kT2ResponseDatagram, arraysize(kT2ResponseDatagram));
856
857 TransactionHelper helper0("www", kT2Qtype, kT2RecordCount);
858 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
859 }
860
TEST_F(DnsTransactionTest,ConnectFailure)861 TEST_F(DnsTransactionTest, ConnectFailure) {
862 socket_factory_->fail_next_socket_ = true;
863 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
864 TransactionHelper helper0("www.chromium.org", dns_protocol::kTypeA,
865 ERR_CONNECTION_REFUSED);
866 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
867 }
868
TEST_F(DnsTransactionTest,ConnectFailureFollowedBySuccess)869 TEST_F(DnsTransactionTest, ConnectFailureFollowedBySuccess) {
870 // Retry after server failure.
871 config_.attempts = 2;
872 ConfigureFactory();
873 // First server connection attempt fails.
874 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
875 socket_factory_->fail_next_socket_ = true;
876 // Second DNS query succeeds.
877 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
878 kT0ResponseDatagram, arraysize(kT0ResponseDatagram));
879 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
880 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
881 }
882
TEST_F(DnsTransactionTest,TCPLookup)883 TEST_F(DnsTransactionTest, TCPLookup) {
884 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
885 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
886 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
887 kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
888 ASYNC, true /* use_tcp */);
889
890 TransactionHelper helper0(kT0HostName, kT0Qtype, kT0RecordCount);
891 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
892 }
893
TEST_F(DnsTransactionTest,TCPFailure)894 TEST_F(DnsTransactionTest, TCPFailure) {
895 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
896 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
897 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
898 ASYNC, true /* use_tcp */);
899
900 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_SERVER_FAILED);
901 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
902 }
903
TEST_F(DnsTransactionTest,TCPMalformed)904 TEST_F(DnsTransactionTest, TCPMalformed) {
905 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
906 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
907 scoped_ptr<DnsSocketData> data(
908 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
909 // Valid response but length too short.
910 // This must be truncated in the question section. The DnsResponse doesn't
911 // examine the answer section until asked to parse it, so truncating it in
912 // the answer section would result in the DnsTransaction itself succeeding.
913 data->AddResponseWithLength(
914 make_scoped_ptr(
915 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
916 arraysize(kT0ResponseDatagram), 0)),
917 ASYNC,
918 static_cast<uint16>(kT0QuerySize - 1));
919 AddSocketData(data.Pass());
920
921 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_MALFORMED_RESPONSE);
922 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
923 }
924
TEST_F(DnsTransactionTest,TCPTimeout)925 TEST_F(DnsTransactionTest, TCPTimeout) {
926 config_.timeout = TestTimeouts::tiny_timeout();
927 ConfigureFactory();
928 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
929 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
930 AddSocketData(make_scoped_ptr(
931 new DnsSocketData(1 /* id */, kT0HostName, kT0Qtype, ASYNC, true)));
932
933 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_DNS_TIMED_OUT);
934 EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
935 }
936
TEST_F(DnsTransactionTest,TCPReadReturnsZeroAsync)937 TEST_F(DnsTransactionTest, TCPReadReturnsZeroAsync) {
938 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
939 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
940 scoped_ptr<DnsSocketData> data(
941 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
942 // Return all but the last byte of the response.
943 data->AddResponseWithLength(
944 make_scoped_ptr(
945 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
946 arraysize(kT0ResponseDatagram) - 1, 0)),
947 ASYNC,
948 static_cast<uint16>(arraysize(kT0ResponseDatagram)));
949 // Then return a 0-length read.
950 data->AddReadError(0, ASYNC);
951 AddSocketData(data.Pass());
952
953 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
954 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
955 }
956
TEST_F(DnsTransactionTest,TCPReadReturnsZeroSynchronous)957 TEST_F(DnsTransactionTest, TCPReadReturnsZeroSynchronous) {
958 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
959 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
960 scoped_ptr<DnsSocketData> data(
961 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
962 // Return all but the last byte of the response.
963 data->AddResponseWithLength(
964 make_scoped_ptr(
965 new DnsResponse(reinterpret_cast<const char*>(kT0ResponseDatagram),
966 arraysize(kT0ResponseDatagram) - 1, 0)),
967 SYNCHRONOUS,
968 static_cast<uint16>(arraysize(kT0ResponseDatagram)));
969 // Then return a 0-length read.
970 data->AddReadError(0, SYNCHRONOUS);
971 AddSocketData(data.Pass());
972
973 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
974 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
975 }
976
TEST_F(DnsTransactionTest,TCPConnectionClosedAsync)977 TEST_F(DnsTransactionTest, TCPConnectionClosedAsync) {
978 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
979 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
980 scoped_ptr<DnsSocketData> data(
981 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
982 data->AddReadError(ERR_CONNECTION_CLOSED, ASYNC);
983 AddSocketData(data.Pass());
984
985 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
986 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
987 }
988
TEST_F(DnsTransactionTest,TCPConnectionClosedSynchronous)989 TEST_F(DnsTransactionTest, TCPConnectionClosedSynchronous) {
990 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
991 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
992 scoped_ptr<DnsSocketData> data(
993 new DnsSocketData(0 /* id */, kT0HostName, kT0Qtype, ASYNC, true));
994 data->AddReadError(ERR_CONNECTION_CLOSED, SYNCHRONOUS);
995 AddSocketData(data.Pass());
996
997 TransactionHelper helper0(kT0HostName, kT0Qtype, ERR_CONNECTION_CLOSED);
998 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
999 }
1000
TEST_F(DnsTransactionTest,InvalidQuery)1001 TEST_F(DnsTransactionTest, InvalidQuery) {
1002 config_.timeout = TestTimeouts::tiny_timeout();
1003 ConfigureFactory();
1004
1005 TransactionHelper helper0(".", dns_protocol::kTypeA, ERR_INVALID_ARGUMENT);
1006 EXPECT_TRUE(helper0.Run(transaction_factory_.get()));
1007 }
1008
1009 } // namespace
1010
1011 } // namespace net
1012