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