xref: /aosp_15_r20/external/cronet/net/dns/dns_test_util.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_test_util.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <cstdint>
8*6777b538SAndroid Build Coastguard Worker #include <optional>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker #include <string_view>
11*6777b538SAndroid Build Coastguard Worker #include <utility>
12*6777b538SAndroid Build Coastguard Worker #include <vector>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/numerics/byte_conversions.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/sys_byteorder.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/test/test_timeouts.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/types/optional_util.h"
28*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
29*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_address.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_endpoint.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/dns/address_sorter.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_hosts.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_names_util.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_query.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_session.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/dns/mock_host_resolver.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_over_https_server_config.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/dns/resolve_context.h"
40*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock-matchers.h"
41*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
42*6777b538SAndroid Build Coastguard Worker #include "url/scheme_host_port.h"
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker namespace net {
45*6777b538SAndroid Build Coastguard Worker namespace {
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker const uint8_t kMalformedResponseHeader[] = {
48*6777b538SAndroid Build Coastguard Worker     // Header
49*6777b538SAndroid Build Coastguard Worker     0x00, 0x14,  // Arbitrary ID
50*6777b538SAndroid Build Coastguard Worker     0x81, 0x80,  // Standard query response, RA, no error
51*6777b538SAndroid Build Coastguard Worker     0x00, 0x01,  // 1 question
52*6777b538SAndroid Build Coastguard Worker     0x00, 0x01,  // 1 RR (answers)
53*6777b538SAndroid Build Coastguard Worker     0x00, 0x00,  // 0 authority RRs
54*6777b538SAndroid Build Coastguard Worker     0x00, 0x00,  // 0 additional RRs
55*6777b538SAndroid Build Coastguard Worker };
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker // Create a response containing a valid question (as would normally be validated
58*6777b538SAndroid Build Coastguard Worker // in DnsTransaction) but completely missing a header-declared answer.
CreateMalformedResponse(std::string hostname,uint16_t type)59*6777b538SAndroid Build Coastguard Worker DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
60*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<uint8_t>> dns_name =
61*6777b538SAndroid Build Coastguard Worker       dns_names_util::DottedNameToNetwork(hostname);
62*6777b538SAndroid Build Coastguard Worker   CHECK(dns_name.has_value());
63*6777b538SAndroid Build Coastguard Worker   DnsQuery query(/*id=*/0x14, dns_name.value(), type);
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   // Build response to simulate the barebones validation DnsResponse applies to
66*6777b538SAndroid Build Coastguard Worker   // responses received from the network.
67*6777b538SAndroid Build Coastguard Worker   auto buffer = base::MakeRefCounted<IOBufferWithSize>(
68*6777b538SAndroid Build Coastguard Worker       sizeof(kMalformedResponseHeader) + query.question().size());
69*6777b538SAndroid Build Coastguard Worker   memcpy(buffer->data(), kMalformedResponseHeader,
70*6777b538SAndroid Build Coastguard Worker          sizeof(kMalformedResponseHeader));
71*6777b538SAndroid Build Coastguard Worker   memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
72*6777b538SAndroid Build Coastguard Worker          query.question().data(), query.question().size());
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   DnsResponse response(buffer, buffer->size());
75*6777b538SAndroid Build Coastguard Worker   CHECK(response.InitParseWithoutQuery(buffer->size()));
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   return response;
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker class MockAddressSorter : public AddressSorter {
81*6777b538SAndroid Build Coastguard Worker  public:
82*6777b538SAndroid Build Coastguard Worker   ~MockAddressSorter() override = default;
Sort(const std::vector<IPEndPoint> & endpoints,CallbackType callback) const83*6777b538SAndroid Build Coastguard Worker   void Sort(const std::vector<IPEndPoint>& endpoints,
84*6777b538SAndroid Build Coastguard Worker             CallbackType callback) const override {
85*6777b538SAndroid Build Coastguard Worker     // Do nothing.
86*6777b538SAndroid Build Coastguard Worker     std::move(callback).Run(true, endpoints);
87*6777b538SAndroid Build Coastguard Worker   }
88*6777b538SAndroid Build Coastguard Worker };
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker }  // namespace
91*6777b538SAndroid Build Coastguard Worker 
CreateValidDnsConfig()92*6777b538SAndroid Build Coastguard Worker DnsConfig CreateValidDnsConfig() {
93*6777b538SAndroid Build Coastguard Worker   IPAddress dns_ip(192, 168, 1, 0);
94*6777b538SAndroid Build Coastguard Worker   DnsConfig config;
95*6777b538SAndroid Build Coastguard Worker   config.nameservers.emplace_back(dns_ip, dns_protocol::kDefaultPort);
96*6777b538SAndroid Build Coastguard Worker   config.doh_config =
97*6777b538SAndroid Build Coastguard Worker       *DnsOverHttpsConfig::FromString("https://dns.example.com/");
98*6777b538SAndroid Build Coastguard Worker   config.secure_dns_mode = SecureDnsMode::kOff;
99*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(config.IsValid());
100*6777b538SAndroid Build Coastguard Worker   return config;
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsRecord(std::string name,uint16_t type,std::string rdata,base::TimeDelta ttl)103*6777b538SAndroid Build Coastguard Worker DnsResourceRecord BuildTestDnsRecord(std::string name,
104*6777b538SAndroid Build Coastguard Worker                                      uint16_t type,
105*6777b538SAndroid Build Coastguard Worker                                      std::string rdata,
106*6777b538SAndroid Build Coastguard Worker                                      base::TimeDelta ttl) {
107*6777b538SAndroid Build Coastguard Worker   DCHECK(!name.empty());
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   DnsResourceRecord record;
110*6777b538SAndroid Build Coastguard Worker   record.name = std::move(name);
111*6777b538SAndroid Build Coastguard Worker   record.type = type;
112*6777b538SAndroid Build Coastguard Worker   record.klass = dns_protocol::kClassIN;
113*6777b538SAndroid Build Coastguard Worker   record.ttl = ttl.InSeconds();
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker   if (!rdata.empty())
116*6777b538SAndroid Build Coastguard Worker     record.SetOwnedRdata(std::move(rdata));
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   return record;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
BuildTestCnameRecord(std::string name,std::string_view canonical_name,base::TimeDelta ttl)121*6777b538SAndroid Build Coastguard Worker DnsResourceRecord BuildTestCnameRecord(std::string name,
122*6777b538SAndroid Build Coastguard Worker                                        std::string_view canonical_name,
123*6777b538SAndroid Build Coastguard Worker                                        base::TimeDelta ttl) {
124*6777b538SAndroid Build Coastguard Worker   DCHECK(!name.empty());
125*6777b538SAndroid Build Coastguard Worker   DCHECK(!canonical_name.empty());
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<uint8_t>> rdata =
128*6777b538SAndroid Build Coastguard Worker       dns_names_util::DottedNameToNetwork(canonical_name);
129*6777b538SAndroid Build Coastguard Worker   CHECK(rdata.has_value());
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsRecord(
132*6777b538SAndroid Build Coastguard Worker       std::move(name), dns_protocol::kTypeCNAME,
133*6777b538SAndroid Build Coastguard Worker       std::string(reinterpret_cast<char*>(rdata.value().data()),
134*6777b538SAndroid Build Coastguard Worker                   rdata.value().size()),
135*6777b538SAndroid Build Coastguard Worker       ttl);
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker 
BuildTestAddressRecord(std::string name,const IPAddress & ip,base::TimeDelta ttl)138*6777b538SAndroid Build Coastguard Worker DnsResourceRecord BuildTestAddressRecord(std::string name,
139*6777b538SAndroid Build Coastguard Worker                                          const IPAddress& ip,
140*6777b538SAndroid Build Coastguard Worker                                          base::TimeDelta ttl) {
141*6777b538SAndroid Build Coastguard Worker   DCHECK(!name.empty());
142*6777b538SAndroid Build Coastguard Worker   DCHECK(ip.IsValid());
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsRecord(
145*6777b538SAndroid Build Coastguard Worker       std::move(name),
146*6777b538SAndroid Build Coastguard Worker       ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
147*6777b538SAndroid Build Coastguard Worker       net::IPAddressToPackedString(ip), ttl);
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker 
BuildTestTextRecord(std::string name,std::vector<std::string> text_strings,base::TimeDelta ttl)150*6777b538SAndroid Build Coastguard Worker DnsResourceRecord BuildTestTextRecord(std::string name,
151*6777b538SAndroid Build Coastguard Worker                                       std::vector<std::string> text_strings,
152*6777b538SAndroid Build Coastguard Worker                                       base::TimeDelta ttl) {
153*6777b538SAndroid Build Coastguard Worker   DCHECK(!text_strings.empty());
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   std::string rdata;
156*6777b538SAndroid Build Coastguard Worker   for (const std::string& text_string : text_strings) {
157*6777b538SAndroid Build Coastguard Worker     DCHECK(!text_string.empty());
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker     rdata += base::checked_cast<unsigned char>(text_string.size());
160*6777b538SAndroid Build Coastguard Worker     rdata += text_string;
161*6777b538SAndroid Build Coastguard Worker   }
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
164*6777b538SAndroid Build Coastguard Worker                             std::move(rdata), ttl);
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker 
BuildTestHttpsAliasRecord(std::string name,std::string_view alias_name,base::TimeDelta ttl)167*6777b538SAndroid Build Coastguard Worker DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
168*6777b538SAndroid Build Coastguard Worker                                             std::string_view alias_name,
169*6777b538SAndroid Build Coastguard Worker                                             base::TimeDelta ttl) {
170*6777b538SAndroid Build Coastguard Worker   DCHECK(!name.empty());
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker   std::string rdata("\000\000", 2);
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<uint8_t>> alias_domain =
175*6777b538SAndroid Build Coastguard Worker       dns_names_util::DottedNameToNetwork(alias_name);
176*6777b538SAndroid Build Coastguard Worker   CHECK(alias_domain.has_value());
177*6777b538SAndroid Build Coastguard Worker   rdata.append(reinterpret_cast<char*>(alias_domain.value().data()),
178*6777b538SAndroid Build Coastguard Worker                alias_domain.value().size());
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
181*6777b538SAndroid Build Coastguard Worker                             std::move(rdata), ttl);
182*6777b538SAndroid Build Coastguard Worker }
183*6777b538SAndroid Build Coastguard Worker 
BuildTestHttpsServiceAlpnParam(const std::vector<std::string> & alpns)184*6777b538SAndroid Build Coastguard Worker std::pair<uint16_t, std::string> BuildTestHttpsServiceAlpnParam(
185*6777b538SAndroid Build Coastguard Worker     const std::vector<std::string>& alpns) {
186*6777b538SAndroid Build Coastguard Worker   std::string param_value;
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   for (const std::string& alpn : alpns) {
189*6777b538SAndroid Build Coastguard Worker     CHECK(!alpn.empty());
190*6777b538SAndroid Build Coastguard Worker     param_value.append(
191*6777b538SAndroid Build Coastguard Worker         1, static_cast<char>(base::checked_cast<uint8_t>(alpn.size())));
192*6777b538SAndroid Build Coastguard Worker     param_value.append(alpn);
193*6777b538SAndroid Build Coastguard Worker   }
194*6777b538SAndroid Build Coastguard Worker 
195*6777b538SAndroid Build Coastguard Worker   return std::pair(dns_protocol::kHttpsServiceParamKeyAlpn,
196*6777b538SAndroid Build Coastguard Worker                    std::move(param_value));
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker 
BuildTestHttpsServiceEchConfigParam(base::span<const uint8_t> ech_config_list)199*6777b538SAndroid Build Coastguard Worker std::pair<uint16_t, std::string> BuildTestHttpsServiceEchConfigParam(
200*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> ech_config_list) {
201*6777b538SAndroid Build Coastguard Worker   return std::pair(
202*6777b538SAndroid Build Coastguard Worker       dns_protocol::kHttpsServiceParamKeyEchConfig,
203*6777b538SAndroid Build Coastguard Worker       std::string(reinterpret_cast<const char*>(ech_config_list.data()),
204*6777b538SAndroid Build Coastguard Worker                   ech_config_list.size()));
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
BuildTestHttpsServiceMandatoryParam(std::vector<uint16_t> param_key_list)207*6777b538SAndroid Build Coastguard Worker std::pair<uint16_t, std::string> BuildTestHttpsServiceMandatoryParam(
208*6777b538SAndroid Build Coastguard Worker     std::vector<uint16_t> param_key_list) {
209*6777b538SAndroid Build Coastguard Worker   base::ranges::sort(param_key_list);
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker   std::string value;
212*6777b538SAndroid Build Coastguard Worker   for (uint16_t param_key : param_key_list) {
213*6777b538SAndroid Build Coastguard Worker     std::array<uint8_t, 2> num_buffer = base::U16ToBigEndian(param_key);
214*6777b538SAndroid Build Coastguard Worker     value.append(num_buffer.begin(), num_buffer.end());
215*6777b538SAndroid Build Coastguard Worker   }
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker   return std::pair(dns_protocol::kHttpsServiceParamKeyMandatory,
218*6777b538SAndroid Build Coastguard Worker                    std::move(value));
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker 
BuildTestHttpsServicePortParam(uint16_t port)221*6777b538SAndroid Build Coastguard Worker std::pair<uint16_t, std::string> BuildTestHttpsServicePortParam(uint16_t port) {
222*6777b538SAndroid Build Coastguard Worker   std::array<uint8_t, 2> buffer = base::U16ToBigEndian(port);
223*6777b538SAndroid Build Coastguard Worker   return std::pair(dns_protocol::kHttpsServiceParamKeyPort,
224*6777b538SAndroid Build Coastguard Worker                    std::string(buffer.begin(), buffer.end()));
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker 
BuildTestHttpsServiceRecord(std::string name,uint16_t priority,std::string_view service_name,const std::map<uint16_t,std::string> & params,base::TimeDelta ttl)227*6777b538SAndroid Build Coastguard Worker DnsResourceRecord BuildTestHttpsServiceRecord(
228*6777b538SAndroid Build Coastguard Worker     std::string name,
229*6777b538SAndroid Build Coastguard Worker     uint16_t priority,
230*6777b538SAndroid Build Coastguard Worker     std::string_view service_name,
231*6777b538SAndroid Build Coastguard Worker     const std::map<uint16_t, std::string>& params,
232*6777b538SAndroid Build Coastguard Worker     base::TimeDelta ttl) {
233*6777b538SAndroid Build Coastguard Worker   DCHECK(!name.empty());
234*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(priority, 0);
235*6777b538SAndroid Build Coastguard Worker 
236*6777b538SAndroid Build Coastguard Worker   std::string rdata;
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker   {
239*6777b538SAndroid Build Coastguard Worker     std::array<uint8_t, 2> buf = base::U16ToBigEndian(priority);
240*6777b538SAndroid Build Coastguard Worker     rdata.append(buf.begin(), buf.end());
241*6777b538SAndroid Build Coastguard Worker   }
242*6777b538SAndroid Build Coastguard Worker 
243*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<uint8_t>> service_domain;
244*6777b538SAndroid Build Coastguard Worker   if (service_name == ".") {
245*6777b538SAndroid Build Coastguard Worker     // HTTPS records have special behavior for `service_name == "."` (that it
246*6777b538SAndroid Build Coastguard Worker     // will be treated as if the service name is the same as the record owner
247*6777b538SAndroid Build Coastguard Worker     // name), so allow such inputs despite normally being disallowed for
248*6777b538SAndroid Build Coastguard Worker     // Chrome-encoded DNS names.
249*6777b538SAndroid Build Coastguard Worker     service_domain = std::vector<uint8_t>{0};
250*6777b538SAndroid Build Coastguard Worker   } else {
251*6777b538SAndroid Build Coastguard Worker     service_domain = dns_names_util::DottedNameToNetwork(service_name);
252*6777b538SAndroid Build Coastguard Worker   }
253*6777b538SAndroid Build Coastguard Worker   CHECK(service_domain.has_value());
254*6777b538SAndroid Build Coastguard Worker   rdata.append(reinterpret_cast<char*>(service_domain.value().data()),
255*6777b538SAndroid Build Coastguard Worker                service_domain.value().size());
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker   for (auto& param : params) {
258*6777b538SAndroid Build Coastguard Worker     {
259*6777b538SAndroid Build Coastguard Worker       std::array<uint8_t, 2> buf = base::U16ToBigEndian(param.first);
260*6777b538SAndroid Build Coastguard Worker       rdata.append(buf.begin(), buf.end());
261*6777b538SAndroid Build Coastguard Worker     }
262*6777b538SAndroid Build Coastguard Worker     {
263*6777b538SAndroid Build Coastguard Worker       std::array<uint8_t, 2> buf = base::U16ToBigEndian(
264*6777b538SAndroid Build Coastguard Worker           base::checked_cast<uint16_t>(param.second.size()));
265*6777b538SAndroid Build Coastguard Worker       rdata.append(buf.begin(), buf.end());
266*6777b538SAndroid Build Coastguard Worker     }
267*6777b538SAndroid Build Coastguard Worker     rdata.append(param.second);
268*6777b538SAndroid Build Coastguard Worker   }
269*6777b538SAndroid Build Coastguard Worker 
270*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
271*6777b538SAndroid Build Coastguard Worker                             std::move(rdata), ttl);
272*6777b538SAndroid Build Coastguard Worker }
273*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsResponse(std::string name,uint16_t type,const std::vector<DnsResourceRecord> & answers,const std::vector<DnsResourceRecord> & authority,const std::vector<DnsResourceRecord> & additional,uint8_t rcode)274*6777b538SAndroid Build Coastguard Worker DnsResponse BuildTestDnsResponse(
275*6777b538SAndroid Build Coastguard Worker     std::string name,
276*6777b538SAndroid Build Coastguard Worker     uint16_t type,
277*6777b538SAndroid Build Coastguard Worker     const std::vector<DnsResourceRecord>& answers,
278*6777b538SAndroid Build Coastguard Worker     const std::vector<DnsResourceRecord>& authority,
279*6777b538SAndroid Build Coastguard Worker     const std::vector<DnsResourceRecord>& additional,
280*6777b538SAndroid Build Coastguard Worker     uint8_t rcode) {
281*6777b538SAndroid Build Coastguard Worker   DCHECK(!name.empty());
282*6777b538SAndroid Build Coastguard Worker 
283*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<uint8_t>> dns_name =
284*6777b538SAndroid Build Coastguard Worker       dns_names_util::DottedNameToNetwork(name);
285*6777b538SAndroid Build Coastguard Worker   CHECK(dns_name.has_value());
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   std::optional<DnsQuery> query(std::in_place, 0, dns_name.value(), type);
288*6777b538SAndroid Build Coastguard Worker   return DnsResponse(0, true /* is_authoritative */, answers,
289*6777b538SAndroid Build Coastguard Worker                      authority /* authority_records */,
290*6777b538SAndroid Build Coastguard Worker                      additional /* additional_records */, query, rcode,
291*6777b538SAndroid Build Coastguard Worker                      false /* validate_records */);
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsAddressResponse(std::string name,const IPAddress & ip,std::string answer_name)294*6777b538SAndroid Build Coastguard Worker DnsResponse BuildTestDnsAddressResponse(std::string name,
295*6777b538SAndroid Build Coastguard Worker                                         const IPAddress& ip,
296*6777b538SAndroid Build Coastguard Worker                                         std::string answer_name) {
297*6777b538SAndroid Build Coastguard Worker   DCHECK(ip.IsValid());
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker   if (answer_name.empty())
300*6777b538SAndroid Build Coastguard Worker     answer_name = name;
301*6777b538SAndroid Build Coastguard Worker 
302*6777b538SAndroid Build Coastguard Worker   std::vector<DnsResourceRecord> answers = {
303*6777b538SAndroid Build Coastguard Worker       BuildTestAddressRecord(std::move(answer_name), ip)};
304*6777b538SAndroid Build Coastguard Worker 
305*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsResponse(
306*6777b538SAndroid Build Coastguard Worker       std::move(name),
307*6777b538SAndroid Build Coastguard Worker       ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsAddressResponseWithCname(std::string name,const IPAddress & ip,std::string cannonname,std::string answer_name)310*6777b538SAndroid Build Coastguard Worker DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
311*6777b538SAndroid Build Coastguard Worker                                                  const IPAddress& ip,
312*6777b538SAndroid Build Coastguard Worker                                                  std::string cannonname,
313*6777b538SAndroid Build Coastguard Worker                                                  std::string answer_name) {
314*6777b538SAndroid Build Coastguard Worker   DCHECK(ip.IsValid());
315*6777b538SAndroid Build Coastguard Worker   DCHECK(!cannonname.empty());
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker   if (answer_name.empty())
318*6777b538SAndroid Build Coastguard Worker     answer_name = name;
319*6777b538SAndroid Build Coastguard Worker 
320*6777b538SAndroid Build Coastguard Worker   std::optional<std::vector<uint8_t>> cname_rdata =
321*6777b538SAndroid Build Coastguard Worker       dns_names_util::DottedNameToNetwork(cannonname);
322*6777b538SAndroid Build Coastguard Worker   CHECK(cname_rdata.has_value());
323*6777b538SAndroid Build Coastguard Worker 
324*6777b538SAndroid Build Coastguard Worker   std::vector<DnsResourceRecord> answers = {
325*6777b538SAndroid Build Coastguard Worker       BuildTestDnsRecord(
326*6777b538SAndroid Build Coastguard Worker           std::move(answer_name), dns_protocol::kTypeCNAME,
327*6777b538SAndroid Build Coastguard Worker           std::string(reinterpret_cast<char*>(cname_rdata.value().data()),
328*6777b538SAndroid Build Coastguard Worker                       cname_rdata.value().size())),
329*6777b538SAndroid Build Coastguard Worker       BuildTestAddressRecord(std::move(cannonname), ip)};
330*6777b538SAndroid Build Coastguard Worker 
331*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsResponse(
332*6777b538SAndroid Build Coastguard Worker       std::move(name),
333*6777b538SAndroid Build Coastguard Worker       ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
334*6777b538SAndroid Build Coastguard Worker }
335*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsTextResponse(std::string name,std::vector<std::vector<std::string>> text_records,std::string answer_name)336*6777b538SAndroid Build Coastguard Worker DnsResponse BuildTestDnsTextResponse(
337*6777b538SAndroid Build Coastguard Worker     std::string name,
338*6777b538SAndroid Build Coastguard Worker     std::vector<std::vector<std::string>> text_records,
339*6777b538SAndroid Build Coastguard Worker     std::string answer_name) {
340*6777b538SAndroid Build Coastguard Worker   if (answer_name.empty())
341*6777b538SAndroid Build Coastguard Worker     answer_name = name;
342*6777b538SAndroid Build Coastguard Worker 
343*6777b538SAndroid Build Coastguard Worker   std::vector<DnsResourceRecord> answers;
344*6777b538SAndroid Build Coastguard Worker   for (std::vector<std::string>& text_record : text_records) {
345*6777b538SAndroid Build Coastguard Worker     answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
346*6777b538SAndroid Build Coastguard Worker   }
347*6777b538SAndroid Build Coastguard Worker 
348*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
349*6777b538SAndroid Build Coastguard Worker }
350*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsPointerResponse(std::string name,std::vector<std::string> pointer_names,std::string answer_name)351*6777b538SAndroid Build Coastguard Worker DnsResponse BuildTestDnsPointerResponse(std::string name,
352*6777b538SAndroid Build Coastguard Worker                                         std::vector<std::string> pointer_names,
353*6777b538SAndroid Build Coastguard Worker                                         std::string answer_name) {
354*6777b538SAndroid Build Coastguard Worker   if (answer_name.empty())
355*6777b538SAndroid Build Coastguard Worker     answer_name = name;
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker   std::vector<DnsResourceRecord> answers;
358*6777b538SAndroid Build Coastguard Worker   for (std::string& pointer_name : pointer_names) {
359*6777b538SAndroid Build Coastguard Worker     std::optional<std::vector<uint8_t>> rdata =
360*6777b538SAndroid Build Coastguard Worker         dns_names_util::DottedNameToNetwork(pointer_name);
361*6777b538SAndroid Build Coastguard Worker     CHECK(rdata.has_value());
362*6777b538SAndroid Build Coastguard Worker 
363*6777b538SAndroid Build Coastguard Worker     answers.push_back(BuildTestDnsRecord(
364*6777b538SAndroid Build Coastguard Worker         answer_name, dns_protocol::kTypePTR,
365*6777b538SAndroid Build Coastguard Worker         std::string(reinterpret_cast<char*>(rdata.value().data()),
366*6777b538SAndroid Build Coastguard Worker                     rdata.value().size())));
367*6777b538SAndroid Build Coastguard Worker   }
368*6777b538SAndroid Build Coastguard Worker 
369*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker 
BuildTestDnsServiceResponse(std::string name,std::vector<TestServiceRecord> service_records,std::string answer_name)372*6777b538SAndroid Build Coastguard Worker DnsResponse BuildTestDnsServiceResponse(
373*6777b538SAndroid Build Coastguard Worker     std::string name,
374*6777b538SAndroid Build Coastguard Worker     std::vector<TestServiceRecord> service_records,
375*6777b538SAndroid Build Coastguard Worker     std::string answer_name) {
376*6777b538SAndroid Build Coastguard Worker   if (answer_name.empty())
377*6777b538SAndroid Build Coastguard Worker     answer_name = name;
378*6777b538SAndroid Build Coastguard Worker 
379*6777b538SAndroid Build Coastguard Worker   std::vector<DnsResourceRecord> answers;
380*6777b538SAndroid Build Coastguard Worker   for (TestServiceRecord& service_record : service_records) {
381*6777b538SAndroid Build Coastguard Worker     std::string rdata;
382*6777b538SAndroid Build Coastguard Worker     {
383*6777b538SAndroid Build Coastguard Worker       std::array<uint8_t, 2> buf =
384*6777b538SAndroid Build Coastguard Worker           base::U16ToBigEndian(service_record.priority);
385*6777b538SAndroid Build Coastguard Worker       rdata.append(buf.begin(), buf.end());
386*6777b538SAndroid Build Coastguard Worker     }
387*6777b538SAndroid Build Coastguard Worker     {
388*6777b538SAndroid Build Coastguard Worker       std::array<uint8_t, 2> buf = base::U16ToBigEndian(service_record.weight);
389*6777b538SAndroid Build Coastguard Worker       rdata.append(buf.begin(), buf.end());
390*6777b538SAndroid Build Coastguard Worker     }
391*6777b538SAndroid Build Coastguard Worker     {
392*6777b538SAndroid Build Coastguard Worker       std::array<uint8_t, 2> buf = base::U16ToBigEndian(service_record.port);
393*6777b538SAndroid Build Coastguard Worker       rdata.append(buf.begin(), buf.end());
394*6777b538SAndroid Build Coastguard Worker     }
395*6777b538SAndroid Build Coastguard Worker 
396*6777b538SAndroid Build Coastguard Worker     std::optional<std::vector<uint8_t>> dns_name =
397*6777b538SAndroid Build Coastguard Worker         dns_names_util::DottedNameToNetwork(service_record.target);
398*6777b538SAndroid Build Coastguard Worker     CHECK(dns_name.has_value());
399*6777b538SAndroid Build Coastguard Worker     rdata.append(reinterpret_cast<char*>(dns_name.value().data()),
400*6777b538SAndroid Build Coastguard Worker                  dns_name.value().size());
401*6777b538SAndroid Build Coastguard Worker 
402*6777b538SAndroid Build Coastguard Worker     answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
403*6777b538SAndroid Build Coastguard Worker                                          std::move(rdata), base::Hours(5)));
404*6777b538SAndroid Build Coastguard Worker   }
405*6777b538SAndroid Build Coastguard Worker 
406*6777b538SAndroid Build Coastguard Worker   return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
407*6777b538SAndroid Build Coastguard Worker }
408*6777b538SAndroid Build Coastguard Worker 
Result(ResultType type,std::optional<DnsResponse> response,std::optional<int> net_error)409*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::Result::Result(ResultType type,
410*6777b538SAndroid Build Coastguard Worker                                   std::optional<DnsResponse> response,
411*6777b538SAndroid Build Coastguard Worker                                   std::optional<int> net_error)
412*6777b538SAndroid Build Coastguard Worker     : type(type), response(std::move(response)), net_error(net_error) {}
413*6777b538SAndroid Build Coastguard Worker 
Result(DnsResponse response)414*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::Result::Result(DnsResponse response)
415*6777b538SAndroid Build Coastguard Worker     : type(ResultType::kOk),
416*6777b538SAndroid Build Coastguard Worker       response(std::move(response)),
417*6777b538SAndroid Build Coastguard Worker       net_error(std::nullopt) {}
418*6777b538SAndroid Build Coastguard Worker 
419*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::Result::Result(Result&&) = default;
420*6777b538SAndroid Build Coastguard Worker 
421*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
422*6777b538SAndroid Build Coastguard Worker     default;
423*6777b538SAndroid Build Coastguard Worker 
424*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::Result::~Result() = default;
425*6777b538SAndroid Build Coastguard Worker 
MockDnsClientRule(const std::string & prefix,uint16_t qtype,bool secure,Result result,bool delay,URLRequestContext * context)426*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
427*6777b538SAndroid Build Coastguard Worker                                      uint16_t qtype,
428*6777b538SAndroid Build Coastguard Worker                                      bool secure,
429*6777b538SAndroid Build Coastguard Worker                                      Result result,
430*6777b538SAndroid Build Coastguard Worker                                      bool delay,
431*6777b538SAndroid Build Coastguard Worker                                      URLRequestContext* context)
432*6777b538SAndroid Build Coastguard Worker     : result(std::move(result)),
433*6777b538SAndroid Build Coastguard Worker       prefix(prefix),
434*6777b538SAndroid Build Coastguard Worker       qtype(qtype),
435*6777b538SAndroid Build Coastguard Worker       secure(secure),
436*6777b538SAndroid Build Coastguard Worker       delay(delay),
437*6777b538SAndroid Build Coastguard Worker       context(context) {}
438*6777b538SAndroid Build Coastguard Worker 
439*6777b538SAndroid Build Coastguard Worker MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
440*6777b538SAndroid Build Coastguard Worker 
441*6777b538SAndroid Build Coastguard Worker // A DnsTransaction which uses MockDnsClientRuleList to determine the response.
442*6777b538SAndroid Build Coastguard Worker class MockDnsTransactionFactory::MockTransaction
443*6777b538SAndroid Build Coastguard Worker     : public DnsTransaction,
444*6777b538SAndroid Build Coastguard Worker       public base::SupportsWeakPtr<MockTransaction> {
445*6777b538SAndroid Build Coastguard Worker  public:
MockTransaction(const MockDnsClientRuleList & rules,std::string hostname,uint16_t qtype,bool secure,bool force_doh_server_available,SecureDnsMode secure_dns_mode,ResolveContext * resolve_context,bool fast_timeout)446*6777b538SAndroid Build Coastguard Worker   MockTransaction(const MockDnsClientRuleList& rules,
447*6777b538SAndroid Build Coastguard Worker                   std::string hostname,
448*6777b538SAndroid Build Coastguard Worker                   uint16_t qtype,
449*6777b538SAndroid Build Coastguard Worker                   bool secure,
450*6777b538SAndroid Build Coastguard Worker                   bool force_doh_server_available,
451*6777b538SAndroid Build Coastguard Worker                   SecureDnsMode secure_dns_mode,
452*6777b538SAndroid Build Coastguard Worker                   ResolveContext* resolve_context,
453*6777b538SAndroid Build Coastguard Worker                   bool fast_timeout)
454*6777b538SAndroid Build Coastguard Worker       : hostname_(std::move(hostname)), qtype_(qtype) {
455*6777b538SAndroid Build Coastguard Worker     // Do not allow matching any rules if transaction is secure and no DoH
456*6777b538SAndroid Build Coastguard Worker     // servers are available.
457*6777b538SAndroid Build Coastguard Worker     if (!secure || force_doh_server_available ||
458*6777b538SAndroid Build Coastguard Worker         resolve_context->NumAvailableDohServers(
459*6777b538SAndroid Build Coastguard Worker             resolve_context->current_session_for_testing()) > 0) {
460*6777b538SAndroid Build Coastguard Worker       // Find the relevant rule which matches |qtype|, |secure|, prefix of
461*6777b538SAndroid Build Coastguard Worker       // |hostname_|, and |url_request_context| (iff the rule context is not
462*6777b538SAndroid Build Coastguard Worker       // null).
463*6777b538SAndroid Build Coastguard Worker       for (const auto& rule : rules) {
464*6777b538SAndroid Build Coastguard Worker         const std::string& prefix = rule.prefix;
465*6777b538SAndroid Build Coastguard Worker         if ((rule.qtype == qtype) && (rule.secure == secure) &&
466*6777b538SAndroid Build Coastguard Worker             (hostname_.size() >= prefix.size()) &&
467*6777b538SAndroid Build Coastguard Worker             (hostname_.compare(0, prefix.size(), prefix) == 0) &&
468*6777b538SAndroid Build Coastguard Worker             (!rule.context ||
469*6777b538SAndroid Build Coastguard Worker              rule.context == resolve_context->url_request_context())) {
470*6777b538SAndroid Build Coastguard Worker           const MockDnsClientRule::Result* result = &rule.result;
471*6777b538SAndroid Build Coastguard Worker           result_ = MockDnsClientRule::Result(result->type);
472*6777b538SAndroid Build Coastguard Worker           result_.net_error = result->net_error;
473*6777b538SAndroid Build Coastguard Worker           delayed_ = rule.delay;
474*6777b538SAndroid Build Coastguard Worker 
475*6777b538SAndroid Build Coastguard Worker           // Generate a DnsResponse when not provided with the rule.
476*6777b538SAndroid Build Coastguard Worker           std::vector<DnsResourceRecord> authority_records;
477*6777b538SAndroid Build Coastguard Worker           std::optional<std::vector<uint8_t>> dns_name =
478*6777b538SAndroid Build Coastguard Worker               dns_names_util::DottedNameToNetwork(hostname_);
479*6777b538SAndroid Build Coastguard Worker           CHECK(dns_name.has_value());
480*6777b538SAndroid Build Coastguard Worker           std::optional<DnsQuery> query(std::in_place, /*id=*/22,
481*6777b538SAndroid Build Coastguard Worker                                         dns_name.value(), qtype_);
482*6777b538SAndroid Build Coastguard Worker           switch (result->type) {
483*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kNoDomain:
484*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kEmpty:
485*6777b538SAndroid Build Coastguard Worker               DCHECK(!result->response);  // Not expected to be provided.
486*6777b538SAndroid Build Coastguard Worker               authority_records = {BuildTestDnsRecord(
487*6777b538SAndroid Build Coastguard Worker                   hostname_, dns_protocol::kTypeSOA, "fake rdata")};
488*6777b538SAndroid Build Coastguard Worker               result_.response = DnsResponse(
489*6777b538SAndroid Build Coastguard Worker                   22 /* id */, false /* is_authoritative */,
490*6777b538SAndroid Build Coastguard Worker                   std::vector<DnsResourceRecord>() /* answers */,
491*6777b538SAndroid Build Coastguard Worker                   authority_records,
492*6777b538SAndroid Build Coastguard Worker                   std::vector<DnsResourceRecord>() /* additional_records */,
493*6777b538SAndroid Build Coastguard Worker                   query,
494*6777b538SAndroid Build Coastguard Worker                   result->type == MockDnsClientRule::ResultType::kNoDomain
495*6777b538SAndroid Build Coastguard Worker                       ? dns_protocol::kRcodeNXDOMAIN
496*6777b538SAndroid Build Coastguard Worker                       : 0);
497*6777b538SAndroid Build Coastguard Worker               break;
498*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kFail:
499*6777b538SAndroid Build Coastguard Worker               if (result->response)
500*6777b538SAndroid Build Coastguard Worker                 SetResponse(result);
501*6777b538SAndroid Build Coastguard Worker               break;
502*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kTimeout:
503*6777b538SAndroid Build Coastguard Worker               DCHECK(!result->response);  // Not expected to be provided.
504*6777b538SAndroid Build Coastguard Worker               break;
505*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kSlow:
506*6777b538SAndroid Build Coastguard Worker               if (!fast_timeout)
507*6777b538SAndroid Build Coastguard Worker                 SetResponse(result);
508*6777b538SAndroid Build Coastguard Worker               break;
509*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kOk:
510*6777b538SAndroid Build Coastguard Worker               SetResponse(result);
511*6777b538SAndroid Build Coastguard Worker               break;
512*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kMalformed:
513*6777b538SAndroid Build Coastguard Worker               DCHECK(!result->response);  // Not expected to be provided.
514*6777b538SAndroid Build Coastguard Worker               result_.response = CreateMalformedResponse(hostname_, qtype_);
515*6777b538SAndroid Build Coastguard Worker               break;
516*6777b538SAndroid Build Coastguard Worker             case MockDnsClientRule::ResultType::kUnexpected:
517*6777b538SAndroid Build Coastguard Worker               if (!delayed_) {
518*6777b538SAndroid Build Coastguard Worker                 // Assume a delayed kUnexpected transaction is only an issue if
519*6777b538SAndroid Build Coastguard Worker                 // allowed to complete.
520*6777b538SAndroid Build Coastguard Worker                 ADD_FAILURE()
521*6777b538SAndroid Build Coastguard Worker                     << "Unexpected DNS transaction created for hostname "
522*6777b538SAndroid Build Coastguard Worker                     << hostname_;
523*6777b538SAndroid Build Coastguard Worker               }
524*6777b538SAndroid Build Coastguard Worker               break;
525*6777b538SAndroid Build Coastguard Worker           }
526*6777b538SAndroid Build Coastguard Worker 
527*6777b538SAndroid Build Coastguard Worker           break;
528*6777b538SAndroid Build Coastguard Worker         }
529*6777b538SAndroid Build Coastguard Worker       }
530*6777b538SAndroid Build Coastguard Worker     }
531*6777b538SAndroid Build Coastguard Worker   }
532*6777b538SAndroid Build Coastguard Worker 
GetHostname() const533*6777b538SAndroid Build Coastguard Worker   const std::string& GetHostname() const override { return hostname_; }
534*6777b538SAndroid Build Coastguard Worker 
GetType() const535*6777b538SAndroid Build Coastguard Worker   uint16_t GetType() const override { return qtype_; }
536*6777b538SAndroid Build Coastguard Worker 
Start(ResponseCallback callback)537*6777b538SAndroid Build Coastguard Worker   void Start(ResponseCallback callback) override {
538*6777b538SAndroid Build Coastguard Worker     CHECK(!callback.is_null());
539*6777b538SAndroid Build Coastguard Worker     CHECK(callback_.is_null());
540*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(started_);
541*6777b538SAndroid Build Coastguard Worker 
542*6777b538SAndroid Build Coastguard Worker     callback_ = std::move(callback);
543*6777b538SAndroid Build Coastguard Worker     started_ = true;
544*6777b538SAndroid Build Coastguard Worker     if (delayed_)
545*6777b538SAndroid Build Coastguard Worker       return;
546*6777b538SAndroid Build Coastguard Worker     // Using WeakPtr to cleanly cancel when transaction is destroyed.
547*6777b538SAndroid Build Coastguard Worker     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
548*6777b538SAndroid Build Coastguard Worker         FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
549*6777b538SAndroid Build Coastguard Worker   }
550*6777b538SAndroid Build Coastguard Worker 
FinishDelayedTransaction()551*6777b538SAndroid Build Coastguard Worker   void FinishDelayedTransaction() {
552*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(delayed_);
553*6777b538SAndroid Build Coastguard Worker     delayed_ = false;
554*6777b538SAndroid Build Coastguard Worker     Finish();
555*6777b538SAndroid Build Coastguard Worker   }
556*6777b538SAndroid Build Coastguard Worker 
delayed() const557*6777b538SAndroid Build Coastguard Worker   bool delayed() const { return delayed_; }
558*6777b538SAndroid Build Coastguard Worker 
559*6777b538SAndroid Build Coastguard Worker  private:
SetResponse(const MockDnsClientRule::Result * result)560*6777b538SAndroid Build Coastguard Worker   void SetResponse(const MockDnsClientRule::Result* result) {
561*6777b538SAndroid Build Coastguard Worker     if (result->response) {
562*6777b538SAndroid Build Coastguard Worker       // Copy response in case |result| is destroyed before the transaction
563*6777b538SAndroid Build Coastguard Worker       // completes.
564*6777b538SAndroid Build Coastguard Worker       auto buffer_copy = base::MakeRefCounted<IOBufferWithSize>(
565*6777b538SAndroid Build Coastguard Worker           result->response->io_buffer_size());
566*6777b538SAndroid Build Coastguard Worker       memcpy(buffer_copy->data(), result->response->io_buffer()->data(),
567*6777b538SAndroid Build Coastguard Worker              result->response->io_buffer_size());
568*6777b538SAndroid Build Coastguard Worker       result_.response = DnsResponse(std::move(buffer_copy),
569*6777b538SAndroid Build Coastguard Worker                                      result->response->io_buffer_size());
570*6777b538SAndroid Build Coastguard Worker       CHECK(result_.response->InitParseWithoutQuery(
571*6777b538SAndroid Build Coastguard Worker           result->response->io_buffer_size()));
572*6777b538SAndroid Build Coastguard Worker     } else {
573*6777b538SAndroid Build Coastguard Worker       // Generated response only available for address types.
574*6777b538SAndroid Build Coastguard Worker       DCHECK(qtype_ == dns_protocol::kTypeA ||
575*6777b538SAndroid Build Coastguard Worker              qtype_ == dns_protocol::kTypeAAAA);
576*6777b538SAndroid Build Coastguard Worker       result_.response = BuildTestDnsAddressResponse(
577*6777b538SAndroid Build Coastguard Worker           hostname_, qtype_ == dns_protocol::kTypeA
578*6777b538SAndroid Build Coastguard Worker                          ? IPAddress::IPv4Localhost()
579*6777b538SAndroid Build Coastguard Worker                          : IPAddress::IPv6Localhost());
580*6777b538SAndroid Build Coastguard Worker     }
581*6777b538SAndroid Build Coastguard Worker   }
582*6777b538SAndroid Build Coastguard Worker 
Finish()583*6777b538SAndroid Build Coastguard Worker   void Finish() {
584*6777b538SAndroid Build Coastguard Worker     switch (result_.type) {
585*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kNoDomain:
586*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kFail: {
587*6777b538SAndroid Build Coastguard Worker         int error = result_.net_error.value_or(ERR_NAME_NOT_RESOLVED);
588*6777b538SAndroid Build Coastguard Worker         DCHECK_NE(error, OK);
589*6777b538SAndroid Build Coastguard Worker         std::move(callback_).Run(error, base::OptionalToPtr(result_.response));
590*6777b538SAndroid Build Coastguard Worker         break;
591*6777b538SAndroid Build Coastguard Worker       }
592*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kEmpty:
593*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kOk:
594*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kMalformed:
595*6777b538SAndroid Build Coastguard Worker         DCHECK(!result_.net_error.has_value());
596*6777b538SAndroid Build Coastguard Worker         std::move(callback_).Run(OK, base::OptionalToPtr(result_.response));
597*6777b538SAndroid Build Coastguard Worker         break;
598*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kTimeout:
599*6777b538SAndroid Build Coastguard Worker         DCHECK(!result_.net_error.has_value());
600*6777b538SAndroid Build Coastguard Worker         std::move(callback_).Run(ERR_DNS_TIMED_OUT, /*response=*/nullptr);
601*6777b538SAndroid Build Coastguard Worker         break;
602*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kSlow:
603*6777b538SAndroid Build Coastguard Worker         if (result_.response) {
604*6777b538SAndroid Build Coastguard Worker           std::move(callback_).Run(
605*6777b538SAndroid Build Coastguard Worker               result_.net_error.value_or(OK),
606*6777b538SAndroid Build Coastguard Worker               result_.response ? &result_.response.value() : nullptr);
607*6777b538SAndroid Build Coastguard Worker         } else {
608*6777b538SAndroid Build Coastguard Worker           DCHECK(!result_.net_error.has_value());
609*6777b538SAndroid Build Coastguard Worker           std::move(callback_).Run(ERR_DNS_TIMED_OUT, /*response=*/nullptr);
610*6777b538SAndroid Build Coastguard Worker         }
611*6777b538SAndroid Build Coastguard Worker         break;
612*6777b538SAndroid Build Coastguard Worker       case MockDnsClientRule::ResultType::kUnexpected:
613*6777b538SAndroid Build Coastguard Worker         ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
614*6777b538SAndroid Build Coastguard Worker                       << hostname_;
615*6777b538SAndroid Build Coastguard Worker         break;
616*6777b538SAndroid Build Coastguard Worker     }
617*6777b538SAndroid Build Coastguard Worker   }
618*6777b538SAndroid Build Coastguard Worker 
SetRequestPriority(RequestPriority priority)619*6777b538SAndroid Build Coastguard Worker   void SetRequestPriority(RequestPriority priority) override {}
620*6777b538SAndroid Build Coastguard Worker 
621*6777b538SAndroid Build Coastguard Worker   MockDnsClientRule::Result result_{MockDnsClientRule::ResultType::kFail};
622*6777b538SAndroid Build Coastguard Worker   const std::string hostname_;
623*6777b538SAndroid Build Coastguard Worker   const uint16_t qtype_;
624*6777b538SAndroid Build Coastguard Worker   ResponseCallback callback_;
625*6777b538SAndroid Build Coastguard Worker   bool started_ = false;
626*6777b538SAndroid Build Coastguard Worker   bool delayed_ = false;
627*6777b538SAndroid Build Coastguard Worker };
628*6777b538SAndroid Build Coastguard Worker 
629*6777b538SAndroid Build Coastguard Worker class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
630*6777b538SAndroid Build Coastguard Worker  public:
MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)631*6777b538SAndroid Build Coastguard Worker   explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
632*6777b538SAndroid Build Coastguard Worker       : factory_(std::move(factory)) {}
633*6777b538SAndroid Build Coastguard Worker 
~MockDohProbeRunner()634*6777b538SAndroid Build Coastguard Worker   ~MockDohProbeRunner() override {
635*6777b538SAndroid Build Coastguard Worker     if (factory_)
636*6777b538SAndroid Build Coastguard Worker       factory_->running_doh_probe_runners_.erase(this);
637*6777b538SAndroid Build Coastguard Worker   }
638*6777b538SAndroid Build Coastguard Worker 
Start(bool network_change)639*6777b538SAndroid Build Coastguard Worker   void Start(bool network_change) override {
640*6777b538SAndroid Build Coastguard Worker     DCHECK(factory_);
641*6777b538SAndroid Build Coastguard Worker     factory_->running_doh_probe_runners_.insert(this);
642*6777b538SAndroid Build Coastguard Worker   }
643*6777b538SAndroid Build Coastguard Worker 
GetDelayUntilNextProbeForTest(size_t doh_server_index) const644*6777b538SAndroid Build Coastguard Worker   base::TimeDelta GetDelayUntilNextProbeForTest(
645*6777b538SAndroid Build Coastguard Worker       size_t doh_server_index) const override {
646*6777b538SAndroid Build Coastguard Worker     NOTREACHED();
647*6777b538SAndroid Build Coastguard Worker     return base::TimeDelta();
648*6777b538SAndroid Build Coastguard Worker   }
649*6777b538SAndroid Build Coastguard Worker 
650*6777b538SAndroid Build Coastguard Worker  private:
651*6777b538SAndroid Build Coastguard Worker   base::WeakPtr<MockDnsTransactionFactory> factory_;
652*6777b538SAndroid Build Coastguard Worker };
653*6777b538SAndroid Build Coastguard Worker 
MockDnsTransactionFactory(MockDnsClientRuleList rules)654*6777b538SAndroid Build Coastguard Worker MockDnsTransactionFactory::MockDnsTransactionFactory(
655*6777b538SAndroid Build Coastguard Worker     MockDnsClientRuleList rules)
656*6777b538SAndroid Build Coastguard Worker     : rules_(std::move(rules)) {}
657*6777b538SAndroid Build Coastguard Worker 
658*6777b538SAndroid Build Coastguard Worker MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
659*6777b538SAndroid Build Coastguard Worker 
CreateTransaction(std::string hostname,uint16_t qtype,const NetLogWithSource &,bool secure,SecureDnsMode secure_dns_mode,ResolveContext * resolve_context,bool fast_timeout)660*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
661*6777b538SAndroid Build Coastguard Worker     std::string hostname,
662*6777b538SAndroid Build Coastguard Worker     uint16_t qtype,
663*6777b538SAndroid Build Coastguard Worker     const NetLogWithSource&,
664*6777b538SAndroid Build Coastguard Worker     bool secure,
665*6777b538SAndroid Build Coastguard Worker     SecureDnsMode secure_dns_mode,
666*6777b538SAndroid Build Coastguard Worker     ResolveContext* resolve_context,
667*6777b538SAndroid Build Coastguard Worker     bool fast_timeout) {
668*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<MockTransaction> transaction =
669*6777b538SAndroid Build Coastguard Worker       std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
670*6777b538SAndroid Build Coastguard Worker                                         secure, force_doh_server_available_,
671*6777b538SAndroid Build Coastguard Worker                                         secure_dns_mode, resolve_context,
672*6777b538SAndroid Build Coastguard Worker                                         fast_timeout);
673*6777b538SAndroid Build Coastguard Worker   if (transaction->delayed())
674*6777b538SAndroid Build Coastguard Worker     delayed_transactions_.push_back(transaction->AsWeakPtr());
675*6777b538SAndroid Build Coastguard Worker   return transaction;
676*6777b538SAndroid Build Coastguard Worker }
677*6777b538SAndroid Build Coastguard Worker 
CreateDohProbeRunner(ResolveContext * resolve_context)678*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
679*6777b538SAndroid Build Coastguard Worker     ResolveContext* resolve_context) {
680*6777b538SAndroid Build Coastguard Worker   return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
681*6777b538SAndroid Build Coastguard Worker }
682*6777b538SAndroid Build Coastguard Worker 
AddEDNSOption(std::unique_ptr<OptRecordRdata::Opt> opt)683*6777b538SAndroid Build Coastguard Worker void MockDnsTransactionFactory::AddEDNSOption(
684*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<OptRecordRdata::Opt> opt) {}
685*6777b538SAndroid Build Coastguard Worker 
GetSecureDnsModeForTest()686*6777b538SAndroid Build Coastguard Worker SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
687*6777b538SAndroid Build Coastguard Worker   return SecureDnsMode::kAutomatic;
688*6777b538SAndroid Build Coastguard Worker }
689*6777b538SAndroid Build Coastguard Worker 
CompleteDelayedTransactions()690*6777b538SAndroid Build Coastguard Worker void MockDnsTransactionFactory::CompleteDelayedTransactions() {
691*6777b538SAndroid Build Coastguard Worker   DelayedTransactionList old_delayed_transactions;
692*6777b538SAndroid Build Coastguard Worker   old_delayed_transactions.swap(delayed_transactions_);
693*6777b538SAndroid Build Coastguard Worker   for (auto& old_delayed_transaction : old_delayed_transactions) {
694*6777b538SAndroid Build Coastguard Worker     if (old_delayed_transaction.get())
695*6777b538SAndroid Build Coastguard Worker       old_delayed_transaction->FinishDelayedTransaction();
696*6777b538SAndroid Build Coastguard Worker   }
697*6777b538SAndroid Build Coastguard Worker }
698*6777b538SAndroid Build Coastguard Worker 
CompleteOneDelayedTransactionOfType(DnsQueryType type)699*6777b538SAndroid Build Coastguard Worker bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
700*6777b538SAndroid Build Coastguard Worker     DnsQueryType type) {
701*6777b538SAndroid Build Coastguard Worker   for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
702*6777b538SAndroid Build Coastguard Worker     if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
703*6777b538SAndroid Build Coastguard Worker       t->FinishDelayedTransaction();
704*6777b538SAndroid Build Coastguard Worker       t.reset();
705*6777b538SAndroid Build Coastguard Worker       return true;
706*6777b538SAndroid Build Coastguard Worker     }
707*6777b538SAndroid Build Coastguard Worker   }
708*6777b538SAndroid Build Coastguard Worker   return false;
709*6777b538SAndroid Build Coastguard Worker }
710*6777b538SAndroid Build Coastguard Worker 
MockDnsClient(DnsConfig config,MockDnsClientRuleList rules)711*6777b538SAndroid Build Coastguard Worker MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
712*6777b538SAndroid Build Coastguard Worker     : config_(std::move(config)),
713*6777b538SAndroid Build Coastguard Worker       factory_(std::make_unique<MockDnsTransactionFactory>(std::move(rules))),
714*6777b538SAndroid Build Coastguard Worker       address_sorter_(std::make_unique<MockAddressSorter>()) {
715*6777b538SAndroid Build Coastguard Worker   effective_config_ = BuildEffectiveConfig();
716*6777b538SAndroid Build Coastguard Worker   session_ = BuildSession();
717*6777b538SAndroid Build Coastguard Worker }
718*6777b538SAndroid Build Coastguard Worker 
719*6777b538SAndroid Build Coastguard Worker MockDnsClient::~MockDnsClient() = default;
720*6777b538SAndroid Build Coastguard Worker 
CanUseSecureDnsTransactions() const721*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::CanUseSecureDnsTransactions() const {
722*6777b538SAndroid Build Coastguard Worker   const DnsConfig* config = GetEffectiveConfig();
723*6777b538SAndroid Build Coastguard Worker   return config && config->IsValid() && !config->doh_config.servers().empty();
724*6777b538SAndroid Build Coastguard Worker }
725*6777b538SAndroid Build Coastguard Worker 
CanUseInsecureDnsTransactions() const726*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::CanUseInsecureDnsTransactions() const {
727*6777b538SAndroid Build Coastguard Worker   const DnsConfig* config = GetEffectiveConfig();
728*6777b538SAndroid Build Coastguard Worker   return config && config->IsValid() && insecure_enabled_ &&
729*6777b538SAndroid Build Coastguard Worker          !config->dns_over_tls_active;
730*6777b538SAndroid Build Coastguard Worker }
731*6777b538SAndroid Build Coastguard Worker 
CanQueryAdditionalTypesViaInsecureDns() const732*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
733*6777b538SAndroid Build Coastguard Worker   DCHECK(CanUseInsecureDnsTransactions());
734*6777b538SAndroid Build Coastguard Worker   return additional_types_enabled_;
735*6777b538SAndroid Build Coastguard Worker }
736*6777b538SAndroid Build Coastguard Worker 
SetInsecureEnabled(bool enabled,bool additional_types_enabled)737*6777b538SAndroid Build Coastguard Worker void MockDnsClient::SetInsecureEnabled(bool enabled,
738*6777b538SAndroid Build Coastguard Worker                                        bool additional_types_enabled) {
739*6777b538SAndroid Build Coastguard Worker   insecure_enabled_ = enabled;
740*6777b538SAndroid Build Coastguard Worker   additional_types_enabled_ = additional_types_enabled;
741*6777b538SAndroid Build Coastguard Worker }
742*6777b538SAndroid Build Coastguard Worker 
FallbackFromSecureTransactionPreferred(ResolveContext * context) const743*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::FallbackFromSecureTransactionPreferred(
744*6777b538SAndroid Build Coastguard Worker     ResolveContext* context) const {
745*6777b538SAndroid Build Coastguard Worker   bool doh_server_available =
746*6777b538SAndroid Build Coastguard Worker       force_doh_server_available_ ||
747*6777b538SAndroid Build Coastguard Worker       context->NumAvailableDohServers(session_.get()) > 0;
748*6777b538SAndroid Build Coastguard Worker   return !CanUseSecureDnsTransactions() || !doh_server_available;
749*6777b538SAndroid Build Coastguard Worker }
750*6777b538SAndroid Build Coastguard Worker 
FallbackFromInsecureTransactionPreferred() const751*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
752*6777b538SAndroid Build Coastguard Worker   return !CanUseInsecureDnsTransactions() ||
753*6777b538SAndroid Build Coastguard Worker          fallback_failures_ >= max_fallback_failures_;
754*6777b538SAndroid Build Coastguard Worker }
755*6777b538SAndroid Build Coastguard Worker 
SetSystemConfig(std::optional<DnsConfig> system_config)756*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::SetSystemConfig(std::optional<DnsConfig> system_config) {
757*6777b538SAndroid Build Coastguard Worker   if (ignore_system_config_changes_)
758*6777b538SAndroid Build Coastguard Worker     return false;
759*6777b538SAndroid Build Coastguard Worker 
760*6777b538SAndroid Build Coastguard Worker   std::optional<DnsConfig> before = effective_config_;
761*6777b538SAndroid Build Coastguard Worker   config_ = std::move(system_config);
762*6777b538SAndroid Build Coastguard Worker   effective_config_ = BuildEffectiveConfig();
763*6777b538SAndroid Build Coastguard Worker   session_ = BuildSession();
764*6777b538SAndroid Build Coastguard Worker   return before != effective_config_;
765*6777b538SAndroid Build Coastguard Worker }
766*6777b538SAndroid Build Coastguard Worker 
SetConfigOverrides(DnsConfigOverrides config_overrides)767*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
768*6777b538SAndroid Build Coastguard Worker   std::optional<DnsConfig> before = effective_config_;
769*6777b538SAndroid Build Coastguard Worker   overrides_ = std::move(config_overrides);
770*6777b538SAndroid Build Coastguard Worker   effective_config_ = BuildEffectiveConfig();
771*6777b538SAndroid Build Coastguard Worker   session_ = BuildSession();
772*6777b538SAndroid Build Coastguard Worker   return before != effective_config_;
773*6777b538SAndroid Build Coastguard Worker }
774*6777b538SAndroid Build Coastguard Worker 
ReplaceCurrentSession()775*6777b538SAndroid Build Coastguard Worker void MockDnsClient::ReplaceCurrentSession() {
776*6777b538SAndroid Build Coastguard Worker   // Noop if no current effective config.
777*6777b538SAndroid Build Coastguard Worker   session_ = BuildSession();
778*6777b538SAndroid Build Coastguard Worker }
779*6777b538SAndroid Build Coastguard Worker 
GetCurrentSession()780*6777b538SAndroid Build Coastguard Worker DnsSession* MockDnsClient::GetCurrentSession() {
781*6777b538SAndroid Build Coastguard Worker   return session_.get();
782*6777b538SAndroid Build Coastguard Worker }
783*6777b538SAndroid Build Coastguard Worker 
GetEffectiveConfig() const784*6777b538SAndroid Build Coastguard Worker const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
785*6777b538SAndroid Build Coastguard Worker   return effective_config_.has_value() ? &effective_config_.value() : nullptr;
786*6777b538SAndroid Build Coastguard Worker }
787*6777b538SAndroid Build Coastguard Worker 
GetDnsConfigAsValueForNetLog() const788*6777b538SAndroid Build Coastguard Worker base::Value::Dict MockDnsClient::GetDnsConfigAsValueForNetLog() const {
789*6777b538SAndroid Build Coastguard Worker   // This is just a stub implementation that never produces a meaningful value.
790*6777b538SAndroid Build Coastguard Worker   return base::Value::Dict();
791*6777b538SAndroid Build Coastguard Worker }
792*6777b538SAndroid Build Coastguard Worker 
GetHosts() const793*6777b538SAndroid Build Coastguard Worker const DnsHosts* MockDnsClient::GetHosts() const {
794*6777b538SAndroid Build Coastguard Worker   const DnsConfig* config = GetEffectiveConfig();
795*6777b538SAndroid Build Coastguard Worker   if (!config)
796*6777b538SAndroid Build Coastguard Worker     return nullptr;
797*6777b538SAndroid Build Coastguard Worker 
798*6777b538SAndroid Build Coastguard Worker   return &config->hosts;
799*6777b538SAndroid Build Coastguard Worker }
800*6777b538SAndroid Build Coastguard Worker 
GetTransactionFactory()801*6777b538SAndroid Build Coastguard Worker DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
802*6777b538SAndroid Build Coastguard Worker   return GetEffectiveConfig() ? factory_.get() : nullptr;
803*6777b538SAndroid Build Coastguard Worker }
804*6777b538SAndroid Build Coastguard Worker 
GetAddressSorter()805*6777b538SAndroid Build Coastguard Worker AddressSorter* MockDnsClient::GetAddressSorter() {
806*6777b538SAndroid Build Coastguard Worker   return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
807*6777b538SAndroid Build Coastguard Worker }
808*6777b538SAndroid Build Coastguard Worker 
IncrementInsecureFallbackFailures()809*6777b538SAndroid Build Coastguard Worker void MockDnsClient::IncrementInsecureFallbackFailures() {
810*6777b538SAndroid Build Coastguard Worker   ++fallback_failures_;
811*6777b538SAndroid Build Coastguard Worker }
812*6777b538SAndroid Build Coastguard Worker 
ClearInsecureFallbackFailures()813*6777b538SAndroid Build Coastguard Worker void MockDnsClient::ClearInsecureFallbackFailures() {
814*6777b538SAndroid Build Coastguard Worker   fallback_failures_ = 0;
815*6777b538SAndroid Build Coastguard Worker }
816*6777b538SAndroid Build Coastguard Worker 
GetSystemConfigForTesting() const817*6777b538SAndroid Build Coastguard Worker std::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
818*6777b538SAndroid Build Coastguard Worker   return config_;
819*6777b538SAndroid Build Coastguard Worker }
820*6777b538SAndroid Build Coastguard Worker 
GetConfigOverridesForTesting() const821*6777b538SAndroid Build Coastguard Worker DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
822*6777b538SAndroid Build Coastguard Worker   return overrides_;
823*6777b538SAndroid Build Coastguard Worker }
824*6777b538SAndroid Build Coastguard Worker 
SetTransactionFactoryForTesting(std::unique_ptr<DnsTransactionFactory> factory)825*6777b538SAndroid Build Coastguard Worker void MockDnsClient::SetTransactionFactoryForTesting(
826*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<DnsTransactionFactory> factory) {
827*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
828*6777b538SAndroid Build Coastguard Worker }
829*6777b538SAndroid Build Coastguard Worker 
SetAddressSorterForTesting(std::unique_ptr<AddressSorter> address_sorter)830*6777b538SAndroid Build Coastguard Worker void MockDnsClient::SetAddressSorterForTesting(
831*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<AddressSorter> address_sorter) {
832*6777b538SAndroid Build Coastguard Worker   address_sorter_ = std::move(address_sorter);
833*6777b538SAndroid Build Coastguard Worker }
834*6777b538SAndroid Build Coastguard Worker 
GetPresetAddrs(const url::SchemeHostPort & endpoint) const835*6777b538SAndroid Build Coastguard Worker std::optional<std::vector<IPEndPoint>> MockDnsClient::GetPresetAddrs(
836*6777b538SAndroid Build Coastguard Worker     const url::SchemeHostPort& endpoint) const {
837*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint));
838*6777b538SAndroid Build Coastguard Worker   return preset_addrs_;
839*6777b538SAndroid Build Coastguard Worker }
840*6777b538SAndroid Build Coastguard Worker 
CompleteDelayedTransactions()841*6777b538SAndroid Build Coastguard Worker void MockDnsClient::CompleteDelayedTransactions() {
842*6777b538SAndroid Build Coastguard Worker   factory_->CompleteDelayedTransactions();
843*6777b538SAndroid Build Coastguard Worker }
844*6777b538SAndroid Build Coastguard Worker 
CompleteOneDelayedTransactionOfType(DnsQueryType type)845*6777b538SAndroid Build Coastguard Worker bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
846*6777b538SAndroid Build Coastguard Worker   return factory_->CompleteOneDelayedTransactionOfType(type);
847*6777b538SAndroid Build Coastguard Worker }
848*6777b538SAndroid Build Coastguard Worker 
SetForceDohServerAvailable(bool available)849*6777b538SAndroid Build Coastguard Worker void MockDnsClient::SetForceDohServerAvailable(bool available) {
850*6777b538SAndroid Build Coastguard Worker   force_doh_server_available_ = available;
851*6777b538SAndroid Build Coastguard Worker   factory_->set_force_doh_server_available(available);
852*6777b538SAndroid Build Coastguard Worker }
853*6777b538SAndroid Build Coastguard Worker 
BuildEffectiveConfig()854*6777b538SAndroid Build Coastguard Worker std::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
855*6777b538SAndroid Build Coastguard Worker   if (overrides_.OverridesEverything())
856*6777b538SAndroid Build Coastguard Worker     return overrides_.ApplyOverrides(DnsConfig());
857*6777b538SAndroid Build Coastguard Worker   if (!config_ || !config_.value().IsValid())
858*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
859*6777b538SAndroid Build Coastguard Worker 
860*6777b538SAndroid Build Coastguard Worker   return overrides_.ApplyOverrides(config_.value());
861*6777b538SAndroid Build Coastguard Worker }
862*6777b538SAndroid Build Coastguard Worker 
BuildSession()863*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
864*6777b538SAndroid Build Coastguard Worker   if (!effective_config_)
865*6777b538SAndroid Build Coastguard Worker     return nullptr;
866*6777b538SAndroid Build Coastguard Worker 
867*6777b538SAndroid Build Coastguard Worker   // Session not expected to be used for anything that will actually require
868*6777b538SAndroid Build Coastguard Worker   // random numbers.
869*6777b538SAndroid Build Coastguard Worker   auto null_random_callback =
870*6777b538SAndroid Build Coastguard Worker       base::BindRepeating([](int, int) -> int { base::ImmediateCrash(); });
871*6777b538SAndroid Build Coastguard Worker 
872*6777b538SAndroid Build Coastguard Worker   return base::MakeRefCounted<DnsSession>(
873*6777b538SAndroid Build Coastguard Worker       effective_config_.value(), null_random_callback, nullptr /* net_log */);
874*6777b538SAndroid Build Coastguard Worker }
875*6777b538SAndroid Build Coastguard Worker 
MockHostResolverProc()876*6777b538SAndroid Build Coastguard Worker MockHostResolverProc::MockHostResolverProc()
877*6777b538SAndroid Build Coastguard Worker     : HostResolverProc(nullptr),
878*6777b538SAndroid Build Coastguard Worker       requests_waiting_(&lock_),
879*6777b538SAndroid Build Coastguard Worker       slots_available_(&lock_) {}
880*6777b538SAndroid Build Coastguard Worker 
881*6777b538SAndroid Build Coastguard Worker MockHostResolverProc::~MockHostResolverProc() = default;
882*6777b538SAndroid Build Coastguard Worker 
WaitFor(unsigned count)883*6777b538SAndroid Build Coastguard Worker bool MockHostResolverProc::WaitFor(unsigned count) {
884*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
885*6777b538SAndroid Build Coastguard Worker   base::Time start_time = base::Time::Now();
886*6777b538SAndroid Build Coastguard Worker   while (num_requests_waiting_ < count) {
887*6777b538SAndroid Build Coastguard Worker     requests_waiting_.TimedWait(TestTimeouts::action_timeout());
888*6777b538SAndroid Build Coastguard Worker     if (base::Time::Now() > start_time + TestTimeouts::action_timeout()) {
889*6777b538SAndroid Build Coastguard Worker       return false;
890*6777b538SAndroid Build Coastguard Worker     }
891*6777b538SAndroid Build Coastguard Worker   }
892*6777b538SAndroid Build Coastguard Worker   return true;
893*6777b538SAndroid Build Coastguard Worker }
894*6777b538SAndroid Build Coastguard Worker 
SignalMultiple(unsigned count)895*6777b538SAndroid Build Coastguard Worker void MockHostResolverProc::SignalMultiple(unsigned count) {
896*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
897*6777b538SAndroid Build Coastguard Worker   num_slots_available_ += count;
898*6777b538SAndroid Build Coastguard Worker   slots_available_.Broadcast();
899*6777b538SAndroid Build Coastguard Worker }
900*6777b538SAndroid Build Coastguard Worker 
SignalAll()901*6777b538SAndroid Build Coastguard Worker void MockHostResolverProc::SignalAll() {
902*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
903*6777b538SAndroid Build Coastguard Worker   num_slots_available_ = num_requests_waiting_;
904*6777b538SAndroid Build Coastguard Worker   slots_available_.Broadcast();
905*6777b538SAndroid Build Coastguard Worker }
906*6777b538SAndroid Build Coastguard Worker 
AddRule(const std::string & hostname,AddressFamily family,const AddressList & result,HostResolverFlags flags)907*6777b538SAndroid Build Coastguard Worker void MockHostResolverProc::AddRule(const std::string& hostname,
908*6777b538SAndroid Build Coastguard Worker                                    AddressFamily family,
909*6777b538SAndroid Build Coastguard Worker                                    const AddressList& result,
910*6777b538SAndroid Build Coastguard Worker                                    HostResolverFlags flags) {
911*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
912*6777b538SAndroid Build Coastguard Worker   rules_[ResolveKey(hostname, family, flags)] = result;
913*6777b538SAndroid Build Coastguard Worker }
914*6777b538SAndroid Build Coastguard Worker 
AddRule(const std::string & hostname,AddressFamily family,const std::string & ip_list,HostResolverFlags flags,const std::string & canonical_name)915*6777b538SAndroid Build Coastguard Worker void MockHostResolverProc::AddRule(const std::string& hostname,
916*6777b538SAndroid Build Coastguard Worker                                    AddressFamily family,
917*6777b538SAndroid Build Coastguard Worker                                    const std::string& ip_list,
918*6777b538SAndroid Build Coastguard Worker                                    HostResolverFlags flags,
919*6777b538SAndroid Build Coastguard Worker                                    const std::string& canonical_name) {
920*6777b538SAndroid Build Coastguard Worker   AddressList result;
921*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> dns_aliases;
922*6777b538SAndroid Build Coastguard Worker   if (canonical_name != "") {
923*6777b538SAndroid Build Coastguard Worker     dns_aliases = {canonical_name};
924*6777b538SAndroid Build Coastguard Worker   }
925*6777b538SAndroid Build Coastguard Worker   int rv = ParseAddressList(ip_list, &result.endpoints());
926*6777b538SAndroid Build Coastguard Worker   result.SetDnsAliases(dns_aliases);
927*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(OK, rv);
928*6777b538SAndroid Build Coastguard Worker   AddRule(hostname, family, result, flags);
929*6777b538SAndroid Build Coastguard Worker }
930*6777b538SAndroid Build Coastguard Worker 
AddRuleForAllFamilies(const std::string & hostname,const std::string & ip_list,HostResolverFlags flags,const std::string & canonical_name)931*6777b538SAndroid Build Coastguard Worker void MockHostResolverProc::AddRuleForAllFamilies(
932*6777b538SAndroid Build Coastguard Worker     const std::string& hostname,
933*6777b538SAndroid Build Coastguard Worker     const std::string& ip_list,
934*6777b538SAndroid Build Coastguard Worker     HostResolverFlags flags,
935*6777b538SAndroid Build Coastguard Worker     const std::string& canonical_name) {
936*6777b538SAndroid Build Coastguard Worker   AddressList result;
937*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> dns_aliases;
938*6777b538SAndroid Build Coastguard Worker   if (canonical_name != "") {
939*6777b538SAndroid Build Coastguard Worker     dns_aliases = {canonical_name};
940*6777b538SAndroid Build Coastguard Worker   }
941*6777b538SAndroid Build Coastguard Worker   int rv = ParseAddressList(ip_list, &result.endpoints());
942*6777b538SAndroid Build Coastguard Worker   result.SetDnsAliases(dns_aliases);
943*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(OK, rv);
944*6777b538SAndroid Build Coastguard Worker   AddRule(hostname, ADDRESS_FAMILY_UNSPECIFIED, result, flags);
945*6777b538SAndroid Build Coastguard Worker   AddRule(hostname, ADDRESS_FAMILY_IPV4, result, flags);
946*6777b538SAndroid Build Coastguard Worker   AddRule(hostname, ADDRESS_FAMILY_IPV6, result, flags);
947*6777b538SAndroid Build Coastguard Worker }
948*6777b538SAndroid Build Coastguard Worker 
Resolve(const std::string & hostname,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)949*6777b538SAndroid Build Coastguard Worker int MockHostResolverProc::Resolve(const std::string& hostname,
950*6777b538SAndroid Build Coastguard Worker                                   AddressFamily address_family,
951*6777b538SAndroid Build Coastguard Worker                                   HostResolverFlags host_resolver_flags,
952*6777b538SAndroid Build Coastguard Worker                                   AddressList* addrlist,
953*6777b538SAndroid Build Coastguard Worker                                   int* os_error) {
954*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
955*6777b538SAndroid Build Coastguard Worker   capture_list_.emplace_back(hostname, address_family, host_resolver_flags);
956*6777b538SAndroid Build Coastguard Worker   ++num_requests_waiting_;
957*6777b538SAndroid Build Coastguard Worker   requests_waiting_.Broadcast();
958*6777b538SAndroid Build Coastguard Worker   {
959*6777b538SAndroid Build Coastguard Worker     base::ScopedAllowBaseSyncPrimitivesForTesting
960*6777b538SAndroid Build Coastguard Worker         scoped_allow_base_sync_primitives;
961*6777b538SAndroid Build Coastguard Worker     while (!num_slots_available_) {
962*6777b538SAndroid Build Coastguard Worker       slots_available_.Wait();
963*6777b538SAndroid Build Coastguard Worker     }
964*6777b538SAndroid Build Coastguard Worker   }
965*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(num_requests_waiting_, 0u);
966*6777b538SAndroid Build Coastguard Worker   --num_slots_available_;
967*6777b538SAndroid Build Coastguard Worker   --num_requests_waiting_;
968*6777b538SAndroid Build Coastguard Worker   if (rules_.empty()) {
969*6777b538SAndroid Build Coastguard Worker     int rv = ParseAddressList("127.0.0.1", &addrlist->endpoints());
970*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(OK, rv);
971*6777b538SAndroid Build Coastguard Worker     return OK;
972*6777b538SAndroid Build Coastguard Worker   }
973*6777b538SAndroid Build Coastguard Worker   ResolveKey key(hostname, address_family, host_resolver_flags);
974*6777b538SAndroid Build Coastguard Worker   if (rules_.count(key) == 0) {
975*6777b538SAndroid Build Coastguard Worker     return ERR_NAME_NOT_RESOLVED;
976*6777b538SAndroid Build Coastguard Worker   }
977*6777b538SAndroid Build Coastguard Worker   *addrlist = rules_[key];
978*6777b538SAndroid Build Coastguard Worker   return OK;
979*6777b538SAndroid Build Coastguard Worker }
980*6777b538SAndroid Build Coastguard Worker 
GetCaptureList() const981*6777b538SAndroid Build Coastguard Worker MockHostResolverProc::CaptureList MockHostResolverProc::GetCaptureList() const {
982*6777b538SAndroid Build Coastguard Worker   CaptureList copy;
983*6777b538SAndroid Build Coastguard Worker   {
984*6777b538SAndroid Build Coastguard Worker     base::AutoLock lock(lock_);
985*6777b538SAndroid Build Coastguard Worker     copy = capture_list_;
986*6777b538SAndroid Build Coastguard Worker   }
987*6777b538SAndroid Build Coastguard Worker   return copy;
988*6777b538SAndroid Build Coastguard Worker }
989*6777b538SAndroid Build Coastguard Worker 
ClearCaptureList()990*6777b538SAndroid Build Coastguard Worker void MockHostResolverProc::ClearCaptureList() {
991*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
992*6777b538SAndroid Build Coastguard Worker   capture_list_.clear();
993*6777b538SAndroid Build Coastguard Worker }
994*6777b538SAndroid Build Coastguard Worker 
HasBlockedRequests() const995*6777b538SAndroid Build Coastguard Worker bool MockHostResolverProc::HasBlockedRequests() const {
996*6777b538SAndroid Build Coastguard Worker   base::AutoLock lock(lock_);
997*6777b538SAndroid Build Coastguard Worker   return num_requests_waiting_ > num_slots_available_;
998*6777b538SAndroid Build Coastguard Worker }
999*6777b538SAndroid Build Coastguard Worker 
1000*6777b538SAndroid Build Coastguard Worker }  // namespace net
1001