1 // Copyright 2012 The Chromium Authors
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 <stdint.h>
8
9 #include <limits>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13
14 #include "base/base64url.h"
15 #include "base/containers/circular_deque.h"
16 #include "base/functional/bind.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/numerics/safe_math.h"
19 #include "base/rand_util.h"
20 #include "base/ranges/algorithm.h"
21 #include "base/run_loop.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/sys_byteorder.h"
25 #include "base/task/single_thread_task_runner.h"
26 #include "base/test/bind.h"
27 #include "base/test/metrics/histogram_tester.h"
28 #include "base/time/time.h"
29 #include "base/values.h"
30 #include "net/base/idempotency.h"
31 #include "net/base/ip_address.h"
32 #include "net/base/port_util.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/url_util.h"
35 #include "net/cookies/cookie_access_result.h"
36 #include "net/cookies/cookie_util.h"
37 #include "net/dns/dns_config.h"
38 #include "net/dns/dns_names_util.h"
39 #include "net/dns/dns_query.h"
40 #include "net/dns/dns_response.h"
41 #include "net/dns/dns_server_iterator.h"
42 #include "net/dns/dns_session.h"
43 #include "net/dns/dns_test_util.h"
44 #include "net/dns/public/dns_over_https_config.h"
45 #include "net/dns/public/dns_over_https_server_config.h"
46 #include "net/dns/public/dns_protocol.h"
47 #include "net/dns/public/secure_dns_policy.h"
48 #include "net/dns/resolve_context.h"
49 #include "net/http/http_util.h"
50 #include "net/log/net_log.h"
51 #include "net/log/net_log_capture_mode.h"
52 #include "net/log/net_log_with_source.h"
53 #include "net/proxy_resolution/proxy_config_service_fixed.h"
54 #include "net/socket/socket_test_util.h"
55 #include "net/test/gtest_util.h"
56 #include "net/test/test_with_task_environment.h"
57 #include "net/test/url_request/url_request_failed_job.h"
58 #include "net/third_party/uri_template/uri_template.h"
59 #include "net/url_request/url_request_context.h"
60 #include "net/url_request/url_request_context_builder.h"
61 #include "net/url_request/url_request_filter.h"
62 #include "net/url_request/url_request_interceptor.h"
63 #include "net/url_request/url_request_test_util.h"
64 #include "testing/gmock/include/gmock/gmock.h"
65 #include "testing/gtest/include/gtest/gtest.h"
66 #include "third_party/abseil-cpp/absl/types/optional.h"
67
68 using net::test::IsOk;
69
70 namespace net {
71
72 namespace {
73
74 base::TimeDelta kFallbackPeriod = base::Seconds(1);
75
76 const char kMockHostname[] = "mock.http";
77
DomainFromDot(base::StringPiece dotted_name)78 std::vector<uint8_t> DomainFromDot(base::StringPiece dotted_name) {
79 absl::optional<std::vector<uint8_t>> dns_name =
80 dns_names_util::DottedNameToNetwork(dotted_name);
81 CHECK(dns_name.has_value());
82 return dns_name.value();
83 }
84
85 enum class Transport { UDP, TCP, HTTPS };
86
87 class NetLogCountingObserver : public net::NetLog::ThreadSafeObserver {
88 public:
89 NetLogCountingObserver() = default;
90
~NetLogCountingObserver()91 ~NetLogCountingObserver() override {
92 if (net_log())
93 net_log()->RemoveObserver(this);
94 }
95
OnAddEntry(const NetLogEntry & entry)96 void OnAddEntry(const NetLogEntry& entry) override {
97 ++count_;
98 if (!entry.params.empty()) {
99 dict_count_++;
100 }
101 }
102
count() const103 int count() const { return count_; }
104
dict_count() const105 int dict_count() const { return dict_count_; }
106
107 private:
108 int count_ = 0;
109 int dict_count_ = 0;
110 };
111
112 // A SocketDataProvider builder.
113 class DnsSocketData {
114 public:
115 // The ctor takes parameters for the DnsQuery.
DnsSocketData(uint16_t id,const char * dotted_name,uint16_t qtype,IoMode mode,Transport transport,const OptRecordRdata * opt_rdata=nullptr,DnsQuery::PaddingStrategy padding_strategy=DnsQuery::PaddingStrategy::NONE)116 DnsSocketData(uint16_t id,
117 const char* dotted_name,
118 uint16_t qtype,
119 IoMode mode,
120 Transport transport,
121 const OptRecordRdata* opt_rdata = nullptr,
122 DnsQuery::PaddingStrategy padding_strategy =
123 DnsQuery::PaddingStrategy::NONE)
124 : query_(std::make_unique<DnsQuery>(id,
125 DomainFromDot(dotted_name),
126 qtype,
127 opt_rdata,
128 padding_strategy)),
129 transport_(transport) {
130 if (Transport::TCP == transport_) {
131 auto length = std::make_unique<uint16_t>();
132 *length = base::HostToNet16(query_->io_buffer()->size());
133 writes_.emplace_back(mode, reinterpret_cast<const char*>(length.get()),
134 sizeof(uint16_t), num_reads_and_writes());
135 lengths_.push_back(std::move(length));
136 }
137 writes_.emplace_back(mode, query_->io_buffer()->data(),
138 query_->io_buffer()->size(), num_reads_and_writes());
139 }
140
141 DnsSocketData(const DnsSocketData&) = delete;
142 DnsSocketData& operator=(const DnsSocketData&) = delete;
143
144 ~DnsSocketData() = default;
145
ClearWrites()146 void ClearWrites() { writes_.clear(); }
147 // All responses must be added before GetProvider.
148
149 // Adds pre-built DnsResponse. |tcp_length| will be used in TCP mode only.
AddResponseWithLength(std::unique_ptr<DnsResponse> response,IoMode mode,uint16_t tcp_length)150 void AddResponseWithLength(std::unique_ptr<DnsResponse> response,
151 IoMode mode,
152 uint16_t tcp_length) {
153 CHECK(!provider_.get());
154 if (Transport::TCP == transport_) {
155 auto length = std::make_unique<uint16_t>();
156 *length = base::HostToNet16(tcp_length);
157 reads_.emplace_back(mode, reinterpret_cast<const char*>(length.get()),
158 sizeof(uint16_t), num_reads_and_writes());
159 lengths_.push_back(std::move(length));
160 }
161 reads_.emplace_back(mode, response->io_buffer()->data(),
162 response->io_buffer_size(), num_reads_and_writes());
163 responses_.push_back(std::move(response));
164 }
165
166 // Adds pre-built DnsResponse.
AddResponse(std::unique_ptr<DnsResponse> response,IoMode mode)167 void AddResponse(std::unique_ptr<DnsResponse> response, IoMode mode) {
168 uint16_t tcp_length = response->io_buffer_size();
169 AddResponseWithLength(std::move(response), mode, tcp_length);
170 }
171
172 // Adds pre-built response from |data| buffer.
AddResponseData(const uint8_t * data,size_t length,IoMode mode)173 void AddResponseData(const uint8_t* data, size_t length, IoMode mode) {
174 CHECK(!provider_.get());
175 AddResponse(std::make_unique<DnsResponse>(
176 reinterpret_cast<const char*>(data), length, 0),
177 mode);
178 }
179
180 // Adds pre-built response from |data| buffer.
AddResponseData(const uint8_t * data,size_t length,int offset,IoMode mode)181 void AddResponseData(const uint8_t* data,
182 size_t length,
183 int offset,
184 IoMode mode) {
185 CHECK(!provider_.get());
186 AddResponse(
187 std::make_unique<DnsResponse>(reinterpret_cast<const char*>(data),
188 length - offset, offset),
189 mode);
190 }
191
192 // Add no-answer (RCODE only) response matching the query.
AddRcode(int rcode,IoMode mode)193 void AddRcode(int rcode, IoMode mode) {
194 auto response = std::make_unique<DnsResponse>(
195 query_->io_buffer()->data(), query_->io_buffer()->size(), 0);
196 dns_protocol::Header* header =
197 reinterpret_cast<dns_protocol::Header*>(response->io_buffer()->data());
198 header->flags |= base::HostToNet16(dns_protocol::kFlagResponse | rcode);
199 AddResponse(std::move(response), mode);
200 }
201
202 // Add error response.
AddReadError(int error,IoMode mode)203 void AddReadError(int error, IoMode mode) {
204 reads_.emplace_back(mode, error, num_reads_and_writes());
205 }
206
207 // Build, if needed, and return the SocketDataProvider. No new responses
208 // should be added afterwards.
GetProvider()209 SequencedSocketData* GetProvider() {
210 if (provider_.get())
211 return provider_.get();
212 // Terminate the reads with ERR_IO_PENDING to prevent overrun and default to
213 // timeout.
214 if (transport_ != Transport::HTTPS) {
215 reads_.emplace_back(SYNCHRONOUS, ERR_IO_PENDING,
216 writes_.size() + reads_.size());
217 }
218 provider_ = std::make_unique<SequencedSocketData>(reads_, writes_);
219 if (Transport::TCP == transport_ || Transport::HTTPS == transport_) {
220 provider_->set_connect_data(MockConnect(reads_[0].mode, OK));
221 }
222 return provider_.get();
223 }
224
query_id() const225 uint16_t query_id() const { return query_->id(); }
226
query_buffer()227 IOBufferWithSize* query_buffer() { return query_->io_buffer(); }
228
229 private:
num_reads_and_writes() const230 size_t num_reads_and_writes() const { return reads_.size() + writes_.size(); }
231
232 std::unique_ptr<DnsQuery> query_;
233 Transport transport_;
234 std::vector<std::unique_ptr<uint16_t>> lengths_;
235 std::vector<std::unique_ptr<DnsResponse>> responses_;
236 std::vector<MockWrite> writes_;
237 std::vector<MockRead> reads_;
238 std::unique_ptr<SequencedSocketData> provider_;
239 };
240
241 class TestSocketFactory;
242
243 // A variant of MockUDPClientSocket which always fails to Connect.
244 class FailingUDPClientSocket : public MockUDPClientSocket {
245 public:
FailingUDPClientSocket(SocketDataProvider * data,net::NetLog * net_log)246 FailingUDPClientSocket(SocketDataProvider* data, net::NetLog* net_log)
247 : MockUDPClientSocket(data, net_log) {}
248
249 FailingUDPClientSocket(const FailingUDPClientSocket&) = delete;
250 FailingUDPClientSocket& operator=(const FailingUDPClientSocket&) = delete;
251
252 ~FailingUDPClientSocket() override = default;
Connect(const IPEndPoint & endpoint)253 int Connect(const IPEndPoint& endpoint) override {
254 return ERR_CONNECTION_REFUSED;
255 }
256 };
257
258 // A variant of MockUDPClientSocket which notifies the factory OnConnect.
259 class TestUDPClientSocket : public MockUDPClientSocket {
260 public:
TestUDPClientSocket(TestSocketFactory * factory,SocketDataProvider * data,net::NetLog * net_log)261 TestUDPClientSocket(TestSocketFactory* factory,
262 SocketDataProvider* data,
263 net::NetLog* net_log)
264 : MockUDPClientSocket(data, net_log), factory_(factory) {}
265
266 TestUDPClientSocket(const TestUDPClientSocket&) = delete;
267 TestUDPClientSocket& operator=(const TestUDPClientSocket&) = delete;
268
269 ~TestUDPClientSocket() override = default;
270 int Connect(const IPEndPoint& endpoint) override;
271 int ConnectAsync(const IPEndPoint& address,
272 CompletionOnceCallback callback) override;
273
274 private:
275 raw_ptr<TestSocketFactory> factory_;
276 };
277
278 // Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
279 class TestSocketFactory : public MockClientSocketFactory {
280 public:
281 TestSocketFactory() = default;
282 ~TestSocketFactory() override = default;
283
CreateDatagramClientSocket(DatagramSocket::BindType bind_type,NetLog * net_log,const NetLogSource & source)284 std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
285 DatagramSocket::BindType bind_type,
286 NetLog* net_log,
287 const NetLogSource& source) override {
288 if (fail_next_socket_) {
289 fail_next_socket_ = false;
290 return std::make_unique<FailingUDPClientSocket>(&empty_data_, net_log);
291 }
292
293 SocketDataProvider* data_provider = mock_data().GetNext();
294 auto socket =
295 std::make_unique<TestUDPClientSocket>(this, data_provider, net_log);
296
297 // Even using DEFAULT_BIND, actual sockets have been measured to very rarely
298 // repeat the same source port multiple times in a row. Need to mimic that
299 // functionality here, so DnsUdpTracker doesn't misdiagnose repeated port
300 // as low entropy.
301 if (diverse_source_ports_)
302 socket->set_source_port(next_source_port_++);
303
304 return socket;
305 }
306
OnConnect(const IPEndPoint & endpoint)307 void OnConnect(const IPEndPoint& endpoint) {
308 remote_endpoints_.emplace_back(endpoint);
309 }
310
311 struct RemoteNameserver {
RemoteNameservernet::__anona6e5b6970111::TestSocketFactory::RemoteNameserver312 explicit RemoteNameserver(IPEndPoint insecure_nameserver)
313 : insecure_nameserver(insecure_nameserver) {}
RemoteNameservernet::__anona6e5b6970111::TestSocketFactory::RemoteNameserver314 explicit RemoteNameserver(DnsOverHttpsServerConfig secure_nameserver)
315 : secure_nameserver(secure_nameserver) {}
316
317 absl::optional<IPEndPoint> insecure_nameserver;
318 absl::optional<DnsOverHttpsServerConfig> secure_nameserver;
319 };
320
321 std::vector<RemoteNameserver> remote_endpoints_;
322 bool fail_next_socket_ = false;
323 bool diverse_source_ports_ = true;
324
325 private:
326 StaticSocketDataProvider empty_data_;
327 uint16_t next_source_port_ = 123;
328 };
329
Connect(const IPEndPoint & endpoint)330 int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {
331 factory_->OnConnect(endpoint);
332 return MockUDPClientSocket::Connect(endpoint);
333 }
334
ConnectAsync(const IPEndPoint & address,CompletionOnceCallback callback)335 int TestUDPClientSocket::ConnectAsync(const IPEndPoint& address,
336 CompletionOnceCallback callback) {
337 factory_->OnConnect(address);
338 return MockUDPClientSocket::ConnectAsync(address, std::move(callback));
339 }
340
341 // Helper class that holds a DnsTransaction and handles OnTransactionComplete.
342 class TransactionHelper {
343 public:
344 // If |expected_answer_count| < 0 then it is the expected net error.
TransactionHelper(int expected_answer_count)345 explicit TransactionHelper(int expected_answer_count)
346 : expected_answer_count_(expected_answer_count) {}
347
348 // Mark that the transaction shall be destroyed immediately upon callback.
set_cancel_in_callback()349 void set_cancel_in_callback() { cancel_in_callback_ = true; }
350
StartTransaction(DnsTransactionFactory * factory,const char * hostname,uint16_t qtype,bool secure,ResolveContext * context)351 void StartTransaction(DnsTransactionFactory* factory,
352 const char* hostname,
353 uint16_t qtype,
354 bool secure,
355 ResolveContext* context) {
356 std::unique_ptr<DnsTransaction> transaction = factory->CreateTransaction(
357 hostname, qtype,
358 NetLogWithSource::Make(net::NetLog::Get(), net::NetLogSourceType::NONE),
359 secure, factory->GetSecureDnsModeForTest(), context,
360 true /* fast_timeout */);
361 transaction->SetRequestPriority(DEFAULT_PRIORITY);
362 EXPECT_EQ(qtype, transaction->GetType());
363 StartTransaction(std::move(transaction));
364 }
365
StartTransaction(std::unique_ptr<DnsTransaction> transaction)366 void StartTransaction(std::unique_ptr<DnsTransaction> transaction) {
367 EXPECT_FALSE(transaction_);
368 transaction_ = std::move(transaction);
369 qtype_ = transaction_->GetType();
370 transaction_->Start(base::BindOnce(
371 &TransactionHelper::OnTransactionComplete, base::Unretained(this)));
372 }
373
Cancel()374 void Cancel() {
375 ASSERT_TRUE(transaction_.get() != nullptr);
376 transaction_.reset(nullptr);
377 }
378
OnTransactionComplete(int rv,const DnsResponse * response)379 void OnTransactionComplete(int rv, const DnsResponse* response) {
380 EXPECT_FALSE(completed_);
381
382 completed_ = true;
383 response_ = response;
384
385 transaction_complete_run_loop_.Quit();
386
387 if (cancel_in_callback_) {
388 Cancel();
389 return;
390 }
391
392 if (response)
393 EXPECT_TRUE(response->IsValid());
394
395 if (expected_answer_count_ >= 0) {
396 ASSERT_THAT(rv, IsOk());
397 ASSERT_TRUE(response != nullptr);
398 EXPECT_EQ(static_cast<unsigned>(expected_answer_count_),
399 response->answer_count());
400 EXPECT_EQ(qtype_, response->GetSingleQType());
401
402 DnsRecordParser parser = response->Parser();
403 DnsResourceRecord record;
404 for (int i = 0; i < expected_answer_count_; ++i) {
405 EXPECT_TRUE(parser.ReadRecord(&record));
406 }
407 } else {
408 EXPECT_EQ(expected_answer_count_, rv);
409 }
410 }
411
has_completed() const412 bool has_completed() const { return completed_; }
response() const413 const DnsResponse* response() const { return response_; }
414
415 // Runs until the completion callback is called. Transaction must have already
416 // been started or this will never complete.
RunUntilComplete()417 void RunUntilComplete() {
418 DCHECK(transaction_);
419 DCHECK(!transaction_complete_run_loop_.running());
420 transaction_complete_run_loop_.Run();
421 DCHECK(has_completed());
422 }
423
424 private:
425 uint16_t qtype_ = 0;
426 std::unique_ptr<DnsTransaction> transaction_;
427 raw_ptr<const DnsResponse> response_ = nullptr;
428 int expected_answer_count_;
429 bool cancel_in_callback_ = false;
430 base::RunLoop transaction_complete_run_loop_;
431 bool completed_ = false;
432 };
433
434 // Callback that allows a test to modify HttpResponseinfo
435 // before the response is sent to the requester. This allows
436 // response headers to be changed.
437 using ResponseModifierCallback =
438 base::RepeatingCallback<void(URLRequest* request, HttpResponseInfo* info)>;
439
440 // Callback that allows the test to substitute its own implementation
441 // of URLRequestJob to handle the request.
442 using DohJobMakerCallback = base::RepeatingCallback<std::unique_ptr<
443 URLRequestJob>(URLRequest* request, SocketDataProvider* data_provider)>;
444
445 // Callback to notify that URLRequestJob::Start has been called.
446 using UrlRequestStartedCallback = base::RepeatingCallback<void()>;
447
448 // Subclass of URLRequestJob which takes a SocketDataProvider with data
449 // representing both a DNS over HTTPS query and response.
450 class URLRequestMockDohJob : public URLRequestJob, public AsyncSocket {
451 public:
URLRequestMockDohJob(URLRequest * request,SocketDataProvider * data_provider,ResponseModifierCallback response_modifier=ResponseModifierCallback (),UrlRequestStartedCallback on_start=UrlRequestStartedCallback ())452 URLRequestMockDohJob(
453 URLRequest* request,
454 SocketDataProvider* data_provider,
455 ResponseModifierCallback response_modifier = ResponseModifierCallback(),
456 UrlRequestStartedCallback on_start = UrlRequestStartedCallback())
457 : URLRequestJob(request),
458 data_provider_(data_provider),
459 response_modifier_(response_modifier),
460 on_start_(on_start) {
461 data_provider_->Initialize(this);
462 MatchQueryData(request, data_provider);
463 }
464
465 // Compare the query contained in either the POST body or the body
466 // parameter of the GET query to the write data of the SocketDataProvider.
MatchQueryData(URLRequest * request,SocketDataProvider * data_provider)467 static void MatchQueryData(URLRequest* request,
468 SocketDataProvider* data_provider) {
469 std::string decoded_query;
470 if (request->method() == "GET") {
471 std::string encoded_query;
472 EXPECT_TRUE(GetValueForKeyInQuery(request->url(), "dns", &encoded_query));
473 EXPECT_GT(encoded_query.size(), 0ul);
474
475 EXPECT_TRUE(base::Base64UrlDecode(
476 encoded_query, base::Base64UrlDecodePolicy::IGNORE_PADDING,
477 &decoded_query));
478 } else if (request->method() == "POST") {
479 EXPECT_EQ(IDEMPOTENT, request->GetIdempotency());
480 const UploadDataStream* stream = request->get_upload_for_testing();
481 auto* readers = stream->GetElementReaders();
482 EXPECT_TRUE(readers);
483 EXPECT_FALSE(readers->empty());
484 for (auto& reader : *readers) {
485 const UploadBytesElementReader* byte_reader = reader->AsBytesReader();
486 decoded_query +=
487 std::string(byte_reader->bytes(), byte_reader->length());
488 }
489 }
490
491 std::string query(decoded_query);
492 MockWriteResult result(SYNCHRONOUS, 1);
493 while (result.result > 0 && query.length() > 0) {
494 result = data_provider->OnWrite(query);
495 if (result.result > 0)
496 query = query.substr(result.result);
497 }
498 }
499
GetMockHttpsUrl(const std::string & path)500 static std::string GetMockHttpsUrl(const std::string& path) {
501 return "https://" + (kMockHostname + ("/" + path));
502 }
503
504 // URLRequestJob implementation:
Start()505 void Start() override {
506 if (on_start_)
507 on_start_.Run();
508 // Start reading asynchronously so that all error reporting and data
509 // callbacks happen as they would for network requests.
510 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
511 FROM_HERE, base::BindOnce(&URLRequestMockDohJob::StartAsync,
512 weak_factory_.GetWeakPtr()));
513 }
514
515 URLRequestMockDohJob(const URLRequestMockDohJob&) = delete;
516 URLRequestMockDohJob& operator=(const URLRequestMockDohJob&) = delete;
517
~URLRequestMockDohJob()518 ~URLRequestMockDohJob() override {
519 if (data_provider_)
520 data_provider_->DetachSocket();
521 }
522
ReadRawData(IOBuffer * buf,int buf_size)523 int ReadRawData(IOBuffer* buf, int buf_size) override {
524 if (!data_provider_)
525 return ERR_FAILED;
526 if (leftover_data_len_ > 0) {
527 int rv = DoBufferCopy(leftover_data_, leftover_data_len_, buf, buf_size);
528 return rv;
529 }
530
531 if (data_provider_->AllReadDataConsumed())
532 return 0;
533
534 MockRead read = data_provider_->OnRead();
535
536 if (read.result < ERR_IO_PENDING)
537 return read.result;
538
539 if (read.result == ERR_IO_PENDING) {
540 pending_buf_ = buf;
541 pending_buf_size_ = buf_size;
542 return ERR_IO_PENDING;
543 }
544 return DoBufferCopy(read.data, read.data_len, buf, buf_size);
545 }
546
GetResponseInfo(HttpResponseInfo * info)547 void GetResponseInfo(HttpResponseInfo* info) override {
548 // Send back mock headers.
549 std::string raw_headers;
550 raw_headers.append(
551 "HTTP/1.1 200 OK\n"
552 "Content-type: application/dns-message\n");
553 if (content_length_ > 0) {
554 raw_headers.append(base::StringPrintf("Content-Length: %1d\n",
555 static_cast<int>(content_length_)));
556 }
557 info->headers = base::MakeRefCounted<HttpResponseHeaders>(
558 HttpUtil::AssembleRawHeaders(raw_headers));
559 if (response_modifier_)
560 response_modifier_.Run(request(), info);
561 }
562
563 // AsyncSocket implementation:
OnReadComplete(const MockRead & data)564 void OnReadComplete(const MockRead& data) override {
565 EXPECT_NE(data.result, ERR_IO_PENDING);
566 if (data.result < 0)
567 return ReadRawDataComplete(data.result);
568 ReadRawDataComplete(DoBufferCopy(data.data, data.data_len, pending_buf_,
569 pending_buf_size_));
570 }
OnWriteComplete(int rv)571 void OnWriteComplete(int rv) override {}
OnConnectComplete(const MockConnect & data)572 void OnConnectComplete(const MockConnect& data) override {}
OnDataProviderDestroyed()573 void OnDataProviderDestroyed() override { data_provider_ = nullptr; }
574
575 private:
StartAsync()576 void StartAsync() {
577 if (!request_)
578 return;
579 if (content_length_)
580 set_expected_content_size(content_length_);
581 NotifyHeadersComplete();
582 }
583
DoBufferCopy(const char * data,int data_len,IOBuffer * buf,int buf_size)584 int DoBufferCopy(const char* data,
585 int data_len,
586 IOBuffer* buf,
587 int buf_size) {
588 if (data_len > buf_size) {
589 memcpy(buf->data(), data, buf_size);
590 leftover_data_ = data + buf_size;
591 leftover_data_len_ = data_len - buf_size;
592 return buf_size;
593 }
594 memcpy(buf->data(), data, data_len);
595 return data_len;
596 }
597
598 const int content_length_ = 0;
599 const char* leftover_data_;
600 int leftover_data_len_ = 0;
601 raw_ptr<SocketDataProvider> data_provider_;
602 const ResponseModifierCallback response_modifier_;
603 const UrlRequestStartedCallback on_start_;
604 raw_ptr<IOBuffer> pending_buf_;
605 int pending_buf_size_;
606
607 base::WeakPtrFactory<URLRequestMockDohJob> weak_factory_{this};
608 };
609
610 class DnsTransactionTestBase : public testing::Test {
611 public:
612 DnsTransactionTestBase() = default;
613
~DnsTransactionTestBase()614 ~DnsTransactionTestBase() override {
615 // All queued transaction IDs should be used by a transaction calling
616 // GetNextId().
617 CHECK(transaction_ids_.empty());
618 }
619
620 // Generates |nameservers| for DnsConfig.
ConfigureNumServers(size_t num_servers)621 void ConfigureNumServers(size_t num_servers) {
622 CHECK_LE(num_servers, 255u);
623 config_.nameservers.clear();
624 for (size_t i = 0; i < num_servers; ++i) {
625 config_.nameservers.emplace_back(IPAddress(192, 168, 1, i),
626 dns_protocol::kDefaultPort);
627 }
628 }
629
630 // Configures the DnsConfig DNS-over-HTTPS server(s), which either
631 // accept GET or POST requests based on use_post. If a
632 // ResponseModifierCallback is provided it will be called to construct the
633 // HTTPResponse.
ConfigureDohServers(bool use_post,size_t num_doh_servers=1,bool make_available=true)634 void ConfigureDohServers(bool use_post,
635 size_t num_doh_servers = 1,
636 bool make_available = true) {
637 GURL url(URLRequestMockDohJob::GetMockHttpsUrl("doh_test"));
638 URLRequestFilter* filter = URLRequestFilter::GetInstance();
639 filter->AddHostnameInterceptor(url.scheme(), url.host(),
640 std::make_unique<DohJobInterceptor>(this));
641 CHECK_LE(num_doh_servers, 255u);
642 std::vector<string> templates;
643 templates.reserve(num_doh_servers);
644 for (size_t i = 0; i < num_doh_servers; ++i) {
645 templates.push_back(URLRequestMockDohJob::GetMockHttpsUrl(
646 base::StringPrintf("doh_test_%zu", i)) +
647 (use_post ? "" : "{?dns}"));
648 }
649 config_.doh_config =
650 *DnsOverHttpsConfig::FromTemplatesForTesting(std::move(templates));
651 ConfigureFactory();
652
653 if (make_available) {
654 for (size_t server_index = 0; server_index < num_doh_servers;
655 ++server_index) {
656 resolve_context_->RecordServerSuccess(
657 server_index, true /* is_doh_server */, session_.get());
658 }
659 }
660 }
661
662 // Called after fully configuring |config|.
ConfigureFactory()663 void ConfigureFactory() {
664 session_ = base::MakeRefCounted<DnsSession>(
665 config_,
666 base::BindRepeating(&DnsTransactionTestBase::GetNextId,
667 base::Unretained(this)),
668 nullptr /* NetLog */);
669 resolve_context_->InvalidateCachesAndPerSessionData(
670 session_.get(), false /* network_change */);
671 transaction_factory_ = DnsTransactionFactory::CreateFactory(session_.get());
672 }
673
AddSocketData(std::unique_ptr<DnsSocketData> data,bool enqueue_transaction_id=true)674 void AddSocketData(std::unique_ptr<DnsSocketData> data,
675 bool enqueue_transaction_id = true) {
676 CHECK(socket_factory_.get());
677 if (enqueue_transaction_id)
678 transaction_ids_.push_back(data->query_id());
679 socket_factory_->AddSocketDataProvider(data->GetProvider());
680 socket_data_.push_back(std::move(data));
681 }
682
AddQueryAndResponseNoWrite(uint16_t id,const char * dotted_name,uint16_t qtype,IoMode mode,Transport transport,const OptRecordRdata * opt_rdata=nullptr,DnsQuery::PaddingStrategy padding_strategy=DnsQuery::PaddingStrategy::NONE)683 void AddQueryAndResponseNoWrite(uint16_t id,
684 const char* dotted_name,
685 uint16_t qtype,
686 IoMode mode,
687 Transport transport,
688 const OptRecordRdata* opt_rdata = nullptr,
689 DnsQuery::PaddingStrategy padding_strategy =
690 DnsQuery::PaddingStrategy::NONE) {
691 CHECK(socket_factory_.get());
692 auto data = std::make_unique<DnsSocketData>(
693 id, dotted_name, qtype, mode, transport, opt_rdata, padding_strategy);
694 data->ClearWrites();
695 AddSocketData(std::move(data), true);
696 }
697
698 // Add expected query for |dotted_name| and |qtype| with |id| and response
699 // taken verbatim from |data| of |data_length| bytes. The transaction id in
700 // |data| should equal |id|, unless testing mismatched response.
AddQueryAndResponse(uint16_t id,const char * dotted_name,uint16_t qtype,const uint8_t * response_data,size_t response_length,IoMode mode,Transport transport,const OptRecordRdata * opt_rdata=nullptr,DnsQuery::PaddingStrategy padding_strategy=DnsQuery::PaddingStrategy::NONE,bool enqueue_transaction_id=true)701 void AddQueryAndResponse(uint16_t id,
702 const char* dotted_name,
703 uint16_t qtype,
704 const uint8_t* response_data,
705 size_t response_length,
706 IoMode mode,
707 Transport transport,
708 const OptRecordRdata* opt_rdata = nullptr,
709 DnsQuery::PaddingStrategy padding_strategy =
710 DnsQuery::PaddingStrategy::NONE,
711 bool enqueue_transaction_id = true) {
712 CHECK(socket_factory_.get());
713 auto data = std::make_unique<DnsSocketData>(
714 id, dotted_name, qtype, mode, transport, opt_rdata, padding_strategy);
715 data->AddResponseData(response_data, response_length, mode);
716 AddSocketData(std::move(data), enqueue_transaction_id);
717 }
718
AddQueryAndErrorResponse(uint16_t id,const char * dotted_name,uint16_t qtype,int error,IoMode mode,Transport transport,const OptRecordRdata * opt_rdata=nullptr,DnsQuery::PaddingStrategy padding_strategy=DnsQuery::PaddingStrategy::NONE,bool enqueue_transaction_id=true)719 void AddQueryAndErrorResponse(uint16_t id,
720 const char* dotted_name,
721 uint16_t qtype,
722 int error,
723 IoMode mode,
724 Transport transport,
725 const OptRecordRdata* opt_rdata = nullptr,
726 DnsQuery::PaddingStrategy padding_strategy =
727 DnsQuery::PaddingStrategy::NONE,
728 bool enqueue_transaction_id = true) {
729 CHECK(socket_factory_.get());
730 auto data = std::make_unique<DnsSocketData>(
731 id, dotted_name, qtype, mode, transport, opt_rdata, padding_strategy);
732 data->AddReadError(error, mode);
733 AddSocketData(std::move(data), enqueue_transaction_id);
734 }
735
AddAsyncQueryAndResponse(uint16_t id,const char * dotted_name,uint16_t qtype,const uint8_t * data,size_t data_length,const OptRecordRdata * opt_rdata=nullptr)736 void AddAsyncQueryAndResponse(uint16_t id,
737 const char* dotted_name,
738 uint16_t qtype,
739 const uint8_t* data,
740 size_t data_length,
741 const OptRecordRdata* opt_rdata = nullptr) {
742 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, ASYNC,
743 Transport::UDP, opt_rdata);
744 }
745
AddSyncQueryAndResponse(uint16_t id,const char * dotted_name,uint16_t qtype,const uint8_t * data,size_t data_length,const OptRecordRdata * opt_rdata=nullptr)746 void AddSyncQueryAndResponse(uint16_t id,
747 const char* dotted_name,
748 uint16_t qtype,
749 const uint8_t* data,
750 size_t data_length,
751 const OptRecordRdata* opt_rdata = nullptr) {
752 AddQueryAndResponse(id, dotted_name, qtype, data, data_length, SYNCHRONOUS,
753 Transport::UDP, opt_rdata);
754 }
755
756 // Add expected query of |dotted_name| and |qtype| and no response.
AddHangingQuery(const char * dotted_name,uint16_t qtype,DnsQuery::PaddingStrategy padding_strategy=DnsQuery::PaddingStrategy::NONE,uint16_t id=base::RandInt (0,std::numeric_limits<uint16_t>::max ()),bool enqueue_transaction_id=true)757 void AddHangingQuery(
758 const char* dotted_name,
759 uint16_t qtype,
760 DnsQuery::PaddingStrategy padding_strategy =
761 DnsQuery::PaddingStrategy::NONE,
762 uint16_t id = base::RandInt(0, std::numeric_limits<uint16_t>::max()),
763 bool enqueue_transaction_id = true) {
764 auto data = std::make_unique<DnsSocketData>(
765 id, dotted_name, qtype, ASYNC, Transport::UDP, nullptr /* opt_rdata */,
766 padding_strategy);
767 AddSocketData(std::move(data), enqueue_transaction_id);
768 }
769
770 // Add expected query of |dotted_name| and |qtype| and matching response with
771 // no answer and RCODE set to |rcode|. The id will be generated randomly.
AddQueryAndRcode(const char * dotted_name,uint16_t qtype,int rcode,IoMode mode,Transport trans,DnsQuery::PaddingStrategy padding_strategy=DnsQuery::PaddingStrategy::NONE,uint16_t id=base::RandInt (0,std::numeric_limits<uint16_t>::max ()),bool enqueue_transaction_id=true)772 void AddQueryAndRcode(
773 const char* dotted_name,
774 uint16_t qtype,
775 int rcode,
776 IoMode mode,
777 Transport trans,
778 DnsQuery::PaddingStrategy padding_strategy =
779 DnsQuery::PaddingStrategy::NONE,
780 uint16_t id = base::RandInt(0, std::numeric_limits<uint16_t>::max()),
781 bool enqueue_transaction_id = true) {
782 CHECK_NE(dns_protocol::kRcodeNOERROR, rcode);
783 auto data = std::make_unique<DnsSocketData>(id, dotted_name, qtype, mode,
784 trans, nullptr /* opt_rdata */,
785 padding_strategy);
786 data->AddRcode(rcode, mode);
787 AddSocketData(std::move(data), enqueue_transaction_id);
788 }
789
AddAsyncQueryAndRcode(const char * dotted_name,uint16_t qtype,int rcode)790 void AddAsyncQueryAndRcode(const char* dotted_name,
791 uint16_t qtype,
792 int rcode) {
793 AddQueryAndRcode(dotted_name, qtype, rcode, ASYNC, Transport::UDP);
794 }
795
AddSyncQueryAndRcode(const char * dotted_name,uint16_t qtype,int rcode)796 void AddSyncQueryAndRcode(const char* dotted_name,
797 uint16_t qtype,
798 int rcode) {
799 AddQueryAndRcode(dotted_name, qtype, rcode, SYNCHRONOUS, Transport::UDP);
800 }
801
802 // Checks if the sockets were connected in the order matching the indices in
803 // |servers|.
CheckServerOrder(const size_t * servers,size_t num_attempts)804 void CheckServerOrder(const size_t* servers, size_t num_attempts) {
805 ASSERT_EQ(num_attempts, socket_factory_->remote_endpoints_.size());
806 auto num_insecure_nameservers = session_->config().nameservers.size();
807 for (size_t i = 0; i < num_attempts; ++i) {
808 if (servers[i] < num_insecure_nameservers) {
809 // Check insecure server match.
810 EXPECT_EQ(
811 socket_factory_->remote_endpoints_[i].insecure_nameserver.value(),
812 session_->config().nameservers[servers[i]]);
813 } else {
814 // Check secure server match.
815 EXPECT_EQ(
816 socket_factory_->remote_endpoints_[i].secure_nameserver.value(),
817 session_->config()
818 .doh_config.servers()[servers[i] - num_insecure_nameservers]);
819 }
820 }
821 }
822
MaybeInterceptRequest(URLRequest * request)823 std::unique_ptr<URLRequestJob> MaybeInterceptRequest(URLRequest* request) {
824 // If the path indicates a redirect, skip checking the list of
825 // configured servers, because it won't be there and we still want
826 // to handle it.
827 bool server_found = request->url().path() == "/redirect-destination";
828 for (auto server : config_.doh_config.servers()) {
829 if (server_found)
830 break;
831 std::string url_base =
832 GetURLFromTemplateWithoutParameters(server.server_template());
833 if (server.use_post() && request->method() == "POST") {
834 if (url_base == request->url().spec()) {
835 server_found = true;
836 socket_factory_->remote_endpoints_.emplace_back(server);
837 }
838 } else if (!server.use_post() && request->method() == "GET") {
839 std::string prefix = url_base + "?dns=";
840 auto mispair = base::ranges::mismatch(prefix, request->url().spec());
841 if (mispair.first == prefix.end()) {
842 server_found = true;
843 socket_factory_->remote_endpoints_.emplace_back(server);
844 }
845 }
846 }
847 EXPECT_TRUE(server_found);
848
849 EXPECT_TRUE(
850 request->isolation_info().network_isolation_key().IsTransient());
851
852 // All DoH requests for the same ResolveContext should use the same
853 // IsolationInfo, so network objects like sockets can be reused between
854 // requests.
855 if (!expect_multiple_isolation_infos_) {
856 if (!isolation_info_) {
857 isolation_info_ =
858 std::make_unique<IsolationInfo>(request->isolation_info());
859 } else {
860 EXPECT_TRUE(
861 isolation_info_->IsEqualForTesting(request->isolation_info()));
862 }
863 }
864
865 EXPECT_FALSE(request->allow_credentials());
866 EXPECT_EQ(SecureDnsPolicy::kBootstrap, request->secure_dns_policy());
867
868 std::string accept;
869 EXPECT_TRUE(request->extra_request_headers().GetHeader("Accept", &accept));
870 EXPECT_EQ(accept, "application/dns-message");
871
872 std::string language;
873 EXPECT_TRUE(request->extra_request_headers().GetHeader("Accept-Language",
874 &language));
875 EXPECT_EQ(language, "*");
876
877 std::string user_agent;
878 EXPECT_TRUE(
879 request->extra_request_headers().GetHeader("User-Agent", &user_agent));
880 EXPECT_EQ(user_agent, "Chrome");
881
882 SocketDataProvider* provider = socket_factory_->mock_data().GetNext();
883
884 if (doh_job_maker_)
885 return doh_job_maker_.Run(request, provider);
886
887 return std::make_unique<URLRequestMockDohJob>(
888 request, provider, response_modifier_, on_start_);
889 }
890
891 class DohJobInterceptor : public URLRequestInterceptor {
892 public:
DohJobInterceptor(DnsTransactionTestBase * test)893 explicit DohJobInterceptor(DnsTransactionTestBase* test) : test_(test) {}
894
895 DohJobInterceptor(const DohJobInterceptor&) = delete;
896 DohJobInterceptor& operator=(const DohJobInterceptor&) = delete;
897
898 ~DohJobInterceptor() override = default;
899
900 // URLRequestInterceptor implementation:
MaybeInterceptRequest(URLRequest * request) const901 std::unique_ptr<URLRequestJob> MaybeInterceptRequest(
902 URLRequest* request) const override {
903 return test_->MaybeInterceptRequest(request);
904 }
905
906 private:
907 raw_ptr<DnsTransactionTestBase> test_;
908 };
909
SetResponseModifierCallback(ResponseModifierCallback response_modifier)910 void SetResponseModifierCallback(ResponseModifierCallback response_modifier) {
911 response_modifier_ = response_modifier;
912 }
913
SetDohJobMakerCallback(DohJobMakerCallback doh_job_maker)914 void SetDohJobMakerCallback(DohJobMakerCallback doh_job_maker) {
915 doh_job_maker_ = doh_job_maker;
916 }
917
SetUrlRequestStartedCallback(UrlRequestStartedCallback on_start)918 void SetUrlRequestStartedCallback(UrlRequestStartedCallback on_start) {
919 on_start_ = on_start;
920 }
921
SetUp()922 void SetUp() override {
923 // By default set one server,
924 ConfigureNumServers(1);
925 // and no retransmissions,
926 config_.attempts = 1;
927 // and an arbitrary fallback period.
928 config_.fallback_period = kFallbackPeriod;
929 auto context_builder = CreateTestURLRequestContextBuilder();
930 socket_factory_ = std::make_unique<TestSocketFactory>();
931 context_builder->set_client_socket_factory_for_testing(
932 socket_factory_.get());
933 request_context_ = context_builder->Build();
934 resolve_context_ = std::make_unique<ResolveContext>(
935 request_context_.get(), false /* enable_caching */);
936
937 ConfigureFactory();
938 }
939
TearDown()940 void TearDown() override {
941 // Check that all socket data was at least written to.
942 for (size_t i = 0; i < socket_data_.size(); ++i) {
943 EXPECT_TRUE(socket_data_[i]->GetProvider()->AllWriteDataConsumed()) << i;
944 }
945
946 URLRequestFilter* filter = URLRequestFilter::GetInstance();
947 filter->ClearHandlers();
948 }
949
set_expect_multiple_isolation_infos(bool expect_multiple_isolation_infos)950 void set_expect_multiple_isolation_infos(
951 bool expect_multiple_isolation_infos) {
952 expect_multiple_isolation_infos_ = expect_multiple_isolation_infos;
953 }
954
955 protected:
GetNextId(int min,int max)956 int GetNextId(int min, int max) {
957 EXPECT_FALSE(transaction_ids_.empty());
958 int id = transaction_ids_.front();
959 transaction_ids_.pop_front();
960 EXPECT_GE(id, min);
961 EXPECT_LE(id, max);
962 return id;
963 }
964
965 DnsConfig config_;
966
967 std::vector<std::unique_ptr<DnsSocketData>> socket_data_;
968
969 base::circular_deque<int> transaction_ids_;
970 std::unique_ptr<TestSocketFactory> socket_factory_;
971 std::unique_ptr<URLRequestContext> request_context_;
972 std::unique_ptr<ResolveContext> resolve_context_;
973 scoped_refptr<DnsSession> session_;
974 std::unique_ptr<DnsTransactionFactory> transaction_factory_;
975 ResponseModifierCallback response_modifier_;
976 UrlRequestStartedCallback on_start_;
977 DohJobMakerCallback doh_job_maker_;
978
979 // Whether multiple IsolationInfos should be expected (due to there being
980 // multiple RequestContexts in use).
981 bool expect_multiple_isolation_infos_ = false;
982
983 // IsolationInfo used by DoH requests. Populated on first DoH request, and
984 // compared to IsolationInfo used by all subsequent requests, unless
985 // |expect_multiple_isolation_infos_| is true.
986 std::unique_ptr<IsolationInfo> isolation_info_;
987 };
988
989 class DnsTransactionTest : public DnsTransactionTestBase,
990 public WithTaskEnvironment {
991 public:
992 DnsTransactionTest() = default;
993 ~DnsTransactionTest() override = default;
994 };
995
996 class DnsTransactionTestWithMockTime : public DnsTransactionTestBase,
997 public WithTaskEnvironment {
998 protected:
DnsTransactionTestWithMockTime()999 DnsTransactionTestWithMockTime()
1000 : WithTaskEnvironment(
1001 base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
1002 ~DnsTransactionTestWithMockTime() override = default;
1003 };
1004
TEST_F(DnsTransactionTest,Lookup)1005 TEST_F(DnsTransactionTest, Lookup) {
1006 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1007 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1008
1009 TransactionHelper helper0(kT0RecordCount);
1010 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1011 false /* secure */, resolve_context_.get());
1012 helper0.RunUntilComplete();
1013 }
1014
TEST_F(DnsTransactionTest,LookupWithLog)1015 TEST_F(DnsTransactionTest, LookupWithLog) {
1016 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1017 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1018
1019 TransactionHelper helper0(kT0RecordCount);
1020 NetLogCountingObserver observer;
1021 NetLog::Get()->AddObserver(&observer, NetLogCaptureMode::kEverything);
1022 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1023 false /* secure */, resolve_context_.get());
1024 helper0.RunUntilComplete();
1025 EXPECT_EQ(observer.count(), 6);
1026 EXPECT_EQ(observer.dict_count(), 4);
1027 }
1028
TEST_F(DnsTransactionTest,LookupWithEDNSOption)1029 TEST_F(DnsTransactionTest, LookupWithEDNSOption) {
1030 OptRecordRdata expected_opt_rdata;
1031
1032 transaction_factory_->AddEDNSOption(
1033 OptRecordRdata::UnknownOpt::CreateForTesting(123, "\xbe\xef"));
1034 expected_opt_rdata.AddOpt(
1035 OptRecordRdata::UnknownOpt::CreateForTesting(123, "\xbe\xef"));
1036
1037 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1038 kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1039 &expected_opt_rdata);
1040
1041 TransactionHelper helper0(kT0RecordCount);
1042 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1043 false /* secure */, resolve_context_.get());
1044 helper0.RunUntilComplete();
1045 }
1046
TEST_F(DnsTransactionTest,LookupWithMultipleEDNSOptions)1047 TEST_F(DnsTransactionTest, LookupWithMultipleEDNSOptions) {
1048 OptRecordRdata expected_opt_rdata;
1049
1050 std::vector<std::pair<uint16_t, std::string>> params = {
1051 // Two options with the same code, to check that both are included.
1052 std::pair<uint16_t, std::string>(1, "\xde\xad"),
1053 std::pair<uint16_t, std::string>(1, "\xbe\xef"),
1054 // Try a different code and different length of data.
1055 std::pair<uint16_t, std::string>(2, "\xff")};
1056
1057 for (auto& param : params) {
1058 transaction_factory_->AddEDNSOption(
1059 OptRecordRdata::UnknownOpt::CreateForTesting(param.first,
1060 param.second));
1061 expected_opt_rdata.AddOpt(OptRecordRdata::UnknownOpt::CreateForTesting(
1062 param.first, param.second));
1063 }
1064
1065 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1066 kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1067 &expected_opt_rdata);
1068
1069 TransactionHelper helper0(kT0RecordCount);
1070 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1071 false /* secure */, resolve_context_.get());
1072 helper0.RunUntilComplete();
1073 }
1074
1075 // Concurrent lookup tests assume that DnsTransaction::Start immediately
1076 // consumes a socket from ClientSocketFactory.
TEST_F(DnsTransactionTest,ConcurrentLookup)1077 TEST_F(DnsTransactionTest, ConcurrentLookup) {
1078 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1079 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1080 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
1081 kT1ResponseDatagram, std::size(kT1ResponseDatagram));
1082
1083 TransactionHelper helper0(kT0RecordCount);
1084 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1085 false /* secure */, resolve_context_.get());
1086 TransactionHelper helper1(kT1RecordCount);
1087 helper1.StartTransaction(transaction_factory_.get(), kT1HostName, kT1Qtype,
1088 false /* secure */, resolve_context_.get());
1089
1090 base::RunLoop().RunUntilIdle();
1091
1092 EXPECT_TRUE(helper0.has_completed());
1093 EXPECT_TRUE(helper1.has_completed());
1094 }
1095
TEST_F(DnsTransactionTest,CancelLookup)1096 TEST_F(DnsTransactionTest, CancelLookup) {
1097 AddQueryAndResponseNoWrite(0 /* id */, kT0HostName, kT0Qtype, ASYNC,
1098 Transport::UDP, nullptr);
1099
1100 AddAsyncQueryAndResponse(1 /* id */, kT1HostName, kT1Qtype,
1101 kT1ResponseDatagram, std::size(kT1ResponseDatagram));
1102
1103 TransactionHelper helper0(kT0RecordCount);
1104 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1105 false /* secure */, resolve_context_.get());
1106 TransactionHelper helper1(kT1RecordCount);
1107 helper1.StartTransaction(transaction_factory_.get(), kT1HostName, kT1Qtype,
1108 false /* secure */, resolve_context_.get());
1109
1110 helper0.Cancel();
1111
1112 base::RunLoop().RunUntilIdle();
1113
1114 EXPECT_FALSE(helper0.has_completed());
1115 EXPECT_TRUE(helper1.has_completed());
1116 }
1117
TEST_F(DnsTransactionTest,DestroyFactory)1118 TEST_F(DnsTransactionTest, DestroyFactory) {
1119 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1120 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1121
1122 TransactionHelper helper0(kT0RecordCount);
1123 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1124 false /* secure */, resolve_context_.get());
1125
1126 // Destroying the client does not affect running requests.
1127 transaction_factory_.reset(nullptr);
1128
1129 helper0.RunUntilComplete();
1130 }
1131
TEST_F(DnsTransactionTest,CancelFromCallback)1132 TEST_F(DnsTransactionTest, CancelFromCallback) {
1133 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1134 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1135
1136 TransactionHelper helper0(kT0RecordCount);
1137 helper0.set_cancel_in_callback();
1138
1139 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1140 false /* secure */, resolve_context_.get());
1141 helper0.RunUntilComplete();
1142 }
1143
TEST_F(DnsTransactionTest,MismatchedResponseSync)1144 TEST_F(DnsTransactionTest, MismatchedResponseSync) {
1145 config_.attempts = 2;
1146 ConfigureFactory();
1147
1148 // First attempt receives mismatched response synchronously.
1149 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
1150 SYNCHRONOUS, Transport::UDP);
1151 data->AddResponseData(kT1ResponseDatagram, std::size(kT1ResponseDatagram),
1152 SYNCHRONOUS);
1153 AddSocketData(std::move(data));
1154
1155 // Second attempt receives valid response synchronously.
1156 auto data1 = std::make_unique<DnsSocketData>(
1157 0 /* id */, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::UDP);
1158 data1->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1159 SYNCHRONOUS);
1160 AddSocketData(std::move(data1));
1161
1162 TransactionHelper helper0(kT0RecordCount);
1163 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1164 false /* secure */, resolve_context_.get());
1165 helper0.RunUntilComplete();
1166 }
1167
TEST_F(DnsTransactionTest,MismatchedResponseAsync)1168 TEST_F(DnsTransactionTest, MismatchedResponseAsync) {
1169 config_.attempts = 2;
1170 ConfigureFactory();
1171
1172 // First attempt receives mismatched response asynchronously.
1173 auto data0 = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName,
1174 kT0Qtype, ASYNC, Transport::UDP);
1175 data0->AddResponseData(kT1ResponseDatagram, std::size(kT1ResponseDatagram),
1176 ASYNC);
1177 AddSocketData(std::move(data0));
1178
1179 // Second attempt receives valid response asynchronously.
1180 auto data1 = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName,
1181 kT0Qtype, ASYNC, Transport::UDP);
1182 data1->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1183 ASYNC);
1184 AddSocketData(std::move(data1));
1185
1186 TransactionHelper helper0(kT0RecordCount);
1187 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1188 false /* secure */, resolve_context_.get());
1189 helper0.RunUntilComplete();
1190 }
1191
1192 // Test that responses are not accepted when only the response ID mismatches.
1193 // Tests against incorrect transaction ID validation, which is anti-pattern #1
1194 // from the "NAME:WRECK" report:
1195 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST_F(DnsTransactionTest,MismatchedResponseFail)1196 TEST_F(DnsTransactionTest, MismatchedResponseFail) {
1197 ConfigureFactory();
1198
1199 // Attempt receives mismatched response and fails because only one attempt is
1200 // allowed.
1201 AddAsyncQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype,
1202 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1203
1204 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
1205 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1206 false /* secure */, resolve_context_.get());
1207 helper0.RunUntilComplete();
1208 }
1209
TEST_F(DnsTransactionTest,MismatchedResponseNxdomain)1210 TEST_F(DnsTransactionTest, MismatchedResponseNxdomain) {
1211 config_.attempts = 2;
1212 ConfigureFactory();
1213
1214 // First attempt receives mismatched response followed by valid NXDOMAIN
1215 // response.
1216 // Second attempt receives valid NXDOMAIN response.
1217 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
1218 SYNCHRONOUS, Transport::UDP);
1219 data->AddResponseData(kT1ResponseDatagram, std::size(kT1ResponseDatagram),
1220 SYNCHRONOUS);
1221 data->AddRcode(dns_protocol::kRcodeNXDOMAIN, ASYNC);
1222 AddSocketData(std::move(data));
1223 AddSyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
1224
1225 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1226 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1227 false /* secure */, resolve_context_.get());
1228 helper0.RunUntilComplete();
1229 }
1230
1231 // This is a regression test for https://crbug.com/1410442.
TEST_F(DnsTransactionTest,ZeroSizeResponseAsync)1232 TEST_F(DnsTransactionTest, ZeroSizeResponseAsync) {
1233 config_.attempts = 2;
1234 ConfigureFactory();
1235
1236 // First attempt receives zero size response asynchronously.
1237 auto data0 = std::make_unique<DnsSocketData>(/*id=*/0, kT0HostName, kT0Qtype,
1238 ASYNC, Transport::UDP);
1239 data0->AddReadError(0, ASYNC);
1240 AddSocketData(std::move(data0));
1241
1242 // Second attempt receives valid response asynchronously.
1243 auto data1 = std::make_unique<DnsSocketData>(/*id=*/0, kT0HostName, kT0Qtype,
1244 ASYNC, Transport::UDP);
1245 data1->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1246 ASYNC);
1247 AddSocketData(std::move(data1));
1248
1249 TransactionHelper helper0(kT0RecordCount);
1250 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1251 /*secure=*/false, resolve_context_.get());
1252 helper0.RunUntilComplete();
1253 }
1254
TEST_F(DnsTransactionTest,ServerFail)1255 TEST_F(DnsTransactionTest, ServerFail) {
1256 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
1257
1258 TransactionHelper helper0(ERR_DNS_SERVER_FAILED);
1259 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1260 false /* secure */, resolve_context_.get());
1261 helper0.RunUntilComplete();
1262
1263 ASSERT_NE(helper0.response(), nullptr);
1264 EXPECT_EQ(helper0.response()->rcode(), dns_protocol::kRcodeSERVFAIL);
1265 }
1266
TEST_F(DnsTransactionTest,NoDomain)1267 TEST_F(DnsTransactionTest, NoDomain) {
1268 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
1269
1270 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1271 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1272 false /* secure */, resolve_context_.get());
1273 helper0.RunUntilComplete();
1274 }
1275
TEST_F(DnsTransactionTestWithMockTime,Timeout_FastTimeout)1276 TEST_F(DnsTransactionTestWithMockTime, Timeout_FastTimeout) {
1277 config_.attempts = 3;
1278 ConfigureFactory();
1279
1280 AddHangingQuery(kT0HostName, kT0Qtype);
1281 AddHangingQuery(kT0HostName, kT0Qtype);
1282 AddHangingQuery(kT0HostName, kT0Qtype);
1283
1284 TransactionHelper helper0(ERR_DNS_TIMED_OUT);
1285 std::unique_ptr<DnsTransaction> transaction =
1286 transaction_factory_->CreateTransaction(
1287 kT0HostName, kT0Qtype, NetLogWithSource(), false /* secure */,
1288 SecureDnsMode::kOff, resolve_context_.get(), true /* fast_timeout */);
1289
1290 helper0.StartTransaction(std::move(transaction));
1291
1292 // Finish when the third attempt expires its fallback period.
1293 base::RunLoop().RunUntilIdle();
1294 EXPECT_FALSE(helper0.has_completed());
1295 FastForwardBy(
1296 resolve_context_->NextClassicFallbackPeriod(0, 0, session_.get()));
1297 EXPECT_FALSE(helper0.has_completed());
1298 FastForwardBy(
1299 resolve_context_->NextClassicFallbackPeriod(0, 1, session_.get()));
1300 EXPECT_FALSE(helper0.has_completed());
1301 FastForwardBy(
1302 resolve_context_->NextClassicFallbackPeriod(0, 2, session_.get()));
1303 EXPECT_TRUE(helper0.has_completed());
1304 }
1305
TEST_F(DnsTransactionTestWithMockTime,ServerFallbackAndRotate)1306 TEST_F(DnsTransactionTestWithMockTime, ServerFallbackAndRotate) {
1307 // Test that we fallback on both server failure and fallback period
1308 // expiration.
1309 config_.attempts = 2;
1310 // The next request should start from the next server.
1311 config_.rotate = true;
1312 ConfigureNumServers(3);
1313 ConfigureFactory();
1314
1315 // Responses for first request.
1316 AddHangingQuery(kT0HostName, kT0Qtype);
1317 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
1318 AddHangingQuery(kT0HostName, kT0Qtype);
1319 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL);
1320 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
1321 // Responses for second request.
1322 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
1323 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeSERVFAIL);
1324 AddAsyncQueryAndRcode(kT1HostName, kT1Qtype, dns_protocol::kRcodeNXDOMAIN);
1325
1326 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1327 TransactionHelper helper1(ERR_NAME_NOT_RESOLVED);
1328
1329 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1330 false /* secure */, resolve_context_.get());
1331 base::RunLoop().RunUntilIdle();
1332 EXPECT_FALSE(helper0.has_completed());
1333 FastForwardUntilNoTasksRemain();
1334 EXPECT_TRUE(helper0.has_completed());
1335
1336 helper1.StartTransaction(transaction_factory_.get(), kT1HostName, kT1Qtype,
1337 false /* secure */, resolve_context_.get());
1338 helper1.RunUntilComplete();
1339
1340 size_t kOrder[] = {
1341 // The first transaction.
1342 0,
1343 1,
1344 2,
1345 0,
1346 1,
1347 // The second transaction starts from the next server, and 0 is skipped
1348 // because it already has 2 consecutive failures.
1349 1,
1350 2,
1351 1,
1352 };
1353 CheckServerOrder(kOrder, std::size(kOrder));
1354 }
1355
TEST_F(DnsTransactionTest,SuffixSearchAboveNdots)1356 TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {
1357 config_.ndots = 2;
1358 config_.search.push_back("a");
1359 config_.search.push_back("b");
1360 config_.search.push_back("c");
1361 config_.rotate = true;
1362 ConfigureNumServers(2);
1363 ConfigureFactory();
1364
1365 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
1366 dns_protocol::kRcodeNXDOMAIN);
1367 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
1368 dns_protocol::kRcodeNXDOMAIN);
1369 AddAsyncQueryAndRcode("x.y.z.b", dns_protocol::kTypeA,
1370 dns_protocol::kRcodeNXDOMAIN);
1371 AddAsyncQueryAndRcode("x.y.z.c", dns_protocol::kTypeA,
1372 dns_protocol::kRcodeNXDOMAIN);
1373
1374 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1375
1376 helper0.StartTransaction(transaction_factory_.get(), "x.y.z",
1377 dns_protocol::kTypeA, false /* secure */,
1378 resolve_context_.get());
1379 helper0.RunUntilComplete();
1380
1381 // Also check if suffix search causes server rotation.
1382 size_t kOrder0[] = {0, 1, 0, 1};
1383 CheckServerOrder(kOrder0, std::size(kOrder0));
1384 }
1385
TEST_F(DnsTransactionTest,SuffixSearchBelowNdots)1386 TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {
1387 config_.ndots = 2;
1388 config_.search.push_back("a");
1389 config_.search.push_back("b");
1390 config_.search.push_back("c");
1391 ConfigureFactory();
1392
1393 // Responses for first transaction.
1394 AddAsyncQueryAndRcode("x.y.a", dns_protocol::kTypeA,
1395 dns_protocol::kRcodeNXDOMAIN);
1396 AddAsyncQueryAndRcode("x.y.b", dns_protocol::kTypeA,
1397 dns_protocol::kRcodeNXDOMAIN);
1398 AddAsyncQueryAndRcode("x.y.c", dns_protocol::kTypeA,
1399 dns_protocol::kRcodeNXDOMAIN);
1400 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
1401 dns_protocol::kRcodeNXDOMAIN);
1402 // Responses for second transaction.
1403 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
1404 dns_protocol::kRcodeNXDOMAIN);
1405 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
1406 dns_protocol::kRcodeNXDOMAIN);
1407 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
1408 dns_protocol::kRcodeNXDOMAIN);
1409 // Responses for third transaction.
1410 AddAsyncQueryAndRcode("x", dns_protocol::kTypeAAAA,
1411 dns_protocol::kRcodeNXDOMAIN);
1412
1413 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1414 helper0.StartTransaction(transaction_factory_.get(), "x.y",
1415 dns_protocol::kTypeA, false /* secure */,
1416 resolve_context_.get());
1417 helper0.RunUntilComplete();
1418
1419 // A single-label name.
1420 TransactionHelper helper1(ERR_NAME_NOT_RESOLVED);
1421 helper1.StartTransaction(transaction_factory_.get(), "x",
1422 dns_protocol::kTypeA, false /* secure */,
1423 resolve_context_.get());
1424 helper1.RunUntilComplete();
1425
1426 // A fully-qualified name.
1427 TransactionHelper helper2(ERR_NAME_NOT_RESOLVED);
1428 helper2.StartTransaction(transaction_factory_.get(), "x.",
1429 dns_protocol::kTypeAAAA, false /* secure */,
1430 resolve_context_.get());
1431 helper2.RunUntilComplete();
1432 }
1433
TEST_F(DnsTransactionTest,EmptySuffixSearch)1434 TEST_F(DnsTransactionTest, EmptySuffixSearch) {
1435 // Responses for first transaction.
1436 AddAsyncQueryAndRcode("x", dns_protocol::kTypeA,
1437 dns_protocol::kRcodeNXDOMAIN);
1438
1439 // A fully-qualified name.
1440 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1441 helper0.StartTransaction(transaction_factory_.get(), "x.",
1442 dns_protocol::kTypeA, false /* secure */,
1443 resolve_context_.get());
1444 helper0.RunUntilComplete();
1445
1446 // A single label name is not even attempted.
1447 TransactionHelper helper1(ERR_DNS_SEARCH_EMPTY);
1448 helper1.StartTransaction(transaction_factory_.get(), "singlelabel",
1449 dns_protocol::kTypeA, false /* secure */,
1450 resolve_context_.get());
1451 helper1.RunUntilComplete();
1452 }
1453
TEST_F(DnsTransactionTest,DontAppendToMultiLabelName)1454 TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) {
1455 config_.search.push_back("a");
1456 config_.search.push_back("b");
1457 config_.search.push_back("c");
1458 config_.append_to_multi_label_name = false;
1459 ConfigureFactory();
1460
1461 // Responses for first transaction.
1462 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
1463 dns_protocol::kRcodeNXDOMAIN);
1464 // Responses for second transaction.
1465 AddAsyncQueryAndRcode("x.y", dns_protocol::kTypeA,
1466 dns_protocol::kRcodeNXDOMAIN);
1467 // Responses for third transaction.
1468 AddAsyncQueryAndRcode("x.a", dns_protocol::kTypeA,
1469 dns_protocol::kRcodeNXDOMAIN);
1470 AddAsyncQueryAndRcode("x.b", dns_protocol::kTypeA,
1471 dns_protocol::kRcodeNXDOMAIN);
1472 AddAsyncQueryAndRcode("x.c", dns_protocol::kTypeA,
1473 dns_protocol::kRcodeNXDOMAIN);
1474
1475 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
1476 helper0.StartTransaction(transaction_factory_.get(), "x.y.z",
1477 dns_protocol::kTypeA, false /* secure */,
1478 resolve_context_.get());
1479 helper0.RunUntilComplete();
1480
1481 TransactionHelper helper1(ERR_NAME_NOT_RESOLVED);
1482 helper1.StartTransaction(transaction_factory_.get(), "x.y",
1483 dns_protocol::kTypeA, false /* secure */,
1484 resolve_context_.get());
1485 helper1.RunUntilComplete();
1486
1487 TransactionHelper helper2(ERR_NAME_NOT_RESOLVED);
1488 helper2.StartTransaction(transaction_factory_.get(), "x",
1489 dns_protocol::kTypeA, false /* secure */,
1490 resolve_context_.get());
1491 helper2.RunUntilComplete();
1492 }
1493
1494 const uint8_t kResponseNoData[] = {
1495 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
1496 // Question
1497 0x01, 'x', 0x01, 'y', 0x01, 'z', 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01,
1498 // Authority section, SOA record, TTL 0x3E6
1499 0x01, 'z', 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE6,
1500 // Minimal RDATA, 18 bytes
1501 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1503 };
1504
TEST_F(DnsTransactionTest,SuffixSearchStop)1505 TEST_F(DnsTransactionTest, SuffixSearchStop) {
1506 config_.ndots = 2;
1507 config_.search.push_back("a");
1508 config_.search.push_back("b");
1509 config_.search.push_back("c");
1510 ConfigureFactory();
1511
1512 AddAsyncQueryAndRcode("x.y.z", dns_protocol::kTypeA,
1513 dns_protocol::kRcodeNXDOMAIN);
1514 AddAsyncQueryAndRcode("x.y.z.a", dns_protocol::kTypeA,
1515 dns_protocol::kRcodeNXDOMAIN);
1516 AddAsyncQueryAndResponse(0 /* id */, "x.y.z.b", dns_protocol::kTypeA,
1517 kResponseNoData, std::size(kResponseNoData));
1518
1519 TransactionHelper helper0(0 /* answers */);
1520
1521 helper0.StartTransaction(transaction_factory_.get(), "x.y.z",
1522 dns_protocol::kTypeA, false /* secure */,
1523 resolve_context_.get());
1524 helper0.RunUntilComplete();
1525 }
1526
TEST_F(DnsTransactionTest,SyncFirstQuery)1527 TEST_F(DnsTransactionTest, SyncFirstQuery) {
1528 config_.search.push_back("lab.ccs.neu.edu");
1529 config_.search.push_back("ccs.neu.edu");
1530 ConfigureFactory();
1531
1532 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1533 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1534
1535 TransactionHelper helper0(kT0RecordCount);
1536 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1537 false /* secure */, resolve_context_.get());
1538 helper0.RunUntilComplete();
1539 }
1540
TEST_F(DnsTransactionTest,SyncFirstQueryWithSearch)1541 TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {
1542 config_.search.push_back("lab.ccs.neu.edu");
1543 config_.search.push_back("ccs.neu.edu");
1544 ConfigureFactory();
1545
1546 AddSyncQueryAndRcode("www.lab.ccs.neu.edu", kT2Qtype,
1547 dns_protocol::kRcodeNXDOMAIN);
1548 // "www.ccs.neu.edu"
1549 AddAsyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
1550 kT2ResponseDatagram, std::size(kT2ResponseDatagram));
1551
1552 TransactionHelper helper0(kT2RecordCount);
1553 helper0.StartTransaction(transaction_factory_.get(), "www", kT2Qtype,
1554 false /* secure */, resolve_context_.get());
1555 helper0.RunUntilComplete();
1556 }
1557
TEST_F(DnsTransactionTest,SyncSearchQuery)1558 TEST_F(DnsTransactionTest, SyncSearchQuery) {
1559 config_.search.push_back("lab.ccs.neu.edu");
1560 config_.search.push_back("ccs.neu.edu");
1561 ConfigureFactory();
1562
1563 AddAsyncQueryAndRcode("www.lab.ccs.neu.edu", dns_protocol::kTypeA,
1564 dns_protocol::kRcodeNXDOMAIN);
1565 AddSyncQueryAndResponse(2 /* id */, kT2HostName, kT2Qtype,
1566 kT2ResponseDatagram, std::size(kT2ResponseDatagram));
1567
1568 TransactionHelper helper0(kT2RecordCount);
1569 helper0.StartTransaction(transaction_factory_.get(), "www", kT2Qtype,
1570 false /* secure */, resolve_context_.get());
1571 helper0.RunUntilComplete();
1572 }
1573
TEST_F(DnsTransactionTest,ConnectFailure)1574 TEST_F(DnsTransactionTest, ConnectFailure) {
1575 // Prep socket factory for a single socket with connection failure.
1576 MockConnect connect_data;
1577 connect_data.result = ERR_FAILED;
1578 StaticSocketDataProvider data_provider;
1579 data_provider.set_connect_data(connect_data);
1580 socket_factory_->AddSocketDataProvider(&data_provider);
1581
1582 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
1583 TransactionHelper helper0(ERR_CONNECTION_REFUSED);
1584
1585 helper0.StartTransaction(transaction_factory_.get(), "www.chromium.org",
1586 dns_protocol::kTypeA, false /* secure */,
1587 resolve_context_.get());
1588 helper0.RunUntilComplete();
1589
1590 EXPECT_FALSE(helper0.response());
1591 EXPECT_FALSE(session_->udp_tracker()->low_entropy());
1592 }
1593
TEST_F(DnsTransactionTest,ConnectFailure_SocketLimitReached)1594 TEST_F(DnsTransactionTest, ConnectFailure_SocketLimitReached) {
1595 // Prep socket factory for a single socket with connection failure.
1596 MockConnect connect_data;
1597 connect_data.result = ERR_INSUFFICIENT_RESOURCES;
1598 StaticSocketDataProvider data_provider;
1599 data_provider.set_connect_data(connect_data);
1600 socket_factory_->AddSocketDataProvider(&data_provider);
1601
1602 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
1603 TransactionHelper helper0(ERR_CONNECTION_REFUSED);
1604
1605 helper0.StartTransaction(transaction_factory_.get(), "www.chromium.org",
1606 dns_protocol::kTypeA, false /* secure */,
1607 resolve_context_.get());
1608 helper0.RunUntilComplete();
1609
1610 EXPECT_FALSE(helper0.response());
1611 EXPECT_TRUE(session_->udp_tracker()->low_entropy());
1612 }
1613
TEST_F(DnsTransactionTest,ConnectFailureFollowedBySuccess)1614 TEST_F(DnsTransactionTest, ConnectFailureFollowedBySuccess) {
1615 // Retry after server failure.
1616 config_.attempts = 2;
1617 ConfigureFactory();
1618 // First server connection attempt fails.
1619 transaction_ids_.push_back(0); // Needed to make a DnsUDPAttempt.
1620 socket_factory_->fail_next_socket_ = true;
1621 // Second DNS query succeeds.
1622 AddAsyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
1623 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
1624 TransactionHelper helper0(kT0RecordCount);
1625 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1626 false /* secure */, resolve_context_.get());
1627 helper0.RunUntilComplete();
1628 }
1629
TEST_F(DnsTransactionTest,HttpsGetLookup)1630 TEST_F(DnsTransactionTest, HttpsGetLookup) {
1631 ConfigureDohServers(false /* use_post */);
1632 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1633 std::size(kT0ResponseDatagram), SYNCHRONOUS,
1634 Transport::HTTPS, nullptr /* opt_rdata */,
1635 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1636 false /* enqueue_transaction_id */);
1637 TransactionHelper helper0(kT0RecordCount);
1638 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1639 true /* secure */, resolve_context_.get());
1640 helper0.RunUntilComplete();
1641 }
1642
TEST_F(DnsTransactionTest,HttpsGetFailure)1643 TEST_F(DnsTransactionTest, HttpsGetFailure) {
1644 ConfigureDohServers(false /* use_post */);
1645 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
1646 SYNCHRONOUS, Transport::HTTPS,
1647 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
1648 false /* enqueue_transaction_id */);
1649
1650 TransactionHelper helper0(ERR_DNS_SERVER_FAILED);
1651 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1652 true /* secure */, resolve_context_.get());
1653 helper0.RunUntilComplete();
1654 ASSERT_NE(helper0.response(), nullptr);
1655 EXPECT_EQ(helper0.response()->rcode(), dns_protocol::kRcodeSERVFAIL);
1656 }
1657
TEST_F(DnsTransactionTest,HttpsGetMalformed)1658 TEST_F(DnsTransactionTest, HttpsGetMalformed) {
1659 ConfigureDohServers(false /* use_post */);
1660 // Use T1 response, which is malformed for a T0 request.
1661 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT1ResponseDatagram,
1662 std::size(kT1ResponseDatagram), SYNCHRONOUS,
1663 Transport::HTTPS, nullptr /* opt_rdata */,
1664 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1665 false /* enqueue_transaction_id */);
1666 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
1667 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1668 true /* secure */, resolve_context_.get());
1669 helper0.RunUntilComplete();
1670 }
1671
TEST_F(DnsTransactionTest,HttpsPostLookup)1672 TEST_F(DnsTransactionTest, HttpsPostLookup) {
1673 ConfigureDohServers(true /* use_post */);
1674 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1675 std::size(kT0ResponseDatagram), SYNCHRONOUS,
1676 Transport::HTTPS, nullptr /* opt_rdata */,
1677 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1678 false /* enqueue_transaction_id */);
1679 TransactionHelper helper0(kT0RecordCount);
1680 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1681 true /* secure */, resolve_context_.get());
1682 helper0.RunUntilComplete();
1683 }
1684
TEST_F(DnsTransactionTest,HttpsPostFailure)1685 TEST_F(DnsTransactionTest, HttpsPostFailure) {
1686 ConfigureDohServers(true /* use_post */);
1687 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
1688 SYNCHRONOUS, Transport::HTTPS,
1689 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
1690 false /* enqueue_transaction_id */);
1691
1692 TransactionHelper helper0(ERR_DNS_SERVER_FAILED);
1693 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1694 true /* secure */, resolve_context_.get());
1695 helper0.RunUntilComplete();
1696 ASSERT_NE(helper0.response(), nullptr);
1697 EXPECT_EQ(helper0.response()->rcode(), dns_protocol::kRcodeSERVFAIL);
1698 }
1699
TEST_F(DnsTransactionTest,HttpsPostMalformed)1700 TEST_F(DnsTransactionTest, HttpsPostMalformed) {
1701 ConfigureDohServers(true /* use_post */);
1702 // Use T1 response, which is malformed for a T0 request.
1703 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT1ResponseDatagram,
1704 std::size(kT1ResponseDatagram), SYNCHRONOUS,
1705 Transport::HTTPS, nullptr /* opt_rdata */,
1706 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1707 false /* enqueue_transaction_id */);
1708
1709 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
1710 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1711 true /* secure */, resolve_context_.get());
1712 helper0.RunUntilComplete();
1713 }
1714
TEST_F(DnsTransactionTest,HttpsPostLookupAsync)1715 TEST_F(DnsTransactionTest, HttpsPostLookupAsync) {
1716 ConfigureDohServers(true /* use_post */);
1717 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1718 std::size(kT0ResponseDatagram), ASYNC, Transport::HTTPS,
1719 nullptr /* opt_rdata */,
1720 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1721 false /* enqueue_transaction_id */);
1722 TransactionHelper helper0(kT0RecordCount);
1723 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1724 true /* secure */, resolve_context_.get());
1725 helper0.RunUntilComplete();
1726 }
1727
DohJobMakerCallbackFailLookup(URLRequest * request,SocketDataProvider * data)1728 std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailLookup(
1729 URLRequest* request,
1730 SocketDataProvider* data) {
1731 URLRequestMockDohJob::MatchQueryData(request, data);
1732 return std::make_unique<URLRequestFailedJob>(
1733 request, URLRequestFailedJob::START, ERR_NAME_NOT_RESOLVED);
1734 }
1735
TEST_F(DnsTransactionTest,HttpsPostLookupFailDohServerLookup)1736 TEST_F(DnsTransactionTest, HttpsPostLookupFailDohServerLookup) {
1737 ConfigureDohServers(true /* use_post */);
1738 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1739 std::size(kT0ResponseDatagram), SYNCHRONOUS,
1740 Transport::HTTPS, nullptr /* opt_rdata */,
1741 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1742 false /* enqueue_transaction_id */);
1743 TransactionHelper helper0(ERR_DNS_SECURE_RESOLVER_HOSTNAME_RESOLUTION_FAILED);
1744 SetDohJobMakerCallback(base::BindRepeating(DohJobMakerCallbackFailLookup));
1745 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1746 true /* secure */, resolve_context_.get());
1747 helper0.RunUntilComplete();
1748 }
1749
DohJobMakerCallbackFailStart(URLRequest * request,SocketDataProvider * data)1750 std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailStart(
1751 URLRequest* request,
1752 SocketDataProvider* data) {
1753 URLRequestMockDohJob::MatchQueryData(request, data);
1754 return std::make_unique<URLRequestFailedJob>(
1755 request, URLRequestFailedJob::START, ERR_FAILED);
1756 }
1757
TEST_F(DnsTransactionTest,HttpsPostLookupFailStart)1758 TEST_F(DnsTransactionTest, HttpsPostLookupFailStart) {
1759 ConfigureDohServers(true /* use_post */);
1760 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1761 std::size(kT0ResponseDatagram), SYNCHRONOUS,
1762 Transport::HTTPS, nullptr /* opt_rdata */,
1763 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1764 false /* enqueue_transaction_id */);
1765 TransactionHelper helper0(ERR_FAILED);
1766 SetDohJobMakerCallback(base::BindRepeating(DohJobMakerCallbackFailStart));
1767 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1768 true /* secure */, resolve_context_.get());
1769 helper0.RunUntilComplete();
1770 }
1771
DohJobMakerCallbackFailSync(URLRequest * request,SocketDataProvider * data)1772 std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailSync(
1773 URLRequest* request,
1774 SocketDataProvider* data) {
1775 URLRequestMockDohJob::MatchQueryData(request, data);
1776 return std::make_unique<URLRequestFailedJob>(
1777 request, URLRequestFailedJob::READ_SYNC, ERR_FAILED);
1778 }
1779
TEST_F(DnsTransactionTest,HttpsPostLookupFailSync)1780 TEST_F(DnsTransactionTest, HttpsPostLookupFailSync) {
1781 ConfigureDohServers(true /* use_post */);
1782 auto data = std::make_unique<DnsSocketData>(
1783 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1784 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1785 data->AddResponseWithLength(std::make_unique<DnsResponse>(), SYNCHRONOUS, 0);
1786 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1787 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
1788 SetDohJobMakerCallback(base::BindRepeating(DohJobMakerCallbackFailSync));
1789 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1790 true /* secure */, resolve_context_.get());
1791 helper0.RunUntilComplete();
1792 }
1793
DohJobMakerCallbackFailAsync(URLRequest * request,SocketDataProvider * data)1794 std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailAsync(
1795 URLRequest* request,
1796 SocketDataProvider* data) {
1797 URLRequestMockDohJob::MatchQueryData(request, data);
1798 return std::make_unique<URLRequestFailedJob>(
1799 request, URLRequestFailedJob::READ_ASYNC, ERR_FAILED);
1800 }
1801
TEST_F(DnsTransactionTest,HttpsPostLookupFailAsync)1802 TEST_F(DnsTransactionTest, HttpsPostLookupFailAsync) {
1803 ConfigureDohServers(true /* use_post */);
1804 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1805 std::size(kT0ResponseDatagram), SYNCHRONOUS,
1806 Transport::HTTPS, nullptr /* opt_rdata */,
1807 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1808 false /* enqueue_transaction_id */);
1809 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
1810 SetDohJobMakerCallback(base::BindRepeating(DohJobMakerCallbackFailAsync));
1811 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1812 true /* secure */, resolve_context_.get());
1813 helper0.RunUntilComplete();
1814 }
1815
TEST_F(DnsTransactionTest,HttpsPostLookup2Sync)1816 TEST_F(DnsTransactionTest, HttpsPostLookup2Sync) {
1817 ConfigureDohServers(true /* use_post */);
1818 auto data = std::make_unique<DnsSocketData>(
1819 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1820 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1821 data->AddResponseData(kT0ResponseDatagram, 20, SYNCHRONOUS);
1822 data->AddResponseData(kT0ResponseDatagram + 20,
1823 std::size(kT0ResponseDatagram) - 20, SYNCHRONOUS);
1824 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1825 TransactionHelper helper0(kT0RecordCount);
1826 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1827 true /* secure */, resolve_context_.get());
1828 helper0.RunUntilComplete();
1829 }
1830
TEST_F(DnsTransactionTest,HttpsPostLookup2Async)1831 TEST_F(DnsTransactionTest, HttpsPostLookup2Async) {
1832 ConfigureDohServers(true /* use_post */);
1833 auto data = std::make_unique<DnsSocketData>(
1834 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1835 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1836 data->AddResponseData(kT0ResponseDatagram, 20, ASYNC);
1837 data->AddResponseData(kT0ResponseDatagram + 20,
1838 std::size(kT0ResponseDatagram) - 20, ASYNC);
1839 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1840 TransactionHelper helper0(kT0RecordCount);
1841 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1842 true /* secure */, resolve_context_.get());
1843 helper0.RunUntilComplete();
1844 }
1845
TEST_F(DnsTransactionTest,HttpsPostLookupAsyncWithAsyncZeroRead)1846 TEST_F(DnsTransactionTest, HttpsPostLookupAsyncWithAsyncZeroRead) {
1847 ConfigureDohServers(true /* use_post */);
1848 auto data = std::make_unique<DnsSocketData>(
1849 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1850 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1851 data->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1852 ASYNC);
1853 data->AddResponseData(kT0ResponseDatagram, 0, ASYNC);
1854 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1855 TransactionHelper helper0(kT0RecordCount);
1856 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1857 true /* secure */, resolve_context_.get());
1858 helper0.RunUntilComplete();
1859 }
1860
TEST_F(DnsTransactionTest,HttpsPostLookupSyncWithAsyncZeroRead)1861 TEST_F(DnsTransactionTest, HttpsPostLookupSyncWithAsyncZeroRead) {
1862 ConfigureDohServers(true /* use_post */);
1863 auto data = std::make_unique<DnsSocketData>(
1864 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1865 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1866 data->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
1867 SYNCHRONOUS);
1868 data->AddResponseData(kT0ResponseDatagram, 0, ASYNC);
1869 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1870 TransactionHelper helper0(kT0RecordCount);
1871 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1872 true /* secure */, resolve_context_.get());
1873 helper0.RunUntilComplete();
1874 }
1875
TEST_F(DnsTransactionTest,HttpsPostLookupAsyncThenSync)1876 TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenSync) {
1877 ConfigureDohServers(true /* use_post */);
1878 auto data = std::make_unique<DnsSocketData>(
1879 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1880 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1881 data->AddResponseData(kT0ResponseDatagram, 20, ASYNC);
1882 data->AddResponseData(kT0ResponseDatagram + 20,
1883 std::size(kT0ResponseDatagram) - 20, SYNCHRONOUS);
1884 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1885 TransactionHelper helper0(kT0RecordCount);
1886 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1887 true /* secure */, resolve_context_.get());
1888 helper0.RunUntilComplete();
1889 }
1890
TEST_F(DnsTransactionTest,HttpsPostLookupAsyncThenSyncError)1891 TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenSyncError) {
1892 ConfigureDohServers(true /* use_post */);
1893 auto data = std::make_unique<DnsSocketData>(
1894 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1895 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1896 data->AddResponseData(kT0ResponseDatagram, 20, ASYNC);
1897 data->AddReadError(ERR_FAILED, SYNCHRONOUS);
1898 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1899 TransactionHelper helper0(ERR_FAILED);
1900 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1901 true /* secure */, resolve_context_.get());
1902 helper0.RunUntilComplete();
1903 }
1904
TEST_F(DnsTransactionTest,HttpsPostLookupAsyncThenAsyncError)1905 TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenAsyncError) {
1906 ConfigureDohServers(true /* use_post */);
1907 auto data = std::make_unique<DnsSocketData>(
1908 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1909 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1910 data->AddResponseData(kT0ResponseDatagram, 20, ASYNC);
1911 data->AddReadError(ERR_FAILED, ASYNC);
1912 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1913 TransactionHelper helper0(ERR_FAILED);
1914 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1915 true /* secure */, resolve_context_.get());
1916 helper0.RunUntilComplete();
1917 }
1918
TEST_F(DnsTransactionTest,HttpsPostLookupSyncThenAsyncError)1919 TEST_F(DnsTransactionTest, HttpsPostLookupSyncThenAsyncError) {
1920 ConfigureDohServers(true /* use_post */);
1921 auto data = std::make_unique<DnsSocketData>(
1922 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1923 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1924 data->AddResponseData(kT0ResponseDatagram, 20, SYNCHRONOUS);
1925 data->AddReadError(ERR_FAILED, ASYNC);
1926 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1927 TransactionHelper helper0(ERR_FAILED);
1928 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1929 true /* secure */, resolve_context_.get());
1930 helper0.RunUntilComplete();
1931 }
1932
TEST_F(DnsTransactionTest,HttpsPostLookupSyncThenSyncError)1933 TEST_F(DnsTransactionTest, HttpsPostLookupSyncThenSyncError) {
1934 ConfigureDohServers(true /* use_post */);
1935 auto data = std::make_unique<DnsSocketData>(
1936 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS,
1937 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
1938 data->AddResponseData(kT0ResponseDatagram, 20, SYNCHRONOUS);
1939 data->AddReadError(ERR_FAILED, SYNCHRONOUS);
1940 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
1941 TransactionHelper helper0(ERR_FAILED);
1942 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1943 true /* secure */, resolve_context_.get());
1944 helper0.RunUntilComplete();
1945 }
1946
TEST_F(DnsTransactionTest,HttpsNotAvailable)1947 TEST_F(DnsTransactionTest, HttpsNotAvailable) {
1948 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
1949 false /* make_available */);
1950 ASSERT_FALSE(resolve_context_->GetDohServerAvailability(
1951 0u /* doh_server_index */, session_.get()));
1952
1953 TransactionHelper helper0(ERR_BLOCKED_BY_CLIENT);
1954 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1955 true /* secure */, resolve_context_.get());
1956 helper0.RunUntilComplete();
1957 }
1958
TEST_F(DnsTransactionTest,HttpsMarkHttpsBad)1959 TEST_F(DnsTransactionTest, HttpsMarkHttpsBad) {
1960 config_.attempts = 1;
1961 ConfigureDohServers(true /* use_post */, 3);
1962 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
1963 SYNCHRONOUS, Transport::HTTPS,
1964 nullptr /* opt_rdata */,
1965 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1966 false /* enqueue_transaction_id */);
1967 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
1968 SYNCHRONOUS, Transport::HTTPS,
1969 nullptr /* opt_rdata */,
1970 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1971 false /* enqueue_transaction_id */);
1972 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1973 std::size(kT0ResponseDatagram), ASYNC, Transport::HTTPS,
1974 nullptr /* opt_rdata */,
1975 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1976 false /* enqueue_transaction_id */);
1977 AddQueryAndErrorResponse(0 /* id */, kT0HostName, kT0Qtype,
1978 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
1979 Transport::HTTPS, nullptr /* opt_rdata */,
1980 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1981 false /* enqueue_transaction_id */);
1982 AddQueryAndErrorResponse(0 /* id */, kT0HostName, kT0Qtype,
1983 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
1984 Transport::HTTPS, nullptr /* opt_rdata */,
1985 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1986 false /* enqueue_transaction_id */);
1987 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
1988 std::size(kT0ResponseDatagram), ASYNC, Transport::HTTPS,
1989 nullptr /* opt_rdata */,
1990 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
1991 false /* enqueue_transaction_id */);
1992
1993 TransactionHelper helper0(kT0RecordCount);
1994 TransactionHelper helper1(kT0RecordCount);
1995
1996 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
1997 true /* secure */, resolve_context_.get());
1998 helper0.RunUntilComplete();
1999
2000 // UDP server 0 is our only UDP server, so it will be good. HTTPS
2001 // servers 0 and 1 failed and will be marked bad. HTTPS server 2 succeeded
2002 // so it will be good.
2003 // The expected order of the HTTPS servers is therefore 2, 0, then 1.
2004 {
2005 std::unique_ptr<DnsServerIterator> classic_itr =
2006 resolve_context_->GetClassicDnsIterator(session_->config(),
2007 session_.get());
2008 std::unique_ptr<DnsServerIterator> doh_itr =
2009 resolve_context_->GetDohIterator(
2010 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2011 EXPECT_TRUE(classic_itr->AttemptAvailable());
2012 EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
2013 ASSERT_TRUE(doh_itr->AttemptAvailable());
2014 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
2015 ASSERT_TRUE(doh_itr->AttemptAvailable());
2016 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2017 ASSERT_TRUE(doh_itr->AttemptAvailable());
2018 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
2019 }
2020 size_t kOrder0[] = {1, 2, 3};
2021 CheckServerOrder(kOrder0, std::size(kOrder0));
2022
2023 helper1.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2024 true /* secure */, resolve_context_.get());
2025 helper1.RunUntilComplete();
2026 // UDP server 0 is still our only UDP server, so it will be good by
2027 // definition. HTTPS server 2 started out as good, so it was tried first and
2028 // failed. HTTPS server 0 then had the oldest failure so it would be the next
2029 // good server and then it failed so it's marked bad. Next attempt was HTTPS
2030 // server 1, which succeeded so it's good. The expected order of the HTTPS
2031 // servers is therefore 1, 2, then 0.
2032
2033 {
2034 std::unique_ptr<DnsServerIterator> classic_itr =
2035 resolve_context_->GetClassicDnsIterator(session_->config(),
2036 session_.get());
2037 std::unique_ptr<DnsServerIterator> doh_itr =
2038 resolve_context_->GetDohIterator(
2039 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2040
2041 EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
2042 ASSERT_TRUE(doh_itr->AttemptAvailable());
2043 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
2044 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
2045 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2046 }
2047
2048 size_t kOrder1[] = {
2049 1, 2, 3, /* transaction0 */
2050 3, 1, 2 /* transaction1 */
2051 };
2052 CheckServerOrder(kOrder1, std::size(kOrder1));
2053 }
2054
TEST_F(DnsTransactionTest,HttpsPostFailThenHTTPFallback)2055 TEST_F(DnsTransactionTest, HttpsPostFailThenHTTPFallback) {
2056 ConfigureDohServers(true /* use_post */, 2);
2057 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL, ASYNC,
2058 Transport::HTTPS,
2059 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2060 false /* enqueue_transaction_id */);
2061 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2062 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2063 Transport::HTTPS, nullptr /* opt_rdata */,
2064 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2065 false /* enqueue_transaction_id */);
2066 TransactionHelper helper0(kT0RecordCount);
2067 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2068 true /* secure */, resolve_context_.get());
2069 helper0.RunUntilComplete();
2070 size_t kOrder0[] = {1, 2};
2071 CheckServerOrder(kOrder0, std::size(kOrder0));
2072 }
2073
TEST_F(DnsTransactionTest,HttpsPostFailTwice)2074 TEST_F(DnsTransactionTest, HttpsPostFailTwice) {
2075 config_.attempts = 3;
2076 ConfigureDohServers(true /* use_post */, 2);
2077 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2078 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2079 Transport::HTTPS, nullptr /* opt_rdata */,
2080 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2081 false /* enqueue_transaction_id */);
2082 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2083 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2084 Transport::HTTPS, nullptr /* opt_rdata */,
2085 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2086 false /* enqueue_transaction_id */);
2087 TransactionHelper helper0(ERR_FAILED);
2088 SetDohJobMakerCallback(base::BindRepeating(DohJobMakerCallbackFailStart));
2089 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2090 true /* secure */, resolve_context_.get());
2091 helper0.RunUntilComplete();
2092 size_t kOrder0[] = {1, 2};
2093 CheckServerOrder(kOrder0, std::size(kOrder0));
2094 }
2095
TEST_F(DnsTransactionTest,HttpsNotAvailableThenHttpFallback)2096 TEST_F(DnsTransactionTest, HttpsNotAvailableThenHttpFallback) {
2097 ConfigureDohServers(true /* use_post */, 2 /* num_doh_servers */,
2098 false /* make_available */);
2099
2100 // Make just server 1 available.
2101 resolve_context_->RecordServerSuccess(
2102 1u /* server_index */, true /* is_doh_server*/, session_.get());
2103
2104 {
2105 std::unique_ptr<DnsServerIterator> doh_itr =
2106 resolve_context_->GetDohIterator(
2107 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2108
2109 ASSERT_TRUE(doh_itr->AttemptAvailable());
2110 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
2111 EXPECT_FALSE(doh_itr->AttemptAvailable());
2112 }
2113 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2114 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2115 Transport::HTTPS, nullptr /* opt_rdata */,
2116 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2117 false /* enqueue_transaction_id */);
2118 TransactionHelper helper0(kT0RecordCount);
2119 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2120 true /* secure */, resolve_context_.get());
2121 helper0.RunUntilComplete();
2122 size_t kOrder0[] = {2};
2123 CheckServerOrder(kOrder0, std::size(kOrder0));
2124 {
2125 std::unique_ptr<DnsServerIterator> doh_itr =
2126 resolve_context_->GetDohIterator(
2127 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2128
2129 ASSERT_TRUE(doh_itr->AttemptAvailable());
2130 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
2131 EXPECT_FALSE(doh_itr->AttemptAvailable());
2132 }
2133 }
2134
2135 // Fail first DoH server, then no fallbacks marked available in AUTOMATIC mode.
TEST_F(DnsTransactionTest,HttpsFailureThenNotAvailable_Automatic)2136 TEST_F(DnsTransactionTest, HttpsFailureThenNotAvailable_Automatic) {
2137 config_.secure_dns_mode = SecureDnsMode::kAutomatic;
2138 ConfigureDohServers(true /* use_post */, 3 /* num_doh_servers */,
2139 false /* make_available */);
2140
2141 // Make just server 0 available.
2142 resolve_context_->RecordServerSuccess(
2143 0u /* server_index */, true /* is_doh_server*/, session_.get());
2144
2145 {
2146 std::unique_ptr<DnsServerIterator> doh_itr =
2147 resolve_context_->GetDohIterator(
2148 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2149
2150 ASSERT_TRUE(doh_itr->AttemptAvailable());
2151 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2152 EXPECT_FALSE(doh_itr->AttemptAvailable());
2153 }
2154
2155 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2156 SYNCHRONOUS, Transport::HTTPS,
2157 nullptr /* opt_rdata */,
2158 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2159 false /* enqueue_transaction_id */);
2160 TransactionHelper helper0(ERR_CONNECTION_REFUSED);
2161 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2162 true /* secure */, resolve_context_.get());
2163 helper0.RunUntilComplete();
2164
2165 // Expect fallback not attempted because other servers not available in
2166 // AUTOMATIC mode until they have recorded a success.
2167 size_t kOrder0[] = {1};
2168 CheckServerOrder(kOrder0, std::size(kOrder0));
2169
2170 {
2171 std::unique_ptr<DnsServerIterator> doh_itr =
2172 resolve_context_->GetDohIterator(
2173 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2174
2175 ASSERT_TRUE(doh_itr->AttemptAvailable());
2176 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2177 EXPECT_FALSE(doh_itr->AttemptAvailable());
2178 }
2179 }
2180
2181 // Test a secure transaction failure in SECURE mode when other DoH servers are
2182 // only available for fallback because of
TEST_F(DnsTransactionTest,HttpsFailureThenNotAvailable_Secure)2183 TEST_F(DnsTransactionTest, HttpsFailureThenNotAvailable_Secure) {
2184 config_.secure_dns_mode = SecureDnsMode::kSecure;
2185 ConfigureDohServers(true /* use_post */, 3 /* num_doh_servers */,
2186 false /* make_available */);
2187
2188 // Make just server 0 available.
2189 resolve_context_->RecordServerSuccess(
2190 0u /* server_index */, true /* is_doh_server*/, session_.get());
2191
2192 {
2193 std::unique_ptr<DnsServerIterator> doh_itr =
2194 resolve_context_->GetDohIterator(
2195 session_->config(), SecureDnsMode::kSecure, session_.get());
2196
2197 ASSERT_TRUE(doh_itr->AttemptAvailable());
2198 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2199 ASSERT_TRUE(doh_itr->AttemptAvailable());
2200 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
2201 ASSERT_TRUE(doh_itr->AttemptAvailable());
2202 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
2203 }
2204
2205 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2206 SYNCHRONOUS, Transport::HTTPS,
2207 nullptr /* opt_rdata */,
2208 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2209 false /* enqueue_transaction_id */);
2210 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2211 SYNCHRONOUS, Transport::HTTPS,
2212 nullptr /* opt_rdata */,
2213 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2214 false /* enqueue_transaction_id */);
2215 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2216 SYNCHRONOUS, Transport::HTTPS,
2217 nullptr /* opt_rdata */,
2218 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2219 false /* enqueue_transaction_id */);
2220 TransactionHelper helper0(ERR_CONNECTION_REFUSED);
2221 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2222 true /* secure */, resolve_context_.get());
2223 helper0.RunUntilComplete();
2224
2225 // Expect fallback to attempt all servers because SECURE mode does not require
2226 // server availability.
2227 size_t kOrder0[] = {1, 2, 3};
2228 CheckServerOrder(kOrder0, std::size(kOrder0));
2229
2230 // Expect server 0 to be preferred due to least recent failure.
2231 {
2232 std::unique_ptr<DnsServerIterator> doh_itr =
2233 resolve_context_->GetDohIterator(
2234 session_->config(), SecureDnsMode::kSecure, session_.get());
2235
2236 ASSERT_TRUE(doh_itr->AttemptAvailable());
2237 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2238 }
2239 }
2240
TEST_F(DnsTransactionTest,MaxHttpsFailures_NonConsecutive)2241 TEST_F(DnsTransactionTest, MaxHttpsFailures_NonConsecutive) {
2242 config_.attempts = 1;
2243 ConfigureDohServers(false /* use_post */);
2244 {
2245 std::unique_ptr<DnsServerIterator> doh_itr =
2246 resolve_context_->GetDohIterator(
2247 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2248
2249 ASSERT_TRUE(doh_itr->AttemptAvailable());
2250 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2251 }
2252
2253 for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit - 1; i++) {
2254 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2255 SYNCHRONOUS, Transport::HTTPS,
2256 nullptr /* opt_rdata */,
2257 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2258 false /* enqueue_transaction_id */);
2259 TransactionHelper failure(ERR_CONNECTION_REFUSED);
2260 failure.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2261 true /* secure */, resolve_context_.get());
2262 failure.RunUntilComplete();
2263
2264 std::unique_ptr<DnsServerIterator> doh_itr =
2265 resolve_context_->GetDohIterator(
2266 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2267
2268 ASSERT_TRUE(doh_itr->AttemptAvailable());
2269 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2270 }
2271
2272 // A success should reset the failure counter for DoH.
2273 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2274 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2275 Transport::HTTPS, nullptr /* opt_rdata */,
2276 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2277 false /* enqueue_transaction_id */);
2278 TransactionHelper success(kT0RecordCount);
2279 success.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2280 true /* secure */, resolve_context_.get());
2281 success.RunUntilComplete();
2282 {
2283 std::unique_ptr<DnsServerIterator> doh_itr =
2284 resolve_context_->GetDohIterator(
2285 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2286
2287 ASSERT_TRUE(doh_itr->AttemptAvailable());
2288 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2289 }
2290
2291 // One more failure should not pass the threshold because failures were reset.
2292 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2293 SYNCHRONOUS, Transport::HTTPS,
2294 nullptr /* opt_rdata */,
2295 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2296 false /* enqueue_transaction_id */);
2297 TransactionHelper last_failure(ERR_CONNECTION_REFUSED);
2298 last_failure.StartTransaction(transaction_factory_.get(), kT0HostName,
2299 kT0Qtype, true /* secure */,
2300 resolve_context_.get());
2301 last_failure.RunUntilComplete();
2302 {
2303 std::unique_ptr<DnsServerIterator> doh_itr =
2304 resolve_context_->GetDohIterator(
2305 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2306
2307 ASSERT_TRUE(doh_itr->AttemptAvailable());
2308 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2309 }
2310 }
2311
TEST_F(DnsTransactionTest,MaxHttpsFailures_Consecutive)2312 TEST_F(DnsTransactionTest, MaxHttpsFailures_Consecutive) {
2313 config_.attempts = 1;
2314 ConfigureDohServers(false /* use_post */);
2315 {
2316 std::unique_ptr<DnsServerIterator> doh_itr =
2317 resolve_context_->GetDohIterator(
2318 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2319
2320 ASSERT_TRUE(doh_itr->AttemptAvailable());
2321 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2322 }
2323
2324 for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit - 1; i++) {
2325 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2326 SYNCHRONOUS, Transport::HTTPS,
2327 nullptr /* opt_rdata */,
2328 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2329 false /* enqueue_transaction_id */);
2330 TransactionHelper failure(ERR_CONNECTION_REFUSED);
2331 failure.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2332 true /* secure */, resolve_context_.get());
2333 failure.RunUntilComplete();
2334 std::unique_ptr<DnsServerIterator> doh_itr =
2335 resolve_context_->GetDohIterator(
2336 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2337
2338 ASSERT_TRUE(doh_itr->AttemptAvailable());
2339 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2340 }
2341
2342 // One more failure should pass the threshold.
2343 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2344 SYNCHRONOUS, Transport::HTTPS,
2345 nullptr /* opt_rdata */,
2346 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2347 false /* enqueue_transaction_id */);
2348 TransactionHelper last_failure(ERR_CONNECTION_REFUSED);
2349 last_failure.StartTransaction(transaction_factory_.get(), kT0HostName,
2350 kT0Qtype, true /* secure */,
2351 resolve_context_.get());
2352 last_failure.RunUntilComplete();
2353 {
2354 std::unique_ptr<DnsServerIterator> doh_itr =
2355 resolve_context_->GetDohIterator(
2356 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2357
2358 EXPECT_FALSE(doh_itr->AttemptAvailable());
2359 }
2360 }
2361
2362 // Test that a secure transaction started before a DoH server becomes
2363 // unavailable can complete and make the server available again.
TEST_F(DnsTransactionTest,SuccessfulTransactionStartedBeforeUnavailable)2364 TEST_F(DnsTransactionTest, SuccessfulTransactionStartedBeforeUnavailable) {
2365 ConfigureDohServers(false /* use_post */);
2366 {
2367 std::unique_ptr<DnsServerIterator> doh_itr =
2368 resolve_context_->GetDohIterator(
2369 session_->config(), SecureDnsMode::kAutomatic, session_.get());
2370
2371 ASSERT_TRUE(doh_itr->AttemptAvailable());
2372 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
2373 }
2374
2375 // Create a socket data to first return ERR_IO_PENDING. This will pause the
2376 // response and not return the second response until
2377 // SequencedSocketData::Resume() is called.
2378 auto data = std::make_unique<DnsSocketData>(
2379 0, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
2380 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
2381 data->AddReadError(ERR_IO_PENDING, ASYNC);
2382 data->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
2383 ASYNC);
2384 SequencedSocketData* sequenced_socket_data = data->GetProvider();
2385 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
2386
2387 TransactionHelper delayed_success(kT0RecordCount);
2388 delayed_success.StartTransaction(transaction_factory_.get(), kT0HostName,
2389 kT0Qtype, true /* secure */,
2390 resolve_context_.get());
2391 base::RunLoop().RunUntilIdle();
2392 EXPECT_FALSE(delayed_success.has_completed());
2393
2394 // Trigger DoH server unavailability with a bunch of failures.
2395 for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
2396 AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED,
2397 SYNCHRONOUS, Transport::HTTPS,
2398 nullptr /* opt_rdata */,
2399 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2400 false /* enqueue_transaction_id */);
2401 TransactionHelper failure(ERR_CONNECTION_REFUSED);
2402 failure.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2403 true /* secure */, resolve_context_.get());
2404 failure.RunUntilComplete();
2405 }
2406 EXPECT_FALSE(resolve_context_->GetDohServerAvailability(
2407 0u /* doh_server_index */, session_.get()));
2408
2409 // Resume first query.
2410 ASSERT_FALSE(delayed_success.has_completed());
2411 sequenced_socket_data->Resume();
2412 delayed_success.RunUntilComplete();
2413
2414 // Expect DoH server is available again.
2415 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
2416 0u /* doh_server_index */, session_.get()));
2417 }
2418
MakeResponseWithCookie(URLRequest * request,HttpResponseInfo * info)2419 void MakeResponseWithCookie(URLRequest* request, HttpResponseInfo* info) {
2420 info->headers->AddHeader("Set-Cookie", "test-cookie=you-fail");
2421 }
2422
2423 class CookieCallback {
2424 public:
CookieCallback()2425 CookieCallback() : loop_to_quit_(std::make_unique<base::RunLoop>()) {}
2426
SetCookieCallback(CookieAccessResult result)2427 void SetCookieCallback(CookieAccessResult result) {
2428 result_ = result.status.IsInclude();
2429 loop_to_quit_->Quit();
2430 }
2431
2432 CookieCallback(const CookieCallback&) = delete;
2433 CookieCallback& operator=(const CookieCallback&) = delete;
2434
GetCookieListCallback(const net::CookieAccessResultList & list,const net::CookieAccessResultList & excluded_cookies)2435 void GetCookieListCallback(
2436 const net::CookieAccessResultList& list,
2437 const net::CookieAccessResultList& excluded_cookies) {
2438 list_ = cookie_util::StripAccessResults(list);
2439 loop_to_quit_->Quit();
2440 }
2441
Reset()2442 void Reset() { loop_to_quit_ = std::make_unique<base::RunLoop>(); }
2443
WaitUntilDone()2444 void WaitUntilDone() { loop_to_quit_->Run(); }
2445
cookie_list_size()2446 size_t cookie_list_size() { return list_.size(); }
2447
2448 private:
2449 net::CookieList list_;
2450 bool result_ = false;
2451 std::unique_ptr<base::RunLoop> loop_to_quit_;
2452 };
2453
TEST_F(DnsTransactionTest,HttpsPostTestNoCookies)2454 TEST_F(DnsTransactionTest, HttpsPostTestNoCookies) {
2455 ConfigureDohServers(true /* use_post */);
2456 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2457 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2458 Transport::HTTPS, nullptr /* opt_rdata */,
2459 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2460 false /* enqueue_transaction_id */);
2461 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2462 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2463 Transport::HTTPS, nullptr /* opt_rdata */,
2464 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2465 false /* enqueue_transaction_id */);
2466 TransactionHelper helper0(kT0RecordCount);
2467 TransactionHelper helper1(kT0RecordCount);
2468 SetResponseModifierCallback(base::BindRepeating(MakeResponseWithCookie));
2469
2470 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2471 true /* secure */, resolve_context_.get());
2472 helper0.RunUntilComplete();
2473
2474 CookieCallback callback;
2475 request_context_->cookie_store()->GetCookieListWithOptionsAsync(
2476 GURL(GetURLFromTemplateWithoutParameters(
2477 config_.doh_config.servers()[0].server_template())),
2478 CookieOptions::MakeAllInclusive(), CookiePartitionKeyCollection(),
2479 base::BindOnce(&CookieCallback::GetCookieListCallback,
2480 base::Unretained(&callback)));
2481 callback.WaitUntilDone();
2482 EXPECT_EQ(0u, callback.cookie_list_size());
2483 callback.Reset();
2484 GURL cookie_url(GetURLFromTemplateWithoutParameters(
2485 config_.doh_config.servers()[0].server_template()));
2486 auto cookie = CanonicalCookie::Create(
2487 cookie_url, "test-cookie=you-still-fail", base::Time::Now(),
2488 absl::nullopt /* server_time */,
2489 absl::nullopt /* cookie_partition_key */);
2490 request_context_->cookie_store()->SetCanonicalCookieAsync(
2491 std::move(cookie), cookie_url, CookieOptions(),
2492 base::BindOnce(&CookieCallback::SetCookieCallback,
2493 base::Unretained(&callback)));
2494 helper1.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2495 true /* secure */, resolve_context_.get());
2496 helper1.RunUntilComplete();
2497 }
2498
MakeResponseWithoutLength(URLRequest * request,HttpResponseInfo * info)2499 void MakeResponseWithoutLength(URLRequest* request, HttpResponseInfo* info) {
2500 info->headers->RemoveHeader("Content-Length");
2501 }
2502
TEST_F(DnsTransactionTest,HttpsPostNoContentLength)2503 TEST_F(DnsTransactionTest, HttpsPostNoContentLength) {
2504 ConfigureDohServers(true /* use_post */);
2505 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2506 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2507 Transport::HTTPS, nullptr /* opt_rdata */,
2508 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2509 false /* enqueue_transaction_id */);
2510 TransactionHelper helper0(kT0RecordCount);
2511 SetResponseModifierCallback(base::BindRepeating(MakeResponseWithoutLength));
2512 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2513 true /* secure */, resolve_context_.get());
2514 helper0.RunUntilComplete();
2515 }
2516
MakeResponseWithBadRequestResponse(URLRequest * request,HttpResponseInfo * info)2517 void MakeResponseWithBadRequestResponse(URLRequest* request,
2518 HttpResponseInfo* info) {
2519 info->headers->ReplaceStatusLine("HTTP/1.1 400 Bad Request");
2520 }
2521
TEST_F(DnsTransactionTest,HttpsPostWithBadRequestResponse)2522 TEST_F(DnsTransactionTest, HttpsPostWithBadRequestResponse) {
2523 ConfigureDohServers(true /* use_post */);
2524 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2525 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2526 Transport::HTTPS, nullptr /* opt_rdata */,
2527 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2528 false /* enqueue_transaction_id */);
2529 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
2530 SetResponseModifierCallback(
2531 base::BindRepeating(MakeResponseWithBadRequestResponse));
2532 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2533 true /* secure */, resolve_context_.get());
2534 helper0.RunUntilComplete();
2535 }
2536
MakeResponseWrongType(URLRequest * request,HttpResponseInfo * info)2537 void MakeResponseWrongType(URLRequest* request, HttpResponseInfo* info) {
2538 info->headers->RemoveHeader("Content-Type");
2539 info->headers->AddHeader("Content-Type", "text/html");
2540 }
2541
TEST_F(DnsTransactionTest,HttpsPostWithWrongType)2542 TEST_F(DnsTransactionTest, HttpsPostWithWrongType) {
2543 ConfigureDohServers(true /* use_post */);
2544 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2545 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2546 Transport::HTTPS, nullptr /* opt_rdata */,
2547 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2548 false /* enqueue_transaction_id */);
2549 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
2550 SetResponseModifierCallback(base::BindRepeating(MakeResponseWrongType));
2551 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2552 true /* secure */, resolve_context_.get());
2553 helper0.RunUntilComplete();
2554 }
2555
MakeResponseRedirect(URLRequest * request,HttpResponseInfo * info)2556 void MakeResponseRedirect(URLRequest* request, HttpResponseInfo* info) {
2557 if (request->url_chain().size() < 2) {
2558 info->headers->ReplaceStatusLine("HTTP/1.1 302 Found");
2559 info->headers->AddHeader("Location",
2560 "/redirect-destination?" + request->url().query());
2561 }
2562 }
2563
TEST_F(DnsTransactionTest,HttpsGetRedirect)2564 TEST_F(DnsTransactionTest, HttpsGetRedirect) {
2565 ConfigureDohServers(false /* use_post */);
2566 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2567 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2568 Transport::HTTPS, nullptr /* opt_rdata */,
2569 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2570 false /* enqueue_transaction_id */);
2571 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2572 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2573 Transport::HTTPS, nullptr /* opt_rdata */,
2574 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2575 false /* enqueue_transaction_id */);
2576 TransactionHelper helper0(kT0RecordCount);
2577 SetResponseModifierCallback(base::BindRepeating(MakeResponseRedirect));
2578 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2579 true /* secure */, resolve_context_.get());
2580 helper0.RunUntilComplete();
2581 }
2582
MakeResponseNoType(URLRequest * request,HttpResponseInfo * info)2583 void MakeResponseNoType(URLRequest* request, HttpResponseInfo* info) {
2584 info->headers->RemoveHeader("Content-Type");
2585 }
2586
TEST_F(DnsTransactionTest,HttpsPostWithNoType)2587 TEST_F(DnsTransactionTest, HttpsPostWithNoType) {
2588 ConfigureDohServers(true /* use_post */);
2589 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2590 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2591 Transport::HTTPS, nullptr /* opt_rdata */,
2592 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2593 false /* enqueue_transaction_id */);
2594 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
2595 SetResponseModifierCallback(base::BindRepeating(MakeResponseNoType));
2596 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2597 true /* secure */, resolve_context_.get());
2598 helper0.RunUntilComplete();
2599 }
2600
TEST_F(DnsTransactionTest,CanLookupDohServerName)2601 TEST_F(DnsTransactionTest, CanLookupDohServerName) {
2602 config_.search.push_back("http");
2603 ConfigureDohServers(true /* use_post */);
2604 AddQueryAndErrorResponse(0, kMockHostname, dns_protocol::kTypeA,
2605 ERR_NAME_NOT_RESOLVED, SYNCHRONOUS, Transport::HTTPS,
2606 nullptr /* opt_rdata */,
2607 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2608 false /* enqueue_transaction_id */);
2609 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
2610 helper0.StartTransaction(transaction_factory_.get(), "mock",
2611 dns_protocol::kTypeA, true /* secure */,
2612 resolve_context_.get());
2613 helper0.RunUntilComplete();
2614 }
2615
TEST_F(DnsTransactionTest,HttpsPostLookupWithLog)2616 TEST_F(DnsTransactionTest, HttpsPostLookupWithLog) {
2617 ConfigureDohServers(true /* use_post */);
2618 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
2619 std::size(kT0ResponseDatagram), SYNCHRONOUS,
2620 Transport::HTTPS, nullptr /* opt_rdata */,
2621 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
2622 false /* enqueue_transaction_id */);
2623 TransactionHelper helper0(kT0RecordCount);
2624 NetLogCountingObserver observer;
2625 NetLog::Get()->AddObserver(&observer, NetLogCaptureMode::kEverything);
2626 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
2627 true /* secure */, resolve_context_.get());
2628 helper0.RunUntilComplete();
2629 base::RunLoop().RunUntilIdle();
2630 EXPECT_EQ(observer.count(), 18);
2631 EXPECT_EQ(observer.dict_count(), 9);
2632 }
2633
2634 // Test for when a slow DoH response is delayed until after the initial fallback
2635 // period (but succeeds before the full timeout period).
TEST_F(DnsTransactionTestWithMockTime,SlowHttpsResponse_SingleAttempt)2636 TEST_F(DnsTransactionTestWithMockTime, SlowHttpsResponse_SingleAttempt) {
2637 config_.doh_attempts = 1;
2638 ConfigureDohServers(false /* use_post */);
2639
2640 // Assume fallback period is less than timeout.
2641 ASSERT_LT(resolve_context_->NextDohFallbackPeriod(0 /* doh_server_index */,
2642 session_.get()),
2643 resolve_context_->SecureTransactionTimeout(SecureDnsMode::kSecure,
2644 session_.get()));
2645
2646 // Simulate a slow response by using an ERR_IO_PENDING read error to delay
2647 // until SequencedSocketData::Resume() is called.
2648 auto data = std::make_unique<DnsSocketData>(
2649 0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
2650 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
2651 data->AddReadError(ERR_IO_PENDING, ASYNC);
2652 data->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
2653 ASYNC);
2654 SequencedSocketData* sequenced_socket_data = data->GetProvider();
2655 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
2656
2657 TransactionHelper helper(kT0RecordCount);
2658 std::unique_ptr<DnsTransaction> transaction =
2659 transaction_factory_->CreateTransaction(
2660 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2661 SecureDnsMode::kSecure, resolve_context_.get(),
2662 false /* fast_timeout */);
2663
2664 helper.StartTransaction(std::move(transaction));
2665 base::RunLoop().RunUntilIdle();
2666 ASSERT_FALSE(helper.has_completed());
2667 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
2668 0 /* doh_server_index */, session_.get()));
2669 EXPECT_FALSE(helper.has_completed());
2670
2671 sequenced_socket_data->Resume();
2672 helper.RunUntilComplete();
2673 }
2674
2675 // Test for when a slow DoH response is delayed until after the initial fallback
2676 // period but fast timeout is enabled, resulting in timeout failure.
TEST_F(DnsTransactionTestWithMockTime,SlowHttpsResponse_SingleAttempt_FastTimeout)2677 TEST_F(DnsTransactionTestWithMockTime,
2678 SlowHttpsResponse_SingleAttempt_FastTimeout) {
2679 config_.doh_attempts = 1;
2680 ConfigureDohServers(false /* use_post */);
2681
2682 AddHangingQuery(kT0HostName, kT0Qtype,
2683 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2684 false /* enqueue_transaction_id */);
2685
2686 TransactionHelper helper(ERR_DNS_TIMED_OUT);
2687 std::unique_ptr<DnsTransaction> transaction =
2688 transaction_factory_->CreateTransaction(
2689 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2690 SecureDnsMode::kSecure, resolve_context_.get(),
2691 true /* fast_timeout */);
2692 helper.StartTransaction(std::move(transaction));
2693 base::RunLoop().RunUntilIdle();
2694 ASSERT_FALSE(helper.has_completed());
2695
2696 // Only one attempt configured and fast timeout enabled, so expect immediate
2697 // failure after fallback period.
2698 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
2699 0 /* doh_server_index */, session_.get()));
2700 EXPECT_TRUE(helper.has_completed());
2701 }
2702
2703 // Test for when a slow DoH response is delayed until after the initial fallback
2704 // period but a retry is configured.
TEST_F(DnsTransactionTestWithMockTime,SlowHttpsResponse_TwoAttempts)2705 TEST_F(DnsTransactionTestWithMockTime, SlowHttpsResponse_TwoAttempts) {
2706 config_.doh_attempts = 2;
2707 ConfigureDohServers(false /* use_post */);
2708
2709 // Simulate a slow response by using an ERR_IO_PENDING read error to delay
2710 // until SequencedSocketData::Resume() is called.
2711 auto data = std::make_unique<DnsSocketData>(
2712 0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
2713 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
2714 data->AddReadError(ERR_IO_PENDING, ASYNC);
2715 data->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
2716 ASYNC);
2717 SequencedSocketData* sequenced_socket_data = data->GetProvider();
2718 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
2719
2720 TransactionHelper helper(kT0RecordCount);
2721 std::unique_ptr<DnsTransaction> transaction =
2722 transaction_factory_->CreateTransaction(
2723 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2724 SecureDnsMode::kSecure, resolve_context_.get(),
2725 false /* fast_timeout */);
2726
2727 helper.StartTransaction(std::move(transaction));
2728 base::RunLoop().RunUntilIdle();
2729 ASSERT_FALSE(helper.has_completed());
2730 ASSERT_TRUE(sequenced_socket_data->IsPaused());
2731
2732 // Another attempt configured, so transaction should not fail after initial
2733 // fallback period. Setup the second attempt to never receive a response.
2734 AddHangingQuery(kT0HostName, kT0Qtype,
2735 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2736 false /* enqueue_transaction_id */);
2737 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
2738 0 /* doh_server_index */, session_.get()));
2739 EXPECT_FALSE(helper.has_completed());
2740
2741 // Expect first attempt to continue in parallel with retry, so expect the
2742 // transaction to complete when the first query is allowed to resume.
2743 sequenced_socket_data->Resume();
2744 helper.RunUntilComplete();
2745 }
2746
2747 // Test for when a slow DoH response is delayed until after the full timeout
2748 // period.
TEST_F(DnsTransactionTestWithMockTime,HttpsTimeout)2749 TEST_F(DnsTransactionTestWithMockTime, HttpsTimeout) {
2750 config_.doh_attempts = 1;
2751 ConfigureDohServers(false /* use_post */);
2752
2753 // Assume fallback period is less than timeout.
2754 ASSERT_LT(resolve_context_->NextDohFallbackPeriod(0 /* doh_server_index */,
2755 session_.get()),
2756 resolve_context_->SecureTransactionTimeout(SecureDnsMode::kSecure,
2757 session_.get()));
2758
2759 AddHangingQuery(kT0HostName, kT0Qtype,
2760 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2761 false /* enqueue_transaction_id */);
2762
2763 TransactionHelper helper(ERR_DNS_TIMED_OUT);
2764 std::unique_ptr<DnsTransaction> transaction =
2765 transaction_factory_->CreateTransaction(
2766 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2767 SecureDnsMode::kSecure, resolve_context_.get(),
2768 false /* fast_timeout */);
2769 helper.StartTransaction(std::move(transaction));
2770 base::RunLoop().RunUntilIdle();
2771 ASSERT_FALSE(helper.has_completed());
2772
2773 // Stop a tiny bit short to ensure transaction doesn't finish early.
2774 const base::TimeDelta kTimeHoldback = base::Milliseconds(5);
2775 base::TimeDelta timeout = resolve_context_->SecureTransactionTimeout(
2776 SecureDnsMode::kSecure, session_.get());
2777 ASSERT_LT(kTimeHoldback, timeout);
2778 FastForwardBy(timeout - kTimeHoldback);
2779 EXPECT_FALSE(helper.has_completed());
2780
2781 FastForwardBy(kTimeHoldback);
2782 EXPECT_TRUE(helper.has_completed());
2783 }
2784
2785 // Test for when two slow DoH responses are delayed until after the full timeout
2786 // period.
TEST_F(DnsTransactionTestWithMockTime,HttpsTimeout2)2787 TEST_F(DnsTransactionTestWithMockTime, HttpsTimeout2) {
2788 config_.doh_attempts = 2;
2789 ConfigureDohServers(false /* use_post */);
2790
2791 // Assume fallback period is less than timeout.
2792 ASSERT_LT(resolve_context_->NextDohFallbackPeriod(0 /* doh_server_index */,
2793 session_.get()),
2794 resolve_context_->SecureTransactionTimeout(SecureDnsMode::kSecure,
2795 session_.get()));
2796
2797 AddHangingQuery(kT0HostName, kT0Qtype,
2798 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2799 false /* enqueue_transaction_id */);
2800 AddHangingQuery(kT0HostName, kT0Qtype,
2801 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2802 false /* enqueue_transaction_id */);
2803
2804 TransactionHelper helper(ERR_DNS_TIMED_OUT);
2805 std::unique_ptr<DnsTransaction> transaction =
2806 transaction_factory_->CreateTransaction(
2807 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2808 SecureDnsMode::kSecure, resolve_context_.get(),
2809 false /* fast_timeout */);
2810 helper.StartTransaction(std::move(transaction));
2811 base::RunLoop().RunUntilIdle();
2812 ASSERT_FALSE(helper.has_completed());
2813
2814 base::TimeDelta fallback_period = resolve_context_->NextDohFallbackPeriod(
2815 0 /* doh_server_index */, session_.get());
2816 FastForwardBy(fallback_period);
2817 EXPECT_FALSE(helper.has_completed());
2818
2819 // Timeout is from start of transaction, so need to keep track of the
2820 // remainder after other fast forwards.
2821 base::TimeDelta timeout = resolve_context_->SecureTransactionTimeout(
2822 SecureDnsMode::kSecure, session_.get());
2823 base::TimeDelta timeout_remainder = timeout - fallback_period;
2824
2825 // Fallback period for second attempt.
2826 fallback_period = resolve_context_->NextDohFallbackPeriod(
2827 0 /* doh_server_index */, session_.get());
2828 ASSERT_LT(fallback_period, timeout_remainder);
2829 FastForwardBy(fallback_period);
2830 EXPECT_FALSE(helper.has_completed());
2831 timeout_remainder -= fallback_period;
2832
2833 // Stop a tiny bit short to ensure transaction doesn't finish early.
2834 const base::TimeDelta kTimeHoldback = base::Milliseconds(5);
2835 ASSERT_LT(kTimeHoldback, timeout_remainder);
2836 FastForwardBy(timeout_remainder - kTimeHoldback);
2837 EXPECT_FALSE(helper.has_completed());
2838
2839 FastForwardBy(kTimeHoldback);
2840 EXPECT_TRUE(helper.has_completed());
2841 }
2842
2843 // Test for when attempt fallback periods go beyond the full timeout period.
TEST_F(DnsTransactionTestWithMockTime,LongHttpsTimeouts)2844 TEST_F(DnsTransactionTestWithMockTime, LongHttpsTimeouts) {
2845 const int kNumAttempts = 20;
2846 config_.doh_attempts = kNumAttempts;
2847 ConfigureDohServers(false /* use_post */);
2848
2849 // Assume sum of fallback periods is greater than timeout.
2850 ASSERT_GT(kNumAttempts * resolve_context_->NextDohFallbackPeriod(
2851 0 /* doh_server_index */, session_.get()),
2852 resolve_context_->SecureTransactionTimeout(SecureDnsMode::kSecure,
2853 session_.get()));
2854
2855 for (int i = 0; i < kNumAttempts; ++i) {
2856 AddHangingQuery(kT0HostName, kT0Qtype,
2857 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2858 false /* enqueue_transaction_id */);
2859 }
2860
2861 TransactionHelper helper(ERR_DNS_TIMED_OUT);
2862 std::unique_ptr<DnsTransaction> transaction =
2863 transaction_factory_->CreateTransaction(
2864 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2865 SecureDnsMode::kSecure, resolve_context_.get(),
2866 false /* fast_timeout */);
2867 helper.StartTransaction(std::move(transaction));
2868 base::RunLoop().RunUntilIdle();
2869 ASSERT_FALSE(helper.has_completed());
2870
2871 for (int i = 0; i < kNumAttempts - 1; ++i) {
2872 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
2873 0 /* doh_server_index */, session_.get()));
2874 EXPECT_FALSE(helper.has_completed());
2875 }
2876
2877 // Expect transaction to time out immediately after the last fallback period.
2878 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
2879 0 /* doh_server_index */, session_.get()));
2880 EXPECT_TRUE(helper.has_completed());
2881 }
2882
2883 // Test for when the last of multiple HTTPS attempts fails (SERVFAIL) before
2884 // a previous attempt succeeds.
TEST_F(DnsTransactionTestWithMockTime,LastHttpsAttemptFails)2885 TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFails) {
2886 config_.doh_attempts = 2;
2887 ConfigureDohServers(false /* use_post */);
2888
2889 // Simulate a slow response by using an ERR_IO_PENDING read error to delay
2890 // until SequencedSocketData::Resume() is called.
2891 auto data = std::make_unique<DnsSocketData>(
2892 0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
2893 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
2894 data->AddReadError(ERR_IO_PENDING, ASYNC);
2895 data->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
2896 ASYNC);
2897 SequencedSocketData* sequenced_socket_data = data->GetProvider();
2898 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
2899
2900 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
2901 SYNCHRONOUS, Transport::HTTPS,
2902 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2903 false /* enqueue_transaction_id */);
2904
2905 TransactionHelper helper(kT0RecordCount);
2906 std::unique_ptr<DnsTransaction> transaction =
2907 transaction_factory_->CreateTransaction(
2908 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2909 SecureDnsMode::kSecure, resolve_context_.get(),
2910 false /* fast_timeout */);
2911 helper.StartTransaction(std::move(transaction));
2912
2913 // Wait for one timeout period to start (and fail) the second attempt.
2914 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
2915 0 /* doh_server_index */, session_.get()));
2916 EXPECT_FALSE(helper.has_completed());
2917
2918 // Complete the first attempt and expect immediate success.
2919 sequenced_socket_data->Resume();
2920 helper.RunUntilComplete();
2921 }
2922
2923 // Test for when the last of multiple HTTPS attempts fails (SERVFAIL), and a
2924 // previous attempt never completes.
TEST_F(DnsTransactionTestWithMockTime,LastHttpsAttemptFails_Timeout)2925 TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFails_Timeout) {
2926 config_.doh_attempts = 2;
2927 ConfigureDohServers(false /* use_post */);
2928
2929 AddHangingQuery(kT0HostName, kT0Qtype,
2930 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2931 false /* enqueue_transaction_id */);
2932 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
2933 SYNCHRONOUS, Transport::HTTPS,
2934 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2935 false /* enqueue_transaction_id */);
2936
2937 TransactionHelper helper(ERR_DNS_TIMED_OUT);
2938 std::unique_ptr<DnsTransaction> transaction =
2939 transaction_factory_->CreateTransaction(
2940 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2941 SecureDnsMode::kSecure, resolve_context_.get(),
2942 false /* fast_timeout */);
2943
2944 helper.StartTransaction(std::move(transaction));
2945 base::RunLoop().RunUntilIdle();
2946 EXPECT_FALSE(helper.has_completed());
2947
2948 // Second attempt fails immediately after first fallback period, but because
2949 // fast timeout is disabled, the transaction will attempt to wait for the
2950 // first attempt.
2951 base::TimeDelta fallback_period = resolve_context_->NextDohFallbackPeriod(
2952 0 /* doh_server_index */, session_.get());
2953 FastForwardBy(fallback_period);
2954 EXPECT_FALSE(helper.has_completed());
2955
2956 // Timeout is from start of transaction, so need to keep track of the
2957 // remainder after other fast forwards.
2958 base::TimeDelta timeout = resolve_context_->SecureTransactionTimeout(
2959 SecureDnsMode::kSecure, session_.get());
2960 base::TimeDelta timeout_remainder = timeout - fallback_period;
2961
2962 // Stop a tiny bit short to ensure transaction doesn't finish early.
2963 const base::TimeDelta kTimeHoldback = base::Milliseconds(5);
2964 ASSERT_LT(kTimeHoldback, timeout_remainder);
2965 FastForwardBy(timeout_remainder - kTimeHoldback);
2966 EXPECT_FALSE(helper.has_completed());
2967
2968 FastForwardBy(kTimeHoldback);
2969 EXPECT_TRUE(helper.has_completed());
2970 }
2971
2972 // Test for when the last of multiple HTTPS attempts fails (SERVFAIL) before
2973 // a previous attempt can complete, but fast timeouts is enabled.
TEST_F(DnsTransactionTestWithMockTime,LastHttpsAttemptFails_FastTimeout)2974 TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFails_FastTimeout) {
2975 config_.doh_attempts = 2;
2976 ConfigureDohServers(false /* use_post */);
2977
2978 AddHangingQuery(kT0HostName, kT0Qtype,
2979 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2980 false /* enqueue_transaction_id */);
2981 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
2982 SYNCHRONOUS, Transport::HTTPS,
2983 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
2984 false /* enqueue_transaction_id */);
2985
2986 TransactionHelper helper(ERR_DNS_SERVER_FAILED);
2987 std::unique_ptr<DnsTransaction> transaction =
2988 transaction_factory_->CreateTransaction(
2989 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
2990 SecureDnsMode::kSecure, resolve_context_.get(),
2991 true /* fast_timeout */);
2992
2993 helper.StartTransaction(std::move(transaction));
2994 base::RunLoop().RunUntilIdle();
2995 EXPECT_FALSE(helper.has_completed());
2996
2997 // With fast timeout enabled, expect the transaction to complete with failure
2998 // immediately on failure of the last transaction.
2999 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
3000 0 /* doh_server_index */, session_.get()));
3001 EXPECT_TRUE(helper.has_completed());
3002 }
3003
3004 // Test for when the last of multiple HTTPS attempts fails (SERVFAIL) before
3005 // a previous attempt later fails as well.
TEST_F(DnsTransactionTestWithMockTime,LastHttpsAttemptFailsFirst)3006 TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFailsFirst) {
3007 config_.doh_attempts = 2;
3008 ConfigureDohServers(false /* use_post */);
3009
3010 // Simulate a slow response by using an ERR_IO_PENDING read error to delay
3011 // until SequencedSocketData::Resume() is called.
3012 auto data = std::make_unique<DnsSocketData>(
3013 0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
3014 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
3015 data->AddReadError(ERR_IO_PENDING, ASYNC);
3016 data->AddRcode(dns_protocol::kRcodeSERVFAIL, ASYNC);
3017 SequencedSocketData* sequenced_socket_data = data->GetProvider();
3018 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
3019
3020 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
3021 SYNCHRONOUS, Transport::HTTPS,
3022 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
3023 false /* enqueue_transaction_id */);
3024
3025 TransactionHelper helper(ERR_DNS_SERVER_FAILED);
3026 std::unique_ptr<DnsTransaction> transaction =
3027 transaction_factory_->CreateTransaction(
3028 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
3029 SecureDnsMode::kSecure, resolve_context_.get(),
3030 false /* fast_timeout */);
3031 helper.StartTransaction(std::move(transaction));
3032
3033 // Wait for one timeout period to start (and fail) the second attempt.
3034 FastForwardBy(resolve_context_->NextDohFallbackPeriod(
3035 0 /* doh_server_index */, session_.get()));
3036 EXPECT_FALSE(helper.has_completed());
3037
3038 // Complete the first attempt and expect immediate completion.
3039 sequenced_socket_data->Resume();
3040 helper.RunUntilComplete();
3041 }
3042
3043 // Test for when multiple HTTPS attempts fail (SERVFAIL) in order, making the
3044 // last started attempt also the last attempt to be pending.
TEST_F(DnsTransactionTestWithMockTime,LastHttpsAttemptFailsLast)3045 TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFailsLast) {
3046 config_.doh_attempts = 2;
3047 ConfigureDohServers(false /* use_post */);
3048
3049 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
3050 SYNCHRONOUS, Transport::HTTPS,
3051 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
3052 false /* enqueue_transaction_id */);
3053 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL,
3054 SYNCHRONOUS, Transport::HTTPS,
3055 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128, 0 /* id */,
3056 false /* enqueue_transaction_id */);
3057
3058 TransactionHelper helper(ERR_DNS_SERVER_FAILED);
3059 std::unique_ptr<DnsTransaction> transaction =
3060 transaction_factory_->CreateTransaction(
3061 kT0HostName, kT0Qtype, NetLogWithSource(), true /* secure */,
3062 SecureDnsMode::kSecure, resolve_context_.get(),
3063 false /* fast_timeout */);
3064 helper.StartTransaction(std::move(transaction));
3065
3066 // Expect both attempts will run quickly without waiting for fallbacks or
3067 // transaction timeout.
3068 helper.RunUntilComplete();
3069 }
3070
TEST_F(DnsTransactionTest,TcpLookup_UdpRetry)3071 TEST_F(DnsTransactionTest, TcpLookup_UdpRetry) {
3072 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3073 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3074 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
3075 std::size(kT0ResponseDatagram), ASYNC, Transport::TCP);
3076
3077 TransactionHelper helper0(kT0RecordCount);
3078 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3079 false /* secure */, resolve_context_.get());
3080 helper0.RunUntilComplete();
3081 }
3082
TEST_F(DnsTransactionTest,TcpLookup_UdpRetry_WithLog)3083 TEST_F(DnsTransactionTest, TcpLookup_UdpRetry_WithLog) {
3084 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3085 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3086 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
3087 std::size(kT0ResponseDatagram), ASYNC, Transport::TCP);
3088
3089 TransactionHelper helper0(kT0RecordCount);
3090 NetLogCountingObserver observer;
3091 NetLog::Get()->AddObserver(&observer, NetLogCaptureMode::kEverything);
3092 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3093 false /* secure */, resolve_context_.get());
3094 helper0.RunUntilComplete();
3095 EXPECT_EQ(observer.count(), 8);
3096 EXPECT_EQ(observer.dict_count(), 6);
3097 }
3098
TEST_F(DnsTransactionTest,TcpLookup_LowEntropy)3099 TEST_F(DnsTransactionTest, TcpLookup_LowEntropy) {
3100 socket_factory_->diverse_source_ports_ = false;
3101
3102 for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
3103 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
3104 std::size(kT0ResponseDatagram), ASYNC, Transport::UDP);
3105 }
3106
3107 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
3108 std::size(kT0ResponseDatagram), ASYNC, Transport::TCP);
3109
3110 for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
3111 TransactionHelper udp_helper(kT0RecordCount);
3112 udp_helper.StartTransaction(transaction_factory_.get(), kT0HostName,
3113 kT0Qtype, false /* secure */,
3114 resolve_context_.get());
3115 udp_helper.RunUntilComplete();
3116 }
3117
3118 ASSERT_TRUE(session_->udp_tracker()->low_entropy());
3119
3120 TransactionHelper helper0(kT0RecordCount);
3121 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3122 false /* secure */, resolve_context_.get());
3123 helper0.RunUntilComplete();
3124 EXPECT_TRUE(session_->udp_tracker()->low_entropy());
3125 }
3126
TEST_F(DnsTransactionTest,TCPFailure)3127 TEST_F(DnsTransactionTest, TCPFailure) {
3128 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3129 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3130 AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL, ASYNC,
3131 Transport::TCP);
3132
3133 TransactionHelper helper0(ERR_DNS_SERVER_FAILED);
3134 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3135 false /* secure */, resolve_context_.get());
3136 helper0.RunUntilComplete();
3137 ASSERT_NE(helper0.response(), nullptr);
3138 EXPECT_EQ(helper0.response()->rcode(), dns_protocol::kRcodeSERVFAIL);
3139 }
3140
TEST_F(DnsTransactionTest,TCPMalformed)3141 TEST_F(DnsTransactionTest, TCPMalformed) {
3142 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3143 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3144 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3145 ASYNC, Transport::TCP);
3146 // Valid response but length too short.
3147 // This must be truncated in the question section. The DnsResponse doesn't
3148 // examine the answer section until asked to parse it, so truncating it in
3149 // the answer section would result in the DnsTransaction itself succeeding.
3150 data->AddResponseWithLength(
3151 std::make_unique<DnsResponse>(
3152 reinterpret_cast<const char*>(kT0ResponseDatagram),
3153 std::size(kT0ResponseDatagram), 0),
3154 ASYNC, static_cast<uint16_t>(kT0QuerySize - 1));
3155 AddSocketData(std::move(data));
3156
3157 TransactionHelper helper0(ERR_DNS_MALFORMED_RESPONSE);
3158 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3159 false /* secure */, resolve_context_.get());
3160 helper0.RunUntilComplete();
3161 }
3162
TEST_F(DnsTransactionTestWithMockTime,TcpTimeout_UdpRetry)3163 TEST_F(DnsTransactionTestWithMockTime, TcpTimeout_UdpRetry) {
3164 ConfigureFactory();
3165 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3166 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3167 AddSocketData(std::make_unique<DnsSocketData>(
3168 1 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::TCP));
3169
3170 TransactionHelper helper0(ERR_DNS_TIMED_OUT);
3171 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3172 false /* secure */, resolve_context_.get());
3173 base::RunLoop().RunUntilIdle();
3174 EXPECT_FALSE(helper0.has_completed());
3175 FastForwardUntilNoTasksRemain();
3176 EXPECT_TRUE(helper0.has_completed());
3177 }
3178
TEST_F(DnsTransactionTestWithMockTime,TcpTimeout_LowEntropy)3179 TEST_F(DnsTransactionTestWithMockTime, TcpTimeout_LowEntropy) {
3180 ConfigureFactory();
3181 socket_factory_->diverse_source_ports_ = false;
3182
3183 for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
3184 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
3185 std::size(kT0ResponseDatagram), ASYNC, Transport::UDP);
3186 }
3187
3188 AddSocketData(std::make_unique<DnsSocketData>(
3189 1 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::TCP));
3190
3191 for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
3192 TransactionHelper udp_helper(kT0RecordCount);
3193 udp_helper.StartTransaction(transaction_factory_.get(), kT0HostName,
3194 kT0Qtype, false /* secure */,
3195 resolve_context_.get());
3196 udp_helper.RunUntilComplete();
3197 }
3198
3199 ASSERT_TRUE(session_->udp_tracker()->low_entropy());
3200
3201 TransactionHelper helper0(ERR_DNS_TIMED_OUT);
3202 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3203 false /* secure */, resolve_context_.get());
3204 base::RunLoop().RunUntilIdle();
3205 EXPECT_FALSE(helper0.has_completed());
3206 FastForwardUntilNoTasksRemain();
3207 EXPECT_TRUE(helper0.has_completed());
3208 }
3209
TEST_F(DnsTransactionTest,TCPReadReturnsZeroAsync)3210 TEST_F(DnsTransactionTest, TCPReadReturnsZeroAsync) {
3211 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3212 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3213 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3214 ASYNC, Transport::TCP);
3215 // Return all but the last byte of the response.
3216 data->AddResponseWithLength(
3217 std::make_unique<DnsResponse>(
3218 reinterpret_cast<const char*>(kT0ResponseDatagram),
3219 std::size(kT0ResponseDatagram) - 1, 0),
3220 ASYNC, static_cast<uint16_t>(std::size(kT0ResponseDatagram)));
3221 // Then return a 0-length read.
3222 data->AddReadError(0, ASYNC);
3223 AddSocketData(std::move(data));
3224
3225 TransactionHelper helper0(ERR_CONNECTION_CLOSED);
3226 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3227 false /* secure */, resolve_context_.get());
3228 helper0.RunUntilComplete();
3229 }
3230
TEST_F(DnsTransactionTest,TCPReadReturnsZeroSynchronous)3231 TEST_F(DnsTransactionTest, TCPReadReturnsZeroSynchronous) {
3232 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3233 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3234 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3235 ASYNC, Transport::TCP);
3236 // Return all but the last byte of the response.
3237 data->AddResponseWithLength(
3238 std::make_unique<DnsResponse>(
3239 reinterpret_cast<const char*>(kT0ResponseDatagram),
3240 std::size(kT0ResponseDatagram) - 1, 0),
3241 SYNCHRONOUS, static_cast<uint16_t>(std::size(kT0ResponseDatagram)));
3242 // Then return a 0-length read.
3243 data->AddReadError(0, SYNCHRONOUS);
3244 AddSocketData(std::move(data));
3245
3246 TransactionHelper helper0(ERR_CONNECTION_CLOSED);
3247 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3248 false /* secure */, resolve_context_.get());
3249 helper0.RunUntilComplete();
3250 }
3251
TEST_F(DnsTransactionTest,TCPConnectionClosedAsync)3252 TEST_F(DnsTransactionTest, TCPConnectionClosedAsync) {
3253 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3254 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3255 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3256 ASYNC, Transport::TCP);
3257 data->AddReadError(ERR_CONNECTION_CLOSED, ASYNC);
3258 AddSocketData(std::move(data));
3259
3260 TransactionHelper helper0(ERR_CONNECTION_CLOSED);
3261 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3262 false /* secure */, resolve_context_.get());
3263 helper0.RunUntilComplete();
3264 }
3265
TEST_F(DnsTransactionTest,TCPConnectionClosedSynchronous)3266 TEST_F(DnsTransactionTest, TCPConnectionClosedSynchronous) {
3267 AddAsyncQueryAndRcode(kT0HostName, kT0Qtype,
3268 dns_protocol::kRcodeNOERROR | dns_protocol::kFlagTC);
3269 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3270 ASYNC, Transport::TCP);
3271 data->AddReadError(ERR_CONNECTION_CLOSED, SYNCHRONOUS);
3272 AddSocketData(std::move(data));
3273
3274 TransactionHelper helper0(ERR_CONNECTION_CLOSED);
3275 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3276 false /* secure */, resolve_context_.get());
3277 helper0.RunUntilComplete();
3278 }
3279
TEST_F(DnsTransactionTest,MismatchedThenNxdomainThenTCP)3280 TEST_F(DnsTransactionTest, MismatchedThenNxdomainThenTCP) {
3281 config_.attempts = 2;
3282 ConfigureFactory();
3283 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3284 SYNCHRONOUS, Transport::UDP);
3285 // First attempt gets a mismatched response.
3286 data->AddResponseData(kT1ResponseDatagram, std::size(kT1ResponseDatagram),
3287 SYNCHRONOUS);
3288 // Second read from first attempt gets TCP required.
3289 data->AddRcode(dns_protocol::kFlagTC, ASYNC);
3290 AddSocketData(std::move(data));
3291 // Second attempt gets NXDOMAIN, which happens before the TCP required.
3292 AddSyncQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeNXDOMAIN);
3293
3294 TransactionHelper helper0(ERR_NAME_NOT_RESOLVED);
3295 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3296 false /* secure */, resolve_context_.get());
3297 helper0.RunUntilComplete();
3298 }
3299
TEST_F(DnsTransactionTest,MismatchedThenOkThenTCP)3300 TEST_F(DnsTransactionTest, MismatchedThenOkThenTCP) {
3301 config_.attempts = 2;
3302 ConfigureFactory();
3303 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3304 SYNCHRONOUS, Transport::UDP);
3305 // First attempt gets a mismatched response.
3306 data->AddResponseData(kT1ResponseDatagram, std::size(kT1ResponseDatagram),
3307 SYNCHRONOUS);
3308 // Second read from first attempt gets TCP required.
3309 data->AddRcode(dns_protocol::kFlagTC, ASYNC);
3310 AddSocketData(std::move(data));
3311 // Second attempt gets a valid response, which happens before the TCP
3312 // required.
3313 AddSyncQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype,
3314 kT0ResponseDatagram, std::size(kT0ResponseDatagram));
3315
3316 TransactionHelper helper0(kT0RecordCount);
3317 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3318 false /* secure */, resolve_context_.get());
3319 helper0.RunUntilComplete();
3320 }
3321
TEST_F(DnsTransactionTest,MismatchedThenRefusedThenTCP)3322 TEST_F(DnsTransactionTest, MismatchedThenRefusedThenTCP) {
3323 // Set up the expected sequence of events:
3324 // 1) First attempt (UDP) gets a synchronous mismatched response. On such
3325 // malformed responses, DnsTransaction triggers an immediate retry to read
3326 // again from the socket within the same "attempt".
3327 // 2) Second read (within the first attempt) starts. Test is configured to
3328 // give an asynchronous TCP required response which will complete later.
3329 // On asynchronous action after a malformed response, the attempt will
3330 // immediately produce a retriable error result while the retry continues,
3331 // thus forking the running attempts.
3332 // 3) Error result triggers a second attempt (UDP) which test gives a
3333 // synchronous ERR_CONNECTION_REFUSED, which is a retriable error, but
3334 // DnsTransaction has exhausted max retries (2 attempts), so this result
3335 // gets posted as the result of the transaction and other running attempts
3336 // should be cancelled.
3337 // 4) First attempt should be cancelled when the transaction result is posted,
3338 // so first attempt's second read should never complete. If it did
3339 // complete, it would complete with a TCP-required error, and
3340 // DnsTransaction would start a TCP attempt and clear previous attempts. It
3341 // would be very bad if that then cleared the attempt posted as the final
3342 // result, as result handling does not expect that memory to go away.
3343
3344 config_.attempts = 2;
3345 ConfigureFactory();
3346
3347 // Attempt 1.
3348 auto data = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName, kT0Qtype,
3349 SYNCHRONOUS, Transport::UDP);
3350 data->AddResponseData(kT1ResponseDatagram, std::size(kT1ResponseDatagram),
3351 SYNCHRONOUS);
3352 data->AddRcode(dns_protocol::kFlagTC, ASYNC);
3353 AddSocketData(std::move(data));
3354
3355 // Attempt 2.
3356 AddQueryAndErrorResponse(0 /* id */, kT0HostName, kT0Qtype,
3357 ERR_CONNECTION_REFUSED, SYNCHRONOUS, Transport::UDP);
3358
3359 TransactionHelper helper0(ERR_CONNECTION_REFUSED);
3360 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3361 false /* secure */, resolve_context_.get());
3362 helper0.RunUntilComplete();
3363 }
3364
TEST_F(DnsTransactionTest,InvalidQuery)3365 TEST_F(DnsTransactionTest, InvalidQuery) {
3366 ConfigureFactory();
3367
3368 TransactionHelper helper0(ERR_INVALID_ARGUMENT);
3369 helper0.StartTransaction(transaction_factory_.get(), ".",
3370 dns_protocol::kTypeA, false /* secure */,
3371 resolve_context_.get());
3372 helper0.RunUntilComplete();
3373
3374 TransactionHelper helper1(ERR_INVALID_ARGUMENT);
3375 helper1.StartTransaction(transaction_factory_.get(), "foo,bar.com",
3376 dns_protocol::kTypeA, false /* secure */,
3377 resolve_context_.get());
3378 helper1.RunUntilComplete();
3379 }
3380
TEST_F(DnsTransactionTest,CheckAsync)3381 TEST_F(DnsTransactionTest, CheckAsync) {
3382 ConfigureDohServers(false /* use_post */);
3383 AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram,
3384 std::size(kT0ResponseDatagram), SYNCHRONOUS,
3385 Transport::HTTPS, nullptr /* opt_rdata */,
3386 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3387 false /* enqueue_transaction_id */);
3388 TransactionHelper helper0(kT0RecordCount);
3389 bool started = false;
3390 SetUrlRequestStartedCallback(
3391 base::BindLambdaForTesting([&] { started = true; }));
3392 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3393 true /* secure */, resolve_context_.get());
3394 EXPECT_FALSE(started);
3395 EXPECT_FALSE(helper0.has_completed());
3396 helper0.RunUntilComplete();
3397 EXPECT_TRUE(started);
3398 }
3399
TEST_F(DnsTransactionTest,EarlyCancel)3400 TEST_F(DnsTransactionTest, EarlyCancel) {
3401 ConfigureDohServers(false /* use_post */);
3402 TransactionHelper helper0(0);
3403 SetUrlRequestStartedCallback(base::BindRepeating([] { FAIL(); }));
3404 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
3405 true /* secure */, resolve_context_.get());
3406 EXPECT_FALSE(helper0.has_completed());
3407 helper0.Cancel();
3408 base::RunLoop().RunUntilIdle();
3409 }
3410
TEST_F(DnsTransactionTestWithMockTime,ProbeUntilSuccess)3411 TEST_F(DnsTransactionTestWithMockTime, ProbeUntilSuccess) {
3412 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3413 false /* make_available */);
3414 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3415 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3416 Transport::HTTPS, nullptr /* opt_rdata */,
3417 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3418 false /* enqueue_transaction_id */);
3419 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3420 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3421 Transport::HTTPS, nullptr /* opt_rdata */,
3422 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3423 false /* enqueue_transaction_id */);
3424 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3425 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3426 nullptr /* opt_rdata */,
3427 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3428 false /* enqueue_transaction_id */);
3429
3430 std::unique_ptr<DnsProbeRunner> runner =
3431 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3432 runner->Start(false /* network_change */);
3433
3434 // The first probe happens without any delay.
3435 RunUntilIdle();
3436 std::unique_ptr<DnsServerIterator> doh_itr = resolve_context_->GetDohIterator(
3437 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3438
3439 EXPECT_FALSE(doh_itr->AttemptAvailable());
3440
3441 // Expect the server to still be unavailable after the second probe.
3442 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3443 EXPECT_FALSE(doh_itr->AttemptAvailable());
3444
3445 // Expect the server to be available after the successful third probe.
3446 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3447 ASSERT_TRUE(doh_itr->AttemptAvailable());
3448 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
3449 }
3450
3451 // Test that if a probe attempt hangs, additional probes will still run on
3452 // schedule
TEST_F(DnsTransactionTestWithMockTime,HungProbe)3453 TEST_F(DnsTransactionTestWithMockTime, HungProbe) {
3454 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3455 false /* make_available */);
3456
3457 // Create a socket data to first return ERR_IO_PENDING. This will pause the
3458 // probe and not return the error until SequencedSocketData::Resume() is
3459 // called.
3460 auto data = std::make_unique<DnsSocketData>(
3461 0 /* id */, kT4HostName, kT4Qtype, ASYNC, Transport::HTTPS,
3462 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
3463 data->AddReadError(ERR_IO_PENDING, ASYNC);
3464 data->AddReadError(ERR_CONNECTION_REFUSED, ASYNC);
3465 data->AddResponseData(kT4ResponseDatagram, std::size(kT4ResponseDatagram),
3466 ASYNC);
3467 SequencedSocketData* sequenced_socket_data = data->GetProvider();
3468 AddSocketData(std::move(data), false /* enqueue_transaction_id */);
3469
3470 // Add success for second probe.
3471 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3472 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3473 nullptr /* opt_rdata */,
3474 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3475 false /* enqueue_transaction_id */);
3476
3477 std::unique_ptr<DnsProbeRunner> runner =
3478 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3479 runner->Start(false /* network_change */);
3480
3481 // The first probe starts without any delay, but doesn't finish.
3482 RunUntilIdle();
3483 EXPECT_FALSE(resolve_context_->GetDohServerAvailability(
3484 0u /* doh_server_index */, session_.get()));
3485
3486 // Second probe succeeds.
3487 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3488 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3489 0u /* doh_server_index */, session_.get()));
3490
3491 // Probe runner self-cancels on next cycle.
3492 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3493 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3494
3495 // Expect no effect when the hung probe wakes up and fails.
3496 sequenced_socket_data->Resume();
3497 RunUntilIdle();
3498 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3499 0u /* doh_server_index */, session_.get()));
3500 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3501 }
3502
TEST_F(DnsTransactionTestWithMockTime,ProbeMultipleServers)3503 TEST_F(DnsTransactionTestWithMockTime, ProbeMultipleServers) {
3504 ConfigureDohServers(true /* use_post */, 2 /* num_doh_servers */,
3505 false /* make_available */);
3506 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3507 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3508 nullptr /* opt_rdata */,
3509 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3510 false /* enqueue_transaction_id */);
3511 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3512 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3513 Transport::HTTPS, nullptr /* opt_rdata */,
3514 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3515 false /* enqueue_transaction_id */);
3516 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3517 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3518 nullptr /* opt_rdata */,
3519 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3520 false /* enqueue_transaction_id */);
3521
3522 ASSERT_FALSE(resolve_context_->GetDohServerAvailability(
3523 0u /* doh_server_index */, session_.get()));
3524 ASSERT_FALSE(resolve_context_->GetDohServerAvailability(
3525 1u /* doh_server_index */, session_.get()));
3526
3527 std::unique_ptr<DnsProbeRunner> runner =
3528 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3529 runner->Start(true /* network_change */);
3530
3531 // The first probes happens without any delay and succeeds for only one server
3532 RunUntilIdle();
3533 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3534 0u /* doh_server_index */, session_.get()));
3535 EXPECT_FALSE(resolve_context_->GetDohServerAvailability(
3536 1u /* doh_server_index */, session_.get()));
3537
3538 // On second round of probing, probes for first server should self-cancel and
3539 // second server should become available.
3540 FastForwardBy(
3541 runner->GetDelayUntilNextProbeForTest(0u /* doh_server_index */));
3542 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(0u /* doh_server_index */),
3543 base::TimeDelta());
3544 FastForwardBy(
3545 runner->GetDelayUntilNextProbeForTest(1u /* doh_server_index */));
3546 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3547 1u /* doh_server_index */, session_.get()));
3548
3549 // Expect server 2 probes to self-cancel on next cycle.
3550 FastForwardBy(runner->GetDelayUntilNextProbeForTest(1u));
3551 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(1u), base::TimeDelta());
3552 }
3553
TEST_F(DnsTransactionTestWithMockTime,MultipleProbeRunners)3554 TEST_F(DnsTransactionTestWithMockTime, MultipleProbeRunners) {
3555 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3556 false /* make_available */);
3557 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3558 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3559 nullptr /* opt_rdata */,
3560 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3561 false /* enqueue_transaction_id */);
3562 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3563 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3564 nullptr /* opt_rdata */,
3565 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3566 false /* enqueue_transaction_id */);
3567
3568 std::unique_ptr<DnsProbeRunner> runner1 =
3569 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3570 std::unique_ptr<DnsProbeRunner> runner2 =
3571 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3572 runner1->Start(true /* network_change */);
3573 runner2->Start(true /* network_change */);
3574
3575 // The first two probes (one for each runner) happen without any delay
3576 // and mark the first server good.
3577 RunUntilIdle();
3578 {
3579 std::unique_ptr<DnsServerIterator> doh_itr =
3580 resolve_context_->GetDohIterator(
3581 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3582
3583 ASSERT_TRUE(doh_itr->AttemptAvailable());
3584 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
3585 }
3586
3587 // Both probes expected to self-cancel on next scheduled run.
3588 FastForwardBy(runner1->GetDelayUntilNextProbeForTest(0));
3589 FastForwardBy(runner2->GetDelayUntilNextProbeForTest(0));
3590 EXPECT_EQ(runner1->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3591 EXPECT_EQ(runner2->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3592 }
3593
TEST_F(DnsTransactionTestWithMockTime,MultipleProbeRunners_SeparateContexts)3594 TEST_F(DnsTransactionTestWithMockTime, MultipleProbeRunners_SeparateContexts) {
3595 // Each RequestContext uses its own transient IsolationInfo. Since there's
3596 // typically only one RequestContext per URLRequestContext, there's no
3597 // advantage in using the same IsolationInfo across RequestContexts.
3598 set_expect_multiple_isolation_infos(true);
3599
3600 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3601 false /* make_available */);
3602 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3603 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3604 nullptr /* opt_rdata */,
3605 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3606 false /* enqueue_transaction_id */);
3607 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3608 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3609 Transport::HTTPS, nullptr /* opt_rdata */,
3610 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3611 false /* enqueue_transaction_id */);
3612 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3613 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3614 nullptr /* opt_rdata */,
3615 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3616 false /* enqueue_transaction_id */);
3617
3618 auto request_context2 = CreateTestURLRequestContextBuilder()->Build();
3619 ResolveContext context2(request_context2.get(), false /* enable_caching */);
3620 context2.InvalidateCachesAndPerSessionData(session_.get(),
3621 false /* network_change */);
3622
3623 std::unique_ptr<DnsProbeRunner> runner1 =
3624 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3625 std::unique_ptr<DnsProbeRunner> runner2 =
3626 transaction_factory_->CreateDohProbeRunner(&context2);
3627 runner1->Start(false /* network_change */);
3628 runner2->Start(false /* network_change */);
3629
3630 // The first two probes (one for each runner) happen without any delay.
3631 // Probe for first context succeeds and second fails.
3632 RunUntilIdle();
3633 {
3634 std::unique_ptr<DnsServerIterator> doh_itr =
3635 resolve_context_->GetDohIterator(
3636 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3637
3638 ASSERT_TRUE(doh_itr->AttemptAvailable());
3639 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
3640 }
3641 {
3642 std::unique_ptr<DnsServerIterator> doh_itr2 = context2.GetDohIterator(
3643 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3644
3645 EXPECT_FALSE(doh_itr2->AttemptAvailable());
3646 }
3647
3648 // First probe runner expected to be compete and self-cancel on next run.
3649 FastForwardBy(runner1->GetDelayUntilNextProbeForTest(0));
3650 EXPECT_EQ(runner1->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3651
3652 // Expect second runner to succeed on its second probe.
3653 FastForwardBy(runner2->GetDelayUntilNextProbeForTest(0));
3654 {
3655 std::unique_ptr<DnsServerIterator> doh_itr2 = context2.GetDohIterator(
3656 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3657
3658 ASSERT_TRUE(doh_itr2->AttemptAvailable());
3659 EXPECT_EQ(doh_itr2->GetNextAttemptIndex(), 0u);
3660 }
3661 FastForwardBy(runner2->GetDelayUntilNextProbeForTest(0));
3662 EXPECT_EQ(runner2->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3663 }
3664
TEST_F(DnsTransactionTestWithMockTime,CancelDohProbeOnDestruction)3665 TEST_F(DnsTransactionTestWithMockTime, CancelDohProbeOnDestruction) {
3666 ConfigureDohServers(/*use_post=*/true, /*num_doh_servers=*/1,
3667 /*make_available=*/false);
3668 AddQueryAndErrorResponse(/*id=*/0, kT4HostName, kT4Qtype,
3669 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3670 Transport::HTTPS, /*opt_rdata=*/nullptr,
3671 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3672 /*enqueue_transaction_id=*/false);
3673 AddQueryAndErrorResponse(/*id=*/0, kT4HostName, kT4Qtype,
3674 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3675 Transport::HTTPS, /*opt_rdata=*/nullptr,
3676 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3677 /* enqueue_transaction_id=*/false);
3678
3679 std::unique_ptr<DnsProbeRunner> runner =
3680 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3681 runner->Start(/*network_change=*/false);
3682
3683 // The first probe happens without any delay.
3684 RunUntilIdle();
3685 std::unique_ptr<DnsServerIterator> doh_itr = resolve_context_->GetDohIterator(
3686 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3687
3688 EXPECT_FALSE(doh_itr->AttemptAvailable());
3689
3690 // Expect the server to still be unavailable after the second probe.
3691 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3692
3693 EXPECT_FALSE(doh_itr->AttemptAvailable());
3694
3695 base::TimeDelta next_delay = runner->GetDelayUntilNextProbeForTest(0);
3696 runner.reset();
3697
3698 // Server stays unavailable because probe canceled before (non-existent)
3699 // success. No success result is added, so this FastForward will cause a
3700 // failure if probes attempt to run.
3701 FastForwardBy(next_delay);
3702
3703 EXPECT_FALSE(doh_itr->AttemptAvailable());
3704 }
3705
TEST_F(DnsTransactionTestWithMockTime,CancelDohProbeOnContextDestruction)3706 TEST_F(DnsTransactionTestWithMockTime, CancelDohProbeOnContextDestruction) {
3707 ConfigureDohServers(/*use_post=*/true, /*num_doh_servers=*/1,
3708 /*make_available=*/false);
3709 AddQueryAndErrorResponse(/*id=*/0, kT4HostName, kT4Qtype,
3710 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3711 Transport::HTTPS, /*opt_rdata=*/nullptr,
3712 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3713 /*enqueue_transaction_id=*/false);
3714 AddQueryAndErrorResponse(/*id=*/0, kT4HostName, kT4Qtype,
3715 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3716 Transport::HTTPS, /*opt_rdata=*/nullptr,
3717 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3718 /* enqueue_transaction_id=*/false);
3719
3720 std::unique_ptr<DnsProbeRunner> runner =
3721 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3722 runner->Start(/*network_change=*/false);
3723
3724 // The first probe happens without any delay.
3725 RunUntilIdle();
3726 std::unique_ptr<DnsServerIterator> doh_itr = resolve_context_->GetDohIterator(
3727 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3728
3729 EXPECT_FALSE(doh_itr->AttemptAvailable());
3730
3731 // Expect the server to still be unavailable after the second probe.
3732 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3733
3734 EXPECT_FALSE(doh_itr->AttemptAvailable());
3735
3736 base::TimeDelta next_delay = runner->GetDelayUntilNextProbeForTest(0);
3737 resolve_context_.reset();
3738
3739 // The probe detects that the context no longer exists and stops running.
3740 FastForwardBy(next_delay);
3741
3742 // There are no more probes to run.
3743 EXPECT_EQ(base::TimeDelta(), runner->GetDelayUntilNextProbeForTest(0));
3744 }
3745
TEST_F(DnsTransactionTestWithMockTime,CancelOneOfMultipleProbeRunners)3746 TEST_F(DnsTransactionTestWithMockTime, CancelOneOfMultipleProbeRunners) {
3747 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3748 false /* make_available */);
3749 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3750 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3751 Transport::HTTPS, nullptr /* opt_rdata */,
3752 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3753 false /* enqueue_transaction_id */);
3754 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3755 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3756 Transport::HTTPS, nullptr /* opt_rdata */,
3757 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3758 false /* enqueue_transaction_id */);
3759 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3760 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3761 nullptr /* opt_rdata */,
3762 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3763 false /* enqueue_transaction_id */);
3764
3765 std::unique_ptr<DnsProbeRunner> runner1 =
3766 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3767 std::unique_ptr<DnsProbeRunner> runner2 =
3768 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3769 runner1->Start(true /* network_change */);
3770 runner2->Start(true /* network_change */);
3771
3772 // The first two probes (one for each runner) happen without any delay.
3773 RunUntilIdle();
3774 std::unique_ptr<DnsServerIterator> doh_itr = resolve_context_->GetDohIterator(
3775 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3776
3777 EXPECT_FALSE(doh_itr->AttemptAvailable());
3778 EXPECT_GT(runner1->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3779 EXPECT_GT(runner2->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3780
3781 // Cancel only one probe runner.
3782 runner1.reset();
3783
3784 // Expect the server to be available after the successful third probe.
3785 FastForwardBy(runner2->GetDelayUntilNextProbeForTest(0));
3786
3787 ASSERT_TRUE(doh_itr->AttemptAvailable());
3788 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
3789 FastForwardBy(runner2->GetDelayUntilNextProbeForTest(0));
3790 EXPECT_EQ(runner2->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3791 }
3792
TEST_F(DnsTransactionTestWithMockTime,CancelAllOfMultipleProbeRunners)3793 TEST_F(DnsTransactionTestWithMockTime, CancelAllOfMultipleProbeRunners) {
3794 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3795 false /* make_available */);
3796 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3797 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3798 Transport::HTTPS, nullptr /* opt_rdata */,
3799 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3800 false /* enqueue_transaction_id */);
3801 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3802 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3803 Transport::HTTPS, nullptr /* opt_rdata */,
3804 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3805 false /* enqueue_transaction_id */);
3806
3807 std::unique_ptr<DnsProbeRunner> runner1 =
3808 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3809 std::unique_ptr<DnsProbeRunner> runner2 =
3810 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3811 runner1->Start(false /* network_change */);
3812 runner2->Start(false /* network_change */);
3813
3814 // The first two probes (one for each runner) happen without any delay.
3815 RunUntilIdle();
3816 std::unique_ptr<DnsServerIterator> doh_itr = resolve_context_->GetDohIterator(
3817 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3818
3819 EXPECT_FALSE(doh_itr->AttemptAvailable());
3820 EXPECT_GT(runner1->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3821 EXPECT_GT(runner2->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3822
3823 base::TimeDelta next_delay = runner1->GetDelayUntilNextProbeForTest(0);
3824 runner1.reset();
3825 runner2.reset();
3826
3827 // Server stays unavailable because probe canceled before (non-existent)
3828 // success. No success result is added, so this FastForward will cause a
3829 // failure if probes attempt to run.
3830 FastForwardBy(next_delay);
3831 EXPECT_FALSE(doh_itr->AttemptAvailable());
3832 }
3833
TEST_F(DnsTransactionTestWithMockTime,CancelDohProbe_AfterSuccess)3834 TEST_F(DnsTransactionTestWithMockTime, CancelDohProbe_AfterSuccess) {
3835 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3836 false /* make_available */);
3837 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3838 std::size(kT4ResponseDatagram), SYNCHRONOUS,
3839 Transport::HTTPS, nullptr /* opt_rdata */,
3840 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3841 false /* enqueue_transaction_id */);
3842
3843 std::unique_ptr<DnsProbeRunner> runner =
3844 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3845 runner->Start(true /* network_change */);
3846
3847 // The first probe happens without any delay, and immediately succeeds.
3848 RunUntilIdle();
3849 {
3850 std::unique_ptr<DnsServerIterator> doh_itr =
3851 resolve_context_->GetDohIterator(
3852 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3853
3854 ASSERT_TRUE(doh_itr->AttemptAvailable());
3855 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
3856 }
3857
3858 runner.reset();
3859
3860 // No change expected after cancellation.
3861 RunUntilIdle();
3862 {
3863 std::unique_ptr<DnsServerIterator> doh_itr =
3864 resolve_context_->GetDohIterator(
3865 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3866
3867 ASSERT_TRUE(doh_itr->AttemptAvailable());
3868 EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
3869 }
3870 }
3871
TEST_F(DnsTransactionTestWithMockTime,DestroyFactoryAfterStartingDohProbe)3872 TEST_F(DnsTransactionTestWithMockTime, DestroyFactoryAfterStartingDohProbe) {
3873 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3874 false /* make_available */);
3875 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3876 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3877 Transport::HTTPS, nullptr /* opt_rdata */,
3878 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3879 false /* enqueue_transaction_id */);
3880
3881 std::unique_ptr<DnsProbeRunner> runner =
3882 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3883 runner->Start(false /* network_change */);
3884
3885 // The first probe happens without any delay.
3886 RunUntilIdle();
3887 std::unique_ptr<DnsServerIterator> doh_itr = resolve_context_->GetDohIterator(
3888 session_->config(), SecureDnsMode::kAutomatic, session_.get());
3889
3890 EXPECT_FALSE(doh_itr->AttemptAvailable());
3891
3892 // Destroy factory and session.
3893 transaction_factory_.reset();
3894 ASSERT_TRUE(session_->HasOneRef());
3895 session_.reset();
3896
3897 // Probe should not encounter issues and should stop running.
3898 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3899 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(0), base::TimeDelta());
3900 }
3901
TEST_F(DnsTransactionTestWithMockTime,StartWhileRunning)3902 TEST_F(DnsTransactionTestWithMockTime, StartWhileRunning) {
3903 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3904 false /* make_available */);
3905 AddQueryAndErrorResponse(0 /* id */, kT4HostName, kT4Qtype,
3906 ERR_CONNECTION_REFUSED, SYNCHRONOUS,
3907 Transport::HTTPS, nullptr /* opt_rdata */,
3908 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3909 false /* enqueue_transaction_id */);
3910 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3911 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3912 nullptr /* opt_rdata */,
3913 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3914 false /* enqueue_transaction_id */);
3915
3916 std::unique_ptr<DnsProbeRunner> runner =
3917 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3918 runner->Start(false /* network_change */);
3919
3920 // The first probe happens without any delay.
3921 RunUntilIdle();
3922 EXPECT_FALSE(resolve_context_->GetDohServerAvailability(
3923 0u /* doh_server_index */, session_.get()));
3924
3925 // Extra Start() call should have no effect because runner is already running.
3926 runner->Start(true /* network_change */);
3927 RunUntilIdle();
3928 EXPECT_FALSE(resolve_context_->GetDohServerAvailability(
3929 0u /* doh_server_index */, session_.get()));
3930
3931 // Expect the server to be available after the successful second probe.
3932 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0));
3933 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3934 0u /* doh_server_index */, session_.get()));
3935 }
3936
TEST_F(DnsTransactionTestWithMockTime,RestartFinishedProbe)3937 TEST_F(DnsTransactionTestWithMockTime, RestartFinishedProbe) {
3938 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3939 false /* make_available */);
3940 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3941 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3942 nullptr /* opt_rdata */,
3943 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3944 false /* enqueue_transaction_id */);
3945 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3946 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3947 nullptr /* opt_rdata */,
3948 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3949 false /* enqueue_transaction_id */);
3950
3951 std::unique_ptr<DnsProbeRunner> runner =
3952 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
3953 runner->Start(true /* network_change */);
3954
3955 // The first probe happens without any delay and succeeds.
3956 RunUntilIdle();
3957 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3958 0u /* doh_server_index */, session_.get()));
3959
3960 // Expect runner to self-cancel on next cycle.
3961 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0u));
3962 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(0u), base::TimeDelta());
3963
3964 // Mark server unavailabe and restart runner.
3965 for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
3966 resolve_context_->RecordServerFailure(0u /* server_index */,
3967 true /* is_doh_server */, ERR_FAILED,
3968 session_.get());
3969 }
3970 ASSERT_FALSE(resolve_context_->GetDohServerAvailability(
3971 0u /* doh_server_index */, session_.get()));
3972 runner->Start(false /* network_change */);
3973
3974 // Expect the server to be available again after a successful immediately-run
3975 // probe.
3976 RunUntilIdle();
3977 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
3978 0u /* doh_server_index */, session_.get()));
3979
3980 // Expect self-cancel again.
3981 FastForwardBy(runner->GetDelayUntilNextProbeForTest(0u));
3982 EXPECT_EQ(runner->GetDelayUntilNextProbeForTest(0u), base::TimeDelta());
3983 }
3984
3985 // Test that a probe runner keeps running on the same schedule if it completes
3986 // but the server is marked unavailable again before the next scheduled probe.
TEST_F(DnsTransactionTestWithMockTime,FastProbeRestart)3987 TEST_F(DnsTransactionTestWithMockTime, FastProbeRestart) {
3988 ConfigureDohServers(true /* use_post */, 1 /* num_doh_servers */,
3989 false /* make_available */);
3990 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3991 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3992 nullptr /* opt_rdata */,
3993 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3994 false /* enqueue_transaction_id */);
3995 AddQueryAndResponse(0 /* id */, kT4HostName, kT4Qtype, kT4ResponseDatagram,
3996 std::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS,
3997 nullptr /* opt_rdata */,
3998 DnsQuery::PaddingStrategy::BLOCK_LENGTH_128,
3999 false /* enqueue_transaction_id */);
4000
4001 std::unique_ptr<DnsProbeRunner> runner =
4002 transaction_factory_->CreateDohProbeRunner(resolve_context_.get());
4003 runner->Start(true /* network_change */);
4004
4005 // The first probe happens without any delay and succeeds.
4006 RunUntilIdle();
4007 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
4008 0u /* doh_server_index */, session_.get()));
4009
4010 base::TimeDelta scheduled_delay = runner->GetDelayUntilNextProbeForTest(0);
4011 EXPECT_GT(scheduled_delay, base::TimeDelta());
4012
4013 // Mark server unavailabe and restart runner. Note that restarting the runner
4014 // is unnecessary, but a Start() call should always happen on a server
4015 // becoming unavailable and might as well replecate real behavior for the
4016 // test.
4017 for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
4018 resolve_context_->RecordServerFailure(0u /* server_index */,
4019 true /* is_doh_server */, ERR_FAILED,
4020 session_.get());
4021 }
4022 ASSERT_FALSE(resolve_context_->GetDohServerAvailability(
4023 0u /* doh_server_index */, session_.get()));
4024 runner->Start(false /* network_change */);
4025
4026 // Probe should not run until scheduled delay.
4027 RunUntilIdle();
4028 EXPECT_FALSE(resolve_context_->GetDohServerAvailability(
4029 0u /* doh_server_index */, session_.get()));
4030
4031 // Expect the probe to run again and succeed after scheduled delay.
4032 FastForwardBy(scheduled_delay);
4033 EXPECT_TRUE(resolve_context_->GetDohServerAvailability(
4034 0u /* doh_server_index */, session_.get()));
4035 }
4036
4037 // Test that queries cannot be sent when they contain a too-long name.
4038 // Tests against incorrect name length validation, which is anti-pattern #3 from
4039 // the "NAME:WRECK" report:
4040 // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST_F(DnsTransactionTestWithMockTime,RejectsQueryingLongNames)4041 TEST_F(DnsTransactionTestWithMockTime, RejectsQueryingLongNames) {
4042 std::string long_dotted_name;
4043 while (long_dotted_name.size() <= dns_protocol::kMaxNameLength) {
4044 long_dotted_name.append("naaaaaamelabel.");
4045 }
4046 long_dotted_name.append("test");
4047
4048 TransactionHelper helper0(ERR_INVALID_ARGUMENT);
4049 helper0.StartTransaction(transaction_factory_.get(), long_dotted_name.c_str(),
4050 dns_protocol::kTypeA, false /* secure */,
4051 resolve_context_.get());
4052 helper0.RunUntilComplete();
4053 }
4054
4055 // Test that ERR_CONNECTION_REFUSED error after fallback of DnsTCPAttempt
4056 // should not cause DCHECK failure (https://crbug.com/1334250).
TEST_F(DnsTransactionTestWithMockTime,TcpConnectionRefusedAfterFallback)4057 TEST_F(DnsTransactionTestWithMockTime, TcpConnectionRefusedAfterFallback) {
4058 ConfigureNumServers(2);
4059 ConfigureFactory();
4060 socket_factory_->diverse_source_ports_ = false;
4061
4062 // Data for UDP attempts to set `low_entropy` flag.
4063 for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
4064 AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
4065 std::size(kT0ResponseDatagram), ASYNC, Transport::UDP);
4066 }
4067
4068 // Data for TCP attempt.
4069 auto data1 = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName,
4070 kT0Qtype, ASYNC, Transport::TCP);
4071 data1->AddReadError(ERR_IO_PENDING, ASYNC);
4072 data1->AddReadError(ERR_CONNECTION_REFUSED, ASYNC);
4073 SequencedSocketData* sequenced_socket_data1 = data1->GetProvider();
4074 AddSocketData(std::move(data1));
4075
4076 auto data2 = std::make_unique<DnsSocketData>(0 /* id */, kT0HostName,
4077 kT0Qtype, ASYNC, Transport::TCP);
4078 data2->AddReadError(ERR_IO_PENDING, ASYNC);
4079 data2->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
4080 ASYNC);
4081 SequencedSocketData* sequenced_socket_data2 = data2->GetProvider();
4082 AddSocketData(std::move(data2));
4083
4084 // DNS transactions for UDP attempts to set `low_entropy` flag.
4085 for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
4086 TransactionHelper udp_helper(kT0RecordCount);
4087 udp_helper.StartTransaction(transaction_factory_.get(), kT0HostName,
4088 kT0Qtype, false /* secure */,
4089 resolve_context_.get());
4090 udp_helper.RunUntilComplete();
4091 }
4092
4093 ASSERT_TRUE(session_->udp_tracker()->low_entropy());
4094
4095 // DNS transactions for TCP attempt.
4096 TransactionHelper helper0(kT0RecordCount);
4097 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
4098 false /* secure */, resolve_context_.get());
4099 base::RunLoop().RunUntilIdle();
4100 EXPECT_FALSE(helper0.has_completed());
4101
4102 base::TimeDelta timeout = resolve_context_->NextClassicFallbackPeriod(
4103 0 /* classic_server_index */, 0 /* attempt */, session_.get());
4104 FastForwardBy(timeout);
4105
4106 // Resume the first query.
4107 sequenced_socket_data1->Resume();
4108
4109 base::RunLoop().RunUntilIdle();
4110 EXPECT_FALSE(helper0.has_completed());
4111
4112 // Resume the second query.
4113 sequenced_socket_data2->Resume();
4114 base::RunLoop().RunUntilIdle();
4115
4116 EXPECT_TRUE(helper0.has_completed());
4117 }
4118
4119 // Test that ERR_CONNECTION_REFUSED error after fallback of DnsHTTPAttempt
4120 // should not cause DCHECK failure (https://crbug.com/1334250).
TEST_F(DnsTransactionTestWithMockTime,HttpsConnectionRefusedAfterFallback)4121 TEST_F(DnsTransactionTestWithMockTime, HttpsConnectionRefusedAfterFallback) {
4122 ConfigureDohServers(false /* use_post */, 2 /* num_doh_servers */,
4123 true /* make_available */);
4124
4125 auto data1 = std::make_unique<DnsSocketData>(
4126 0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
4127 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
4128 data1->AddReadError(ERR_IO_PENDING, ASYNC);
4129 data1->AddReadError(ERR_CONNECTION_REFUSED, ASYNC);
4130 SequencedSocketData* sequenced_socket_data1 = data1->GetProvider();
4131 AddSocketData(std::move(data1), false /* enqueue_transaction_id */);
4132
4133 auto data2 = std::make_unique<DnsSocketData>(
4134 0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
4135 nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128);
4136 data2->AddReadError(ERR_IO_PENDING, ASYNC);
4137 data2->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
4138 ASYNC);
4139 SequencedSocketData* sequenced_socket_data2 = data2->GetProvider();
4140 AddSocketData(std::move(data2), false /* enqueue_transaction_id */);
4141
4142 TransactionHelper helper0(kT0RecordCount);
4143 helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
4144 true /* secure */, resolve_context_.get());
4145 base::RunLoop().RunUntilIdle();
4146 EXPECT_FALSE(helper0.has_completed());
4147
4148 base::TimeDelta timeout = resolve_context_->NextDohFallbackPeriod(
4149 0 /* doh_server_index */, session_.get());
4150 FastForwardBy(timeout);
4151
4152 // Resume the first query.
4153 sequenced_socket_data1->Resume();
4154
4155 base::RunLoop().RunUntilIdle();
4156 EXPECT_FALSE(helper0.has_completed());
4157
4158 // Resume the second query.
4159 sequenced_socket_data2->Resume();
4160
4161 EXPECT_TRUE(helper0.has_completed());
4162 }
4163
4164 } // namespace
4165
4166 } // namespace net
4167