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