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