xref: /aosp_15_r20/external/cronet/net/dns/dns_test_util.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_DNS_DNS_TEST_UTIL_H_
6 #define NET_DNS_DNS_TEST_UTIL_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <memory>
12 #include <optional>
13 #include <set>
14 #include <string>
15 #include <string_view>
16 #include <utility>
17 #include <vector>
18 
19 #include "base/containers/span.h"
20 #include "base/memory/raw_ptr.h"
21 #include "base/memory/scoped_refptr.h"
22 #include "base/memory/weak_ptr.h"
23 #include "base/synchronization/condition_variable.h"
24 #include "base/time/time.h"
25 #include "base/values.h"
26 #include "net/base/connection_endpoint_metadata.h"
27 #include "net/base/ip_endpoint.h"
28 #include "net/dns/dns_client.h"
29 #include "net/dns/dns_config.h"
30 #include "net/dns/dns_response.h"
31 #include "net/dns/dns_transaction.h"
32 #include "net/dns/dns_util.h"
33 #include "net/dns/public/dns_over_https_server_config.h"
34 #include "net/dns/public/dns_protocol.h"
35 #include "net/dns/public/secure_dns_mode.h"
36 #include "net/socket/socket_test_util.h"
37 #include "url/scheme_host_port.h"
38 
39 namespace net {
40 
41 //-----------------------------------------------------------------------------
42 // Query/response set for www.google.com, ID is fixed to 0.
43 static const char kT0HostName[] = "www.google.com";
44 static const uint16_t kT0Qtype = dns_protocol::kTypeA;
45 static const char kT0DnsName[] = {
46   0x03, 'w', 'w', 'w',
47   0x06, 'g', 'o', 'o', 'g', 'l', 'e',
48   0x03, 'c', 'o', 'm',
49   0x00
50 };
51 static const size_t kT0QuerySize = 32;
52 static const uint8_t kT0ResponseDatagram[] = {
53     // response contains one CNAME for www.l.google.com and the following
54     // IP addresses: 74.125.226.{179,180,176,177,178}
55     0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
56     0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
57     0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05,
58     0x00, 0x01, 0x00, 0x01, 0x4d, 0x13, 0x00, 0x08, 0x03, 0x77, 0x77, 0x77,
59     0x01, 0x6c, 0xc0, 0x10, 0xc0, 0x2c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
60     0x00, 0xe4, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb3, 0xc0, 0x2c, 0x00, 0x01,
61     0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb4,
62     0xc0, 0x2c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04,
63     0x4a, 0x7d, 0xe2, 0xb0, 0xc0, 0x2c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
64     0x00, 0xe4, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb1, 0xc0, 0x2c, 0x00, 0x01,
65     0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb2};
66 static const char* const kT0IpAddresses[] = {
67   "74.125.226.179", "74.125.226.180", "74.125.226.176",
68   "74.125.226.177", "74.125.226.178"
69 };
70 static const char kT0CanonName[] = "www.l.google.com";
71 static const base::TimeDelta kT0Ttl = base::Seconds(0x000000e4);
72 // +1 for the CNAME record.
73 static const unsigned kT0RecordCount = std::size(kT0IpAddresses) + 1;
74 
75 //-----------------------------------------------------------------------------
76 // Query/response set for codereview.chromium.org, ID is fixed to 1.
77 static const char kT1HostName[] = "codereview.chromium.org";
78 static const uint16_t kT1Qtype = dns_protocol::kTypeA;
79 static const char kT1DnsName[] = {
80   0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
81   0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
82   0x03, 'o', 'r', 'g',
83   0x00
84 };
85 static const size_t kT1QuerySize = 41;
86 static const uint8_t kT1ResponseDatagram[] = {
87     // response contains one CNAME for ghs.l.google.com and the following
88     // IP address: 64.233.169.121
89     0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
90     0x00, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x65, 0x76, 0x69, 0x65,
91     0x77, 0x08, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x03,
92     0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00,
93     0x05, 0x00, 0x01, 0x00, 0x01, 0x41, 0x75, 0x00, 0x12, 0x03, 0x67,
94     0x68, 0x73, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
95     0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0, 0x35, 0x00, 0x01, 0x00, 0x01,
96     0x00, 0x00, 0x01, 0x0b, 0x00, 0x04, 0x40, 0xe9, 0xa9, 0x79};
97 static const char* const kT1IpAddresses[] = {
98   "64.233.169.121"
99 };
100 static const char kT1CanonName[] = "ghs.l.google.com";
101 static const base::TimeDelta kT1Ttl = base::Seconds(0x0000010b);
102 // +1 for the CNAME record.
103 static const unsigned kT1RecordCount = std::size(kT1IpAddresses) + 1;
104 
105 //-----------------------------------------------------------------------------
106 // Query/response set for www.ccs.neu.edu, ID is fixed to 2.
107 static const char kT2HostName[] = "www.ccs.neu.edu";
108 static const uint16_t kT2Qtype = dns_protocol::kTypeA;
109 static const char kT2DnsName[] = {
110   0x03, 'w', 'w', 'w',
111   0x03, 'c', 'c', 's',
112   0x03, 'n', 'e', 'u',
113   0x03, 'e', 'd', 'u',
114   0x00
115 };
116 static const size_t kT2QuerySize = 33;
117 static const uint8_t kT2ResponseDatagram[] = {
118     // response contains one CNAME for vulcan.ccs.neu.edu and the following
119     // IP address: 129.10.116.81
120     0x00, 0x02, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
121     0x03, 0x77, 0x77, 0x77, 0x03, 0x63, 0x63, 0x73, 0x03, 0x6e, 0x65, 0x75,
122     0x03, 0x65, 0x64, 0x75, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00,
123     0x05, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x09, 0x06, 0x76, 0x75,
124     0x6c, 0x63, 0x61, 0x6e, 0xc0, 0x10, 0xc0, 0x2d, 0x00, 0x01, 0x00, 0x01,
125     0x00, 0x00, 0x01, 0x2c, 0x00, 0x04, 0x81, 0x0a, 0x74, 0x51};
126 static const char* const kT2IpAddresses[] = {
127   "129.10.116.81"
128 };
129 static const char kT2CanonName[] = "vulcan.ccs.neu.edu";
130 static const base::TimeDelta kT2Ttl = base::Seconds(0x0000012c);
131 // +1 for the CNAME record.
132 static const unsigned kT2RecordCount = std::size(kT2IpAddresses) + 1;
133 
134 //-----------------------------------------------------------------------------
135 // Query/response set for www.google.az, ID is fixed to 3.
136 static const char kT3HostName[] = "www.google.az";
137 static const uint16_t kT3Qtype = dns_protocol::kTypeA;
138 static const char kT3DnsName[] = {
139   0x03, 'w', 'w', 'w',
140   0x06, 'g', 'o', 'o', 'g', 'l', 'e',
141   0x02, 'a', 'z',
142   0x00
143 };
144 static const size_t kT3QuerySize = 31;
145 static const uint8_t kT3ResponseDatagram[] = {
146     // response contains www.google.com as CNAME for www.google.az and
147     // www.l.google.com as CNAME for www.google.com and the following
148     // IP addresses: 74.125.226.{178,179,180,176,177}
149     // The TTLs on the records are: 0x00015099, 0x00025099, 0x00000415,
150     // 0x00003015, 0x00002015, 0x00000015, 0x00001015.
151     // The last record is an imaginary TXT record for t.google.com.
152     0x00, 0x03, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
153     0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x02,
154     0x61, 0x7a, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00,
155     0x01, 0x00, 0x01, 0x50, 0x99, 0x00, 0x10, 0x03, 0x77, 0x77, 0x77, 0x06,
156     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0,
157     0x2b, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x50, 0x99, 0x00, 0x08, 0x03,
158     0x77, 0x77, 0x77, 0x01, 0x6c, 0xc0, 0x2f, 0xc0, 0x47, 0x00, 0x01, 0x00,
159     0x01, 0x00, 0x00, 0x04, 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb2, 0xc0,
160     0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x30, 0x15, 0x00, 0x04, 0x4a,
161     0x7d, 0xe2, 0xb3, 0xc0, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x20,
162     0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb4, 0xc0, 0x47, 0x00, 0x01, 0x00,
163     0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb0, 0xc0,
164     0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10, 0x15, 0x00, 0x04, 0x4a,
165     0x7d, 0xe2, 0xb1, 0x01, 0x74, 0xc0, 0x2f, 0x00, 0x10, 0x00, 0x01, 0x00,
166     0x00, 0x00, 0x01, 0x00, 0x04, 0xde, 0xad, 0xfe, 0xed};
167 static const char* const kT3IpAddresses[] = {
168   "74.125.226.178", "74.125.226.179", "74.125.226.180",
169   "74.125.226.176", "74.125.226.177"
170 };
171 static const char kT3CanonName[] = "www.l.google.com";
172 static const base::TimeDelta kT3Ttl = base::Seconds(0x00000015);
173 // +2 for the CNAME records, +1 for TXT record.
174 static const unsigned kT3RecordCount = std::size(kT3IpAddresses) + 3;
175 
176 //-----------------------------------------------------------------------------
177 // Query/response set for www.gstatic.com, ID is fixed to 0.
178 static const char kT4HostName[] = "www.gstatic.com";
179 static const uint16_t kT4Qtype = dns_protocol::kTypeA;
180 static const char kT4DnsName[] = {0x03, 'w', 'w', 'w', 0x07, 'g',
181                                   's',  't', 'a', 't', 'i',  'c',
182                                   0x03, 'c', 'o', 'm', 0x00};
183 static const size_t kT4QuerySize = 33;
184 static const uint8_t kT4ResponseDatagram[] = {
185     // response contains the following IP addresses: 172.217.6.195.
186     0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
187     0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x07, 0x67, 0x73, 0x74,
188     0x61, 0x74, 0x69, 0x63, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
189     0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,
190     0x00, 0x01, 0x2b, 0x00, 0x04, 0xac, 0xd9, 0x06, 0xc3};
191 
192 static const char* const kT4IpAddresses[] = {"172.217.6.195"};
193 static const base::TimeDelta kT4Ttl = base::Seconds(0x0000012b);
194 static const unsigned kT4RecordCount = std::size(kT0IpAddresses);
195 
196 class AddressSorter;
197 class DnsClient;
198 class DnsSession;
199 class IPAddress;
200 class ResolveContext;
201 class URLRequestContext;
202 
203 DnsConfig CreateValidDnsConfig();
204 
205 DnsResourceRecord BuildTestDnsRecord(std::string name,
206                                      uint16_t type,
207                                      std::string rdata,
208                                      base::TimeDelta ttl = base::Days(1));
209 
210 DnsResourceRecord BuildTestCnameRecord(std::string name,
211                                        std::string_view canonical_name,
212                                        base::TimeDelta ttl = base::Days(1));
213 
214 DnsResourceRecord BuildTestAddressRecord(std::string name,
215                                          const IPAddress& ip,
216                                          base::TimeDelta ttl = base::Days(1));
217 
218 DnsResourceRecord BuildTestTextRecord(std::string name,
219                                       std::vector<std::string> text_strings,
220                                       base::TimeDelta ttl = base::Days(1));
221 
222 DnsResourceRecord BuildTestHttpsAliasRecord(
223     std::string name,
224     std::string_view alias_name,
225     base::TimeDelta ttl = base::Days(1));
226 
227 std::pair<uint16_t, std::string> BuildTestHttpsServiceAlpnParam(
228     const std::vector<std::string>& alpns);
229 
230 std::pair<uint16_t, std::string> BuildTestHttpsServiceEchConfigParam(
231     base::span<const uint8_t> ech_config_list);
232 
233 std::pair<uint16_t, std::string> BuildTestHttpsServiceMandatoryParam(
234     std::vector<uint16_t> param_key_list);
235 
236 std::pair<uint16_t, std::string> BuildTestHttpsServicePortParam(uint16_t port);
237 
238 // `params` is a mapping from service param keys to a string containing the
239 // encoded bytes of a service param value (without the value length prefix which
240 // this method will automatically add).
241 DnsResourceRecord BuildTestHttpsServiceRecord(
242     std::string name,
243     uint16_t priority,
244     std::string_view service_name,
245     const std::map<uint16_t, std::string>& params,
246     base::TimeDelta ttl = base::Days(1));
247 
248 DnsResponse BuildTestDnsResponse(
249     std::string name,
250     uint16_t type,
251     const std::vector<DnsResourceRecord>& answers,
252     const std::vector<DnsResourceRecord>& authority = {},
253     const std::vector<DnsResourceRecord>& additional = {},
254     uint8_t rcode = dns_protocol::kRcodeNOERROR);
255 
256 DnsResponse BuildTestDnsAddressResponse(std::string name,
257                                         const IPAddress& ip,
258                                         std::string answer_name = "");
259 DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
260                                                  const IPAddress& ip,
261                                                  std::string cannonname,
262                                                  std::string answer_name = "");
263 
264 // If |answer_name| is empty, |name| will be used for all answer records, as is
265 // the normal behavior.
266 DnsResponse BuildTestDnsTextResponse(
267     std::string name,
268     std::vector<std::vector<std::string>> text_records,
269     std::string answer_name = "");
270 DnsResponse BuildTestDnsPointerResponse(std::string name,
271                                         std::vector<std::string> pointer_names,
272                                         std::string answer_name = "");
273 
274 struct TestServiceRecord {
275   uint16_t priority;
276   uint16_t weight;
277   uint16_t port;
278   std::string target;
279 };
280 
281 DnsResponse BuildTestDnsServiceResponse(
282     std::string name,
283     std::vector<TestServiceRecord> service_records,
284     std::string answer_name = "");
285 
286 struct MockDnsClientRule {
287   enum class ResultType {
288     // Fail asynchronously with ERR_NAME_NOT_RESOLVED and NXDOMAIN.
289     kNoDomain,
290     // Fail asynchronously with `net_error` or (if nullopt)
291     // ERR_NAME_NOT_RESOLVED and  `response` if not nullopt.
292     kFail,
293     // Fail asynchronously with ERR_DNS_TIMED_OUT.
294     kTimeout,
295     // Simulates a slow transaction that will complete only with a lenient
296     // timeout. Fails asynchronously with ERR_DNS_TIMED_OUT only if the
297     // transaction was created with |fast_timeout|. Otherwise completes
298     // successfully as if the ResultType were |kOk|.
299     kSlow,
300     // Return an empty response.
301     kEmpty,
302     // "Succeed" but with an unparsable response.
303     kMalformed,
304     // Immediately records a test failure if queried. Used to catch unexpected
305     // queries. Alternately, if combined with `MockDnsClientRule::delay`, fails
306     // only if the query is allowed to complete without being cancelled.
307     kUnexpected,
308 
309     // Results in the response in |Result::response| or, if null, results in a
310     // localhost IP response.
311     kOk,
312   };
313 
314   struct Result {
315     explicit Result(ResultType type,
316                     std::optional<DnsResponse> response = std::nullopt,
317                     std::optional<int> net_error = std::nullopt);
318     explicit Result(DnsResponse response);
319     Result(Result&&);
320     Result& operator=(Result&&);
321     ~Result();
322 
323     ResultType type;
324     std::optional<DnsResponse> response;
325     std::optional<int> net_error;
326   };
327 
328   // If |delay| is true, matching transactions will be delayed until triggered
329   // by the consumer. If |context| is non-null, it will only match transactions
330   // with the same context.
331   MockDnsClientRule(const std::string& prefix,
332                     uint16_t qtype,
333                     bool secure,
334                     Result result,
335                     bool delay,
336                     URLRequestContext* context = nullptr);
337   MockDnsClientRule(MockDnsClientRule&& rule);
338 
339   Result result;
340   std::string prefix;
341   uint16_t qtype;
342   bool secure;
343   bool delay;
344   raw_ptr<URLRequestContext, DanglingUntriaged> context;
345 };
346 
347 typedef std::vector<MockDnsClientRule> MockDnsClientRuleList;
348 
349 // A DnsTransactionFactory which creates MockTransaction.
350 class MockDnsTransactionFactory : public DnsTransactionFactory {
351  public:
352   explicit MockDnsTransactionFactory(MockDnsClientRuleList rules);
353   ~MockDnsTransactionFactory() override;
354 
355   std::unique_ptr<DnsTransaction> CreateTransaction(
356       std::string hostname,
357       uint16_t qtype,
358       const NetLogWithSource&,
359       bool secure,
360       SecureDnsMode secure_dns_mode,
361       ResolveContext* resolve_context,
362       bool fast_timeout) override;
363 
364   std::unique_ptr<DnsProbeRunner> CreateDohProbeRunner(
365       ResolveContext* resolve_context) override;
366 
367   void AddEDNSOption(std::unique_ptr<OptRecordRdata::Opt> opt) override;
368 
369   SecureDnsMode GetSecureDnsModeForTest() override;
370 
371   void CompleteDelayedTransactions();
372   // If there are any pending transactions of the given type,
373   // completes one and returns true. Otherwise, returns false.
374   [[nodiscard]] bool CompleteOneDelayedTransactionOfType(DnsQueryType type);
375 
doh_probes_running()376   bool doh_probes_running() { return !running_doh_probe_runners_.empty(); }
CompleteDohProbeRuners()377   void CompleteDohProbeRuners() { running_doh_probe_runners_.clear(); }
378 
set_force_doh_server_available(bool available)379   void set_force_doh_server_available(bool available) {
380     force_doh_server_available_ = available;
381   }
382 
383  private:
384   class MockTransaction;
385   class MockDohProbeRunner;
386   using DelayedTransactionList = std::vector<base::WeakPtr<MockTransaction>>;
387 
388   MockDnsClientRuleList rules_;
389   DelayedTransactionList delayed_transactions_;
390 
391   bool force_doh_server_available_ = true;
392   std::set<raw_ptr<MockDohProbeRunner, SetExperimental>>
393       running_doh_probe_runners_;
394 
395   base::WeakPtrFactory<MockDnsTransactionFactory> weak_ptr_factory_{this};
396 };
397 
398 // MockDnsClient provides MockDnsTransactionFactory.
399 class MockDnsClient : public DnsClient {
400  public:
401   MockDnsClient(DnsConfig config, MockDnsClientRuleList rules);
402   ~MockDnsClient() override;
403 
404   // DnsClient interface:
405   bool CanUseSecureDnsTransactions() const override;
406   bool CanUseInsecureDnsTransactions() const override;
407   bool CanQueryAdditionalTypesViaInsecureDns() const override;
408   void SetInsecureEnabled(bool enabled, bool additional_types_enabled) override;
409   bool FallbackFromSecureTransactionPreferred(
410       ResolveContext* resolve_context) const override;
411   bool FallbackFromInsecureTransactionPreferred() const override;
412   bool SetSystemConfig(std::optional<DnsConfig> system_config) override;
413   bool SetConfigOverrides(DnsConfigOverrides config_overrides) override;
414   void ReplaceCurrentSession() override;
415   DnsSession* GetCurrentSession() override;
416   const DnsConfig* GetEffectiveConfig() const override;
417   const DnsHosts* GetHosts() const override;
418   DnsTransactionFactory* GetTransactionFactory() override;
419   AddressSorter* GetAddressSorter() override;
420   void IncrementInsecureFallbackFailures() override;
421   void ClearInsecureFallbackFailures() override;
422   base::Value::Dict GetDnsConfigAsValueForNetLog() const override;
423   std::optional<DnsConfig> GetSystemConfigForTesting() const override;
424   DnsConfigOverrides GetConfigOverridesForTesting() const override;
425   void SetTransactionFactoryForTesting(
426       std::unique_ptr<DnsTransactionFactory> factory) override;
427   void SetAddressSorterForTesting(
428       std::unique_ptr<AddressSorter> address_sorter) override;
429   std::optional<std::vector<IPEndPoint>> GetPresetAddrs(
430       const url::SchemeHostPort& endpoint) const override;
431 
432   // Completes all DnsTransactions that were delayed by a rule.
433   void CompleteDelayedTransactions();
434   // If there are any pending transactions of the given type,
435   // completes one and returns true. Otherwise, returns false.
436   [[nodiscard]] bool CompleteOneDelayedTransactionOfType(DnsQueryType type);
437 
set_max_fallback_failures(int max_fallback_failures)438   void set_max_fallback_failures(int max_fallback_failures) {
439     max_fallback_failures_ = max_fallback_failures;
440   }
441 
set_ignore_system_config_changes(bool ignore_system_config_changes)442   void set_ignore_system_config_changes(bool ignore_system_config_changes) {
443     ignore_system_config_changes_ = ignore_system_config_changes;
444   }
445 
set_preset_endpoint(std::optional<url::SchemeHostPort> endpoint)446   void set_preset_endpoint(std::optional<url::SchemeHostPort> endpoint) {
447     preset_endpoint_ = std::move(endpoint);
448   }
449 
set_preset_addrs(std::vector<IPEndPoint> preset_addrs)450   void set_preset_addrs(std::vector<IPEndPoint> preset_addrs) {
451     preset_addrs_ = std::move(preset_addrs);
452   }
453 
454   void SetForceDohServerAvailable(bool available);
455 
factory()456   MockDnsTransactionFactory* factory() { return factory_.get(); }
457 
458  private:
459   std::optional<DnsConfig> BuildEffectiveConfig();
460   scoped_refptr<DnsSession> BuildSession();
461 
462   bool insecure_enabled_ = false;
463   bool additional_types_enabled_ = false;
464   int fallback_failures_ = 0;
465   int max_fallback_failures_ = DnsClient::kMaxInsecureFallbackFailures;
466   bool ignore_system_config_changes_ = false;
467 
468   // If |true|, MockDnsClient will always pretend DoH servers are available and
469   // allow secure transactions no matter what the state is in the transaction
470   // ResolveContext. If |false|, the ResolveContext must contain at least one
471   // available DoH server to allow secure transactions.
472   bool force_doh_server_available_ = true;
473 
474   MockClientSocketFactory socket_factory_;
475   std::optional<DnsConfig> config_;
476   scoped_refptr<DnsSession> session_;
477   DnsConfigOverrides overrides_;
478   std::optional<DnsConfig> effective_config_;
479   std::unique_ptr<MockDnsTransactionFactory> factory_;
480   std::unique_ptr<AddressSorter> address_sorter_;
481   std::optional<url::SchemeHostPort> preset_endpoint_;
482   std::optional<std::vector<IPEndPoint>> preset_addrs_;
483 };
484 
485 // A HostResolverProc that pushes each host mapped into a list and allows
486 // waiting for a specific number of requests. Unlike RuleBasedHostResolverProc
487 // it never calls SystemHostResolverCall. By default resolves all hostnames to
488 // "127.0.0.1". After AddRule(), it resolves only names explicitly specified.
489 class MockHostResolverProc : public HostResolverProc {
490  public:
491   struct ResolveKey {
ResolveKeyResolveKey492     ResolveKey(const std::string& hostname,
493                AddressFamily address_family,
494                HostResolverFlags flags)
495         : hostname(hostname), address_family(address_family), flags(flags) {}
496     bool operator<(const ResolveKey& other) const {
497       return std::tie(address_family, hostname, flags) <
498              std::tie(other.address_family, other.hostname, other.flags);
499     }
500     std::string hostname;
501     AddressFamily address_family;
502     HostResolverFlags flags;
503   };
504 
505   typedef std::vector<ResolveKey> CaptureList;
506 
507   MockHostResolverProc();
508 
509   MockHostResolverProc(const MockHostResolverProc&) = delete;
510   MockHostResolverProc& operator=(const MockHostResolverProc&) = delete;
511 
512   // Waits until `count` calls to `Resolve` are blocked. Returns false when
513   // timed out.
514   bool WaitFor(unsigned count);
515 
516   // Signals `count` waiting calls to `Resolve`. First come first served.
517   void SignalMultiple(unsigned count);
518 
519   // Signals all waiting calls to `Resolve`. Beware of races.
520   void SignalAll();
521 
522   void AddRule(const std::string& hostname,
523                AddressFamily family,
524                const AddressList& result,
525                HostResolverFlags flags = 0);
526 
527   void AddRule(const std::string& hostname,
528                AddressFamily family,
529                const std::string& ip_list,
530                HostResolverFlags flags = 0,
531                const std::string& canonical_name = "");
532 
533   void AddRuleForAllFamilies(const std::string& hostname,
534                              const std::string& ip_list,
535                              HostResolverFlags flags = 0,
536                              const std::string& canonical_name = "");
537 
538   int Resolve(const std::string& hostname,
539               AddressFamily address_family,
540               HostResolverFlags host_resolver_flags,
541               AddressList* addrlist,
542               int* os_error) override;
543 
544   CaptureList GetCaptureList() const;
545 
546   void ClearCaptureList();
547 
548   bool HasBlockedRequests() const;
549 
550  protected:
551   ~MockHostResolverProc() override;
552 
553  private:
554   mutable base::Lock lock_;
555   std::map<ResolveKey, AddressList> rules_;
556   CaptureList capture_list_;
557   unsigned num_requests_waiting_ = 0;
558   unsigned num_slots_available_ = 0;
559   base::ConditionVariable requests_waiting_;
560   base::ConditionVariable slots_available_;
561 };
562 
563 }  // namespace net
564 
565 #endif  // NET_DNS_DNS_TEST_UTIL_H_
566