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