1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 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/resolve_context.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/test/metrics/histogram_tester.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/base/address_list.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_address.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_endpoint.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/base/mock_network_change_notifier.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/base/network_change_notifier.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/base/network_isolation_key.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_config.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_server_iterator.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_session.h"
28*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_util.h"
29*6777b538SAndroid Build Coastguard Worker #include "net/dns/host_cache.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_over_https_config.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_over_https_server_config.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_protocol.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_query_type.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/host_resolver_source.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/secure_dns_mode.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_test_util.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/test/test_with_task_environment.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_context.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_context_builder.h"
40*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_test_util.h"
41*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
42*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker namespace net {
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker namespace {
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker class ResolveContextTest : public ::testing::Test, public WithTaskEnvironment {
49*6777b538SAndroid Build Coastguard Worker protected:
ResolveContextTest()50*6777b538SAndroid Build Coastguard Worker ResolveContextTest()
51*6777b538SAndroid Build Coastguard Worker : WithTaskEnvironment(
52*6777b538SAndroid Build Coastguard Worker base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
53*6777b538SAndroid Build Coastguard Worker
CreateDnsSession(const DnsConfig & config)54*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> CreateDnsSession(const DnsConfig& config) {
55*6777b538SAndroid Build Coastguard Worker auto null_random_callback =
56*6777b538SAndroid Build Coastguard Worker base::BindRepeating([](int, int) -> int { base::ImmediateCrash(); });
57*6777b538SAndroid Build Coastguard Worker return base::MakeRefCounted<DnsSession>(config, null_random_callback,
58*6777b538SAndroid Build Coastguard Worker nullptr /* netlog */);
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker protected:
62*6777b538SAndroid Build Coastguard Worker test::ScopedMockNetworkChangeNotifier mock_notifier_;
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker private:
65*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MockClientSocketFactory> socket_factory_ =
66*6777b538SAndroid Build Coastguard Worker std::make_unique<MockClientSocketFactory>();
67*6777b538SAndroid Build Coastguard Worker };
68*6777b538SAndroid Build Coastguard Worker
CreateDnsConfig(int num_servers,int num_doh_servers)69*6777b538SAndroid Build Coastguard Worker DnsConfig CreateDnsConfig(int num_servers, int num_doh_servers) {
70*6777b538SAndroid Build Coastguard Worker DnsConfig config;
71*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < num_servers; ++i) {
72*6777b538SAndroid Build Coastguard Worker IPEndPoint dns_endpoint(IPAddress(192, 168, 1, static_cast<uint8_t>(i)),
73*6777b538SAndroid Build Coastguard Worker dns_protocol::kDefaultPort);
74*6777b538SAndroid Build Coastguard Worker config.nameservers.push_back(dns_endpoint);
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker std::vector<std::string> templates;
77*6777b538SAndroid Build Coastguard Worker templates.reserve(num_doh_servers);
78*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < num_doh_servers; ++i) {
79*6777b538SAndroid Build Coastguard Worker templates.push_back(
80*6777b538SAndroid Build Coastguard Worker base::StringPrintf("https://mock.http/doh_test_%d{?dns}", i));
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker config.doh_config =
83*6777b538SAndroid Build Coastguard Worker *DnsOverHttpsConfig::FromTemplatesForTesting(std::move(templates));
84*6777b538SAndroid Build Coastguard Worker config.secure_dns_mode = SecureDnsMode::kAutomatic;
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker return config;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
CreateDnsConfigWithKnownDohProviderConfig()89*6777b538SAndroid Build Coastguard Worker DnsConfig CreateDnsConfigWithKnownDohProviderConfig() {
90*6777b538SAndroid Build Coastguard Worker DnsConfig config;
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1306495): Refactor this to not rely on an entry
93*6777b538SAndroid Build Coastguard Worker // for 8.8.8.8 existing in the DoH provider list.
94*6777b538SAndroid Build Coastguard Worker IPEndPoint dns_endpoint(IPAddress(8, 8, 8, 8), dns_protocol::kDefaultPort);
95*6777b538SAndroid Build Coastguard Worker config.nameservers.push_back(dns_endpoint);
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker config.doh_config = DnsOverHttpsConfig(
98*6777b538SAndroid Build Coastguard Worker GetDohUpgradeServersFromNameservers(config.nameservers));
99*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(config.doh_config.servers().empty());
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker config.secure_dns_mode = SecureDnsMode::kAutomatic;
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker return config;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker // Simulate a new session with the same pointer as an old deleted session by
107*6777b538SAndroid Build Coastguard Worker // invalidating WeakPtrs.
TEST_F(ResolveContextTest,ReusedSessionPointer)108*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, ReusedSessionPointer) {
109*6777b538SAndroid Build Coastguard Worker DnsConfig config =
110*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
111*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
114*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
115*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
116*6777b538SAndroid Build Coastguard Worker false /* network_change */);
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker // Mark probe success for the "original" (pre-invalidation) session.
119*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
120*6777b538SAndroid Build Coastguard Worker session.get());
121*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.GetDohServerAvailability(1u, session.get()));
122*6777b538SAndroid Build Coastguard Worker
123*6777b538SAndroid Build Coastguard Worker // Simulate session destruction and recreation on the same pointer.
124*6777b538SAndroid Build Coastguard Worker session->InvalidateWeakPtrsForTesting();
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker // Expect |session| should now be treated as a new session, not matching
127*6777b538SAndroid Build Coastguard Worker // |context|'s "current" session. Expect availability from the "old" session
128*6777b538SAndroid Build Coastguard Worker // should not be read and RecordServerSuccess() should have no effect because
129*6777b538SAndroid Build Coastguard Worker // the "new" session has not yet been marked as "current" through
130*6777b538SAndroid Build Coastguard Worker // InvalidateCaches().
131*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.GetDohServerAvailability(1u, session.get()));
132*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
133*6777b538SAndroid Build Coastguard Worker session.get());
134*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.GetDohServerAvailability(1u, session.get()));
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerAvailability_InitialAvailability)137*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerAvailability_InitialAvailability) {
138*6777b538SAndroid Build Coastguard Worker DnsConfig config =
139*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
140*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
143*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
144*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
145*6777b538SAndroid Build Coastguard Worker false /* network_change */);
146*6777b538SAndroid Build Coastguard Worker
147*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.NumAvailableDohServers(session.get()), 0u);
148*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
149*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
150*6777b538SAndroid Build Coastguard Worker
151*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(doh_itr->AttemptAvailable());
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
154*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
155*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
156*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
157*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
158*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
159*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
160*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
161*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status", 0);
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerAvailability_RecordedSuccess)164*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerAvailability_RecordedSuccess) {
165*6777b538SAndroid Build Coastguard Worker DnsConfig config =
166*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
167*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
168*6777b538SAndroid Build Coastguard Worker
169*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
170*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
171*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
172*6777b538SAndroid Build Coastguard Worker false /* network_change */);
173*6777b538SAndroid Build Coastguard Worker
174*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(context.NumAvailableDohServers(session.get()), 0u);
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
177*6777b538SAndroid Build Coastguard Worker session.get());
178*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.NumAvailableDohServers(session.get()), 1u);
179*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
180*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
183*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
186*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
187*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
188*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
189*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
190*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
191*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
192*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
193*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status", 1);
194*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
195*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
196*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kSuccessWithNoPriorFailures, 1);
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerAvailability_NoCurrentSession)199*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerAvailability_NoCurrentSession) {
200*6777b538SAndroid Build Coastguard Worker DnsConfig config =
201*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
202*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
203*6777b538SAndroid Build Coastguard Worker
204*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
205*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
208*6777b538SAndroid Build Coastguard Worker session.get());
209*6777b538SAndroid Build Coastguard Worker
210*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
211*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(doh_itr->AttemptAvailable());
214*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
215*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.GetDohServerAvailability(1, session.get()));
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerAvailability_DifferentSession)218*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerAvailability_DifferentSession) {
219*6777b538SAndroid Build Coastguard Worker DnsConfig config1 =
220*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
221*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
222*6777b538SAndroid Build Coastguard Worker
223*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
224*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
225*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
226*6777b538SAndroid Build Coastguard Worker
227*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
228*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
229*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session2.get(),
230*6777b538SAndroid Build Coastguard Worker true /* network_change */);
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker // Use current session to set a probe result.
233*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
234*6777b538SAndroid Build Coastguard Worker session2.get());
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
237*6777b538SAndroid Build Coastguard Worker session1->config(), SecureDnsMode::kAutomatic, session1.get());
238*6777b538SAndroid Build Coastguard Worker
239*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(doh_itr->AttemptAvailable());
240*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, context.NumAvailableDohServers(session1.get()));
241*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.GetDohServerAvailability(1u, session1.get()));
242*6777b538SAndroid Build Coastguard Worker
243*6777b538SAndroid Build Coastguard Worker // Different session for RecordServerFailure() should have no effect.
244*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.GetDohServerAvailability(1u, session2.get()));
245*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
246*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
247*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session1.get());
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(context.GetDohServerAvailability(1u, session2.get()));
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerIndexToUse)252*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerIndexToUse) {
253*6777b538SAndroid Build Coastguard Worker DnsConfig config =
254*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
255*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
258*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
259*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
260*6777b538SAndroid Build Coastguard Worker false /* network_change */);
261*6777b538SAndroid Build Coastguard Worker
262*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
263*6777b538SAndroid Build Coastguard Worker session.get());
264*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.NumAvailableDohServers(session.get()), 1u);
265*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
266*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
269*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
270*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(doh_itr->AttemptAvailable());
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerIndexToUse_NoneEligible)273*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerIndexToUse_NoneEligible) {
274*6777b538SAndroid Build Coastguard Worker DnsConfig config =
275*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
276*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
277*6777b538SAndroid Build Coastguard Worker
278*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
279*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
280*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
281*6777b538SAndroid Build Coastguard Worker false /* network_change */);
282*6777b538SAndroid Build Coastguard Worker
283*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
284*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
285*6777b538SAndroid Build Coastguard Worker
286*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(doh_itr->AttemptAvailable());
287*6777b538SAndroid Build Coastguard Worker }
288*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerIndexToUse_SecureMode)289*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerIndexToUse_SecureMode) {
290*6777b538SAndroid Build Coastguard Worker DnsConfig config =
291*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
292*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
293*6777b538SAndroid Build Coastguard Worker
294*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
295*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
296*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
297*6777b538SAndroid Build Coastguard Worker false /* network_change */);
298*6777b538SAndroid Build Coastguard Worker
299*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
300*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kSecure, session.get());
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
303*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
304*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
305*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,StartDohAutoupgradeSuccessTimer)308*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, StartDohAutoupgradeSuccessTimer) {
309*6777b538SAndroid Build Coastguard Worker DnsConfig config = CreateDnsConfig(/*num_servers=*/2, /*num_doh_servers=*/2);
310*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
313*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), /*enable_caching=*/true);
314*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
315*6777b538SAndroid Build Coastguard Worker /*network_change=*/false);
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.doh_autoupgrade_metrics_timer_is_running_for_testing());
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker // Calling with a valid session should start the timer.
320*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
321*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(context.doh_autoupgrade_metrics_timer_is_running_for_testing());
322*6777b538SAndroid Build Coastguard Worker
323*6777b538SAndroid Build Coastguard Worker // Making a second call should have no effect.
324*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
325*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(context.doh_autoupgrade_metrics_timer_is_running_for_testing());
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
328*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
329*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
330*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
331*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
332*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.doh_autoupgrade_metrics_timer_is_running_for_testing());
333*6777b538SAndroid Build Coastguard Worker }
334*6777b538SAndroid Build Coastguard Worker
335*6777b538SAndroid Build Coastguard Worker class TestDnsObserver : public NetworkChangeNotifier::DNSObserver {
336*6777b538SAndroid Build Coastguard Worker public:
OnDNSChanged()337*6777b538SAndroid Build Coastguard Worker void OnDNSChanged() override { ++dns_changed_calls_; }
338*6777b538SAndroid Build Coastguard Worker
dns_changed_calls() const339*6777b538SAndroid Build Coastguard Worker int dns_changed_calls() const { return dns_changed_calls_; }
340*6777b538SAndroid Build Coastguard Worker
341*6777b538SAndroid Build Coastguard Worker private:
342*6777b538SAndroid Build Coastguard Worker int dns_changed_calls_ = 0;
343*6777b538SAndroid Build Coastguard Worker };
344*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohServerAvailabilityNotification)345*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohServerAvailabilityNotification) {
346*6777b538SAndroid Build Coastguard Worker TestDnsObserver config_observer;
347*6777b538SAndroid Build Coastguard Worker NetworkChangeNotifier::AddDNSObserver(&config_observer);
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker DnsConfig config =
350*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
351*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Worker auto request_context = CreateTestURLRequestContextBuilder()->Build();
354*6777b538SAndroid Build Coastguard Worker ResolveContext context(request_context.get(), true /* enable_caching */);
355*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
356*6777b538SAndroid Build Coastguard Worker false /* network_change */);
357*6777b538SAndroid Build Coastguard Worker
358*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle(); // Notifications are async.
359*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, config_observer.dns_changed_calls());
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker // Expect notification on first available DoH server.
362*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(0u, context.NumAvailableDohServers(session.get()));
363*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
364*6777b538SAndroid Build Coastguard Worker session.get());
365*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1u, context.NumAvailableDohServers(session.get()));
366*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle(); // Notifications are async.
367*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, config_observer.dns_changed_calls());
368*6777b538SAndroid Build Coastguard Worker
369*6777b538SAndroid Build Coastguard Worker // No notifications as additional servers are available or unavailable.
370*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
371*6777b538SAndroid Build Coastguard Worker session.get());
372*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle(); // Notifications are async.
373*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, config_observer.dns_changed_calls());
374*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
375*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(2u, context.NumAvailableDohServers(session.get()));
376*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(0u /* server_index */, true /* is_doh_server */,
377*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
378*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle(); // Notifications are async.
379*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, config_observer.dns_changed_calls());
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1u, context.NumAvailableDohServers(session.get()));
382*6777b538SAndroid Build Coastguard Worker
383*6777b538SAndroid Build Coastguard Worker // Expect notification on last server unavailable.
384*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
385*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1u, context.NumAvailableDohServers(session.get()));
386*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle(); // Notifications are async.
387*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, config_observer.dns_changed_calls());
388*6777b538SAndroid Build Coastguard Worker
389*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
390*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
391*6777b538SAndroid Build Coastguard Worker }
392*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(0u, context.NumAvailableDohServers(session.get()));
393*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle(); // Notifications are async.
394*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2, config_observer.dns_changed_calls());
395*6777b538SAndroid Build Coastguard Worker
396*6777b538SAndroid Build Coastguard Worker NetworkChangeNotifier::RemoveDNSObserver(&config_observer);
397*6777b538SAndroid Build Coastguard Worker }
398*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,HostCacheInvalidation)399*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, HostCacheInvalidation) {
400*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
401*6777b538SAndroid Build Coastguard Worker true /* enable_caching */);
402*6777b538SAndroid Build Coastguard Worker
403*6777b538SAndroid Build Coastguard Worker base::TimeTicks now;
404*6777b538SAndroid Build Coastguard Worker HostCache::Key key("example.com", DnsQueryType::UNSPECIFIED, 0,
405*6777b538SAndroid Build Coastguard Worker HostResolverSource::ANY, NetworkAnonymizationKey());
406*6777b538SAndroid Build Coastguard Worker context.host_cache()->Set(
407*6777b538SAndroid Build Coastguard Worker key,
408*6777b538SAndroid Build Coastguard Worker HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
409*6777b538SAndroid Build Coastguard Worker HostCache::Entry::SOURCE_UNKNOWN),
410*6777b538SAndroid Build Coastguard Worker now, base::Seconds(10));
411*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.host_cache()->Lookup(key, now));
412*6777b538SAndroid Build Coastguard Worker
413*6777b538SAndroid Build Coastguard Worker DnsConfig config =
414*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
415*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
416*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
417*6777b538SAndroid Build Coastguard Worker false /* network_change */);
418*6777b538SAndroid Build Coastguard Worker
419*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.host_cache()->Lookup(key, now));
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker // Re-add to the host cache and now add some DoH server status.
422*6777b538SAndroid Build Coastguard Worker context.host_cache()->Set(
423*6777b538SAndroid Build Coastguard Worker key,
424*6777b538SAndroid Build Coastguard Worker HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
425*6777b538SAndroid Build Coastguard Worker HostCache::Entry::SOURCE_UNKNOWN),
426*6777b538SAndroid Build Coastguard Worker now, base::Seconds(10));
427*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
428*6777b538SAndroid Build Coastguard Worker session.get());
429*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.host_cache()->Lookup(key, now));
430*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.GetDohServerAvailability(0u, session.get()));
431*6777b538SAndroid Build Coastguard Worker
432*6777b538SAndroid Build Coastguard Worker // Invalidate again.
433*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
434*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
435*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
436*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session2.get(),
437*6777b538SAndroid Build Coastguard Worker true /* network_change */);
438*6777b538SAndroid Build Coastguard Worker
439*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.host_cache()->Lookup(key, now));
440*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.GetDohServerAvailability(0u, session.get()));
441*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.GetDohServerAvailability(0u, session2.get()));
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,HostCacheInvalidation_SameSession)444*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, HostCacheInvalidation_SameSession) {
445*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
446*6777b538SAndroid Build Coastguard Worker true /* enable_caching */);
447*6777b538SAndroid Build Coastguard Worker DnsConfig config =
448*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
449*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
450*6777b538SAndroid Build Coastguard Worker
451*6777b538SAndroid Build Coastguard Worker // Initial invalidation just to set the session.
452*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
453*6777b538SAndroid Build Coastguard Worker false /* network_change */);
454*6777b538SAndroid Build Coastguard Worker
455*6777b538SAndroid Build Coastguard Worker // Add to the host cache and add some DoH server status.
456*6777b538SAndroid Build Coastguard Worker base::TimeTicks now;
457*6777b538SAndroid Build Coastguard Worker HostCache::Key key("example.com", DnsQueryType::UNSPECIFIED, 0,
458*6777b538SAndroid Build Coastguard Worker HostResolverSource::ANY, NetworkAnonymizationKey());
459*6777b538SAndroid Build Coastguard Worker context.host_cache()->Set(
460*6777b538SAndroid Build Coastguard Worker key,
461*6777b538SAndroid Build Coastguard Worker HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{"example.com"},
462*6777b538SAndroid Build Coastguard Worker HostCache::Entry::SOURCE_UNKNOWN),
463*6777b538SAndroid Build Coastguard Worker now, base::Seconds(10));
464*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
465*6777b538SAndroid Build Coastguard Worker session.get());
466*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.host_cache()->Lookup(key, now));
467*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(context.GetDohServerAvailability(0u, session.get()));
468*6777b538SAndroid Build Coastguard Worker
469*6777b538SAndroid Build Coastguard Worker // Invalidate again with the same session.
470*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
471*6777b538SAndroid Build Coastguard Worker false /* network_change */);
472*6777b538SAndroid Build Coastguard Worker
473*6777b538SAndroid Build Coastguard Worker // Expect host cache to be invalidated but not the per-session data.
474*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(context.host_cache()->Lookup(key, now));
475*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(context.GetDohServerAvailability(0u, session.get()));
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,Failures_Consecutive)478*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, Failures_Consecutive) {
479*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
480*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
481*6777b538SAndroid Build Coastguard Worker DnsConfig config =
482*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
483*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
484*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
485*6777b538SAndroid Build Coastguard Worker false /* network_change */);
486*6777b538SAndroid Build Coastguard Worker
487*6777b538SAndroid Build Coastguard Worker // Expect server preference to change after |config.attempts| failures.
488*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < config.attempts; i++) {
489*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
490*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
491*6777b538SAndroid Build Coastguard Worker
492*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
493*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
494*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
495*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
496*6777b538SAndroid Build Coastguard Worker
497*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */,
498*6777b538SAndroid Build Coastguard Worker false /* is_doh_server */, ERR_FAILED,
499*6777b538SAndroid Build Coastguard Worker session.get());
500*6777b538SAndroid Build Coastguard Worker }
501*6777b538SAndroid Build Coastguard Worker
502*6777b538SAndroid Build Coastguard Worker {
503*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
504*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
505*6777b538SAndroid Build Coastguard Worker
506*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
507*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
508*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
509*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
510*6777b538SAndroid Build Coastguard Worker }
511*6777b538SAndroid Build Coastguard Worker
512*6777b538SAndroid Build Coastguard Worker // Expect failures to be reset on successful request.
513*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, false /* is_doh_server */,
514*6777b538SAndroid Build Coastguard Worker session.get());
515*6777b538SAndroid Build Coastguard Worker {
516*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
517*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
518*6777b538SAndroid Build Coastguard Worker
519*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
520*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
521*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
522*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
523*6777b538SAndroid Build Coastguard Worker }
524*6777b538SAndroid Build Coastguard Worker }
525*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,Failures_NonConsecutive)526*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, Failures_NonConsecutive) {
527*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
528*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
529*6777b538SAndroid Build Coastguard Worker DnsConfig config =
530*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
531*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
532*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
533*6777b538SAndroid Build Coastguard Worker false /* network_change */);
534*6777b538SAndroid Build Coastguard Worker
535*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < config.attempts - 1; i++) {
536*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
537*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
538*6777b538SAndroid Build Coastguard Worker
539*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
540*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
541*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
542*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
543*6777b538SAndroid Build Coastguard Worker
544*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */,
545*6777b538SAndroid Build Coastguard Worker false /* is_doh_server */, ERR_FAILED,
546*6777b538SAndroid Build Coastguard Worker session.get());
547*6777b538SAndroid Build Coastguard Worker }
548*6777b538SAndroid Build Coastguard Worker
549*6777b538SAndroid Build Coastguard Worker {
550*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
551*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
552*6777b538SAndroid Build Coastguard Worker
553*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
554*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
555*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
556*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
557*6777b538SAndroid Build Coastguard Worker }
558*6777b538SAndroid Build Coastguard Worker
559*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, false /* is_doh_server */,
560*6777b538SAndroid Build Coastguard Worker session.get());
561*6777b538SAndroid Build Coastguard Worker {
562*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
563*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
564*6777b538SAndroid Build Coastguard Worker
565*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
566*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
567*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
568*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
569*6777b538SAndroid Build Coastguard Worker }
570*6777b538SAndroid Build Coastguard Worker
571*6777b538SAndroid Build Coastguard Worker // Expect server stay preferred through non-consecutive failures.
572*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, false /* is_doh_server */,
573*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
574*6777b538SAndroid Build Coastguard Worker {
575*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
576*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
577*6777b538SAndroid Build Coastguard Worker
578*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
579*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
580*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
581*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
582*6777b538SAndroid Build Coastguard Worker }
583*6777b538SAndroid Build Coastguard Worker }
584*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,Failures_NoSession)585*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, Failures_NoSession) {
586*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
587*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
588*6777b538SAndroid Build Coastguard Worker DnsConfig config =
589*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
590*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
591*6777b538SAndroid Build Coastguard Worker
592*6777b538SAndroid Build Coastguard Worker // No expected change from recording failures.
593*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < config.attempts; i++) {
594*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
595*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
596*6777b538SAndroid Build Coastguard Worker
597*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(classic_itr->AttemptAvailable());
598*6777b538SAndroid Build Coastguard Worker
599*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */,
600*6777b538SAndroid Build Coastguard Worker false /* is_doh_server */, ERR_FAILED,
601*6777b538SAndroid Build Coastguard Worker session.get());
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
604*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
605*6777b538SAndroid Build Coastguard Worker
606*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(classic_itr->AttemptAvailable());
607*6777b538SAndroid Build Coastguard Worker }
608*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,Failures_DifferentSession)609*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, Failures_DifferentSession) {
610*6777b538SAndroid Build Coastguard Worker DnsConfig config1 =
611*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
612*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
613*6777b538SAndroid Build Coastguard Worker
614*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
615*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
616*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
617*6777b538SAndroid Build Coastguard Worker
618*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
619*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
620*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session2.get(),
621*6777b538SAndroid Build Coastguard Worker true /* network_change */);
622*6777b538SAndroid Build Coastguard Worker
623*6777b538SAndroid Build Coastguard Worker // No change from recording failures to wrong session.
624*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < config1.attempts; i++) {
625*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
626*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session2->config(), session2.get());
627*6777b538SAndroid Build Coastguard Worker
628*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
629*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
630*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
631*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
632*6777b538SAndroid Build Coastguard Worker
633*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */,
634*6777b538SAndroid Build Coastguard Worker false /* is_doh_server */, ERR_FAILED,
635*6777b538SAndroid Build Coastguard Worker session1.get());
636*6777b538SAndroid Build Coastguard Worker }
637*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
638*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session2->config(), session2.get());
639*6777b538SAndroid Build Coastguard Worker
640*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
641*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
642*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
643*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
644*6777b538SAndroid Build Coastguard Worker }
645*6777b538SAndroid Build Coastguard Worker
646*6777b538SAndroid Build Coastguard Worker // Test 2 of 3 servers failing.
TEST_F(ResolveContextTest,TwoFailures)647*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, TwoFailures) {
648*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
649*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
650*6777b538SAndroid Build Coastguard Worker DnsConfig config =
651*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(3 /* num_servers */, 2 /* num_doh_servers */);
652*6777b538SAndroid Build Coastguard Worker config.attempts = 1;
653*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
654*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
655*6777b538SAndroid Build Coastguard Worker false /* network_change */);
656*6777b538SAndroid Build Coastguard Worker
657*6777b538SAndroid Build Coastguard Worker // Expect server preference to change after |config.attempts| failures.
658*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < config.attempts; i++) {
659*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
660*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
661*6777b538SAndroid Build Coastguard Worker
662*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
663*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
664*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
665*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
666*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
667*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 2u);
668*6777b538SAndroid Build Coastguard Worker
669*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(0u /* server_index */,
670*6777b538SAndroid Build Coastguard Worker false /* is_doh_server */, ERR_FAILED,
671*6777b538SAndroid Build Coastguard Worker session.get());
672*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */,
673*6777b538SAndroid Build Coastguard Worker false /* is_doh_server */, ERR_FAILED,
674*6777b538SAndroid Build Coastguard Worker session.get());
675*6777b538SAndroid Build Coastguard Worker }
676*6777b538SAndroid Build Coastguard Worker {
677*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
678*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
679*6777b538SAndroid Build Coastguard Worker
680*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
681*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 2u);
682*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
683*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
684*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
685*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
686*6777b538SAndroid Build Coastguard Worker }
687*6777b538SAndroid Build Coastguard Worker
688*6777b538SAndroid Build Coastguard Worker // Expect failures to be reset on successful request.
689*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(0u /* server_index */, false /* is_doh_server */,
690*6777b538SAndroid Build Coastguard Worker session.get());
691*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, false /* is_doh_server */,
692*6777b538SAndroid Build Coastguard Worker session.get());
693*6777b538SAndroid Build Coastguard Worker {
694*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> classic_itr =
695*6777b538SAndroid Build Coastguard Worker context.GetClassicDnsIterator(session->config(), session.get());
696*6777b538SAndroid Build Coastguard Worker
697*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
698*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
699*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
700*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
701*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(classic_itr->AttemptAvailable());
702*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 2u);
703*6777b538SAndroid Build Coastguard Worker }
704*6777b538SAndroid Build Coastguard Worker }
705*6777b538SAndroid Build Coastguard Worker
706*6777b538SAndroid Build Coastguard Worker class TestDohStatusObserver : public ResolveContext::DohStatusObserver {
707*6777b538SAndroid Build Coastguard Worker public:
OnSessionChanged()708*6777b538SAndroid Build Coastguard Worker void OnSessionChanged() override { ++session_changes_; }
OnDohServerUnavailable(bool network_change)709*6777b538SAndroid Build Coastguard Worker void OnDohServerUnavailable(bool network_change) override {
710*6777b538SAndroid Build Coastguard Worker ++server_unavailable_notifications_;
711*6777b538SAndroid Build Coastguard Worker }
712*6777b538SAndroid Build Coastguard Worker
session_changes() const713*6777b538SAndroid Build Coastguard Worker int session_changes() const { return session_changes_; }
server_unavailable_notifications() const714*6777b538SAndroid Build Coastguard Worker int server_unavailable_notifications() const {
715*6777b538SAndroid Build Coastguard Worker return server_unavailable_notifications_;
716*6777b538SAndroid Build Coastguard Worker }
717*6777b538SAndroid Build Coastguard Worker
718*6777b538SAndroid Build Coastguard Worker private:
719*6777b538SAndroid Build Coastguard Worker int session_changes_ = 0;
720*6777b538SAndroid Build Coastguard Worker int server_unavailable_notifications_ = 0;
721*6777b538SAndroid Build Coastguard Worker };
722*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohFailures_Consecutive)723*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_Consecutive) {
724*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
725*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
726*6777b538SAndroid Build Coastguard Worker DnsConfig config =
727*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
728*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
729*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
730*6777b538SAndroid Build Coastguard Worker false /* network_change */);
731*6777b538SAndroid Build Coastguard Worker
732*6777b538SAndroid Build Coastguard Worker TestDohStatusObserver observer;
733*6777b538SAndroid Build Coastguard Worker context.RegisterDohStatusObserver(&observer);
734*6777b538SAndroid Build Coastguard Worker
735*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
736*6777b538SAndroid Build Coastguard Worker session.get());
737*6777b538SAndroid Build Coastguard Worker
738*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
739*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
740*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
741*6777b538SAndroid Build Coastguard Worker
742*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
743*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
744*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
745*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, observer.server_unavailable_notifications());
746*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
747*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
748*6777b538SAndroid Build Coastguard Worker }
749*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
750*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
751*6777b538SAndroid Build Coastguard Worker
752*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(doh_itr->AttemptAvailable());
753*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
754*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, observer.server_unavailable_notifications());
755*6777b538SAndroid Build Coastguard Worker
756*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
757*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
758*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
759*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
760*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
761*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
762*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
763*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
764*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
765*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
766*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
767*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
768*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kFailureWithSomePriorSuccesses,
769*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
770*6777b538SAndroid Build Coastguard Worker
771*6777b538SAndroid Build Coastguard Worker context.UnregisterDohStatusObserver(&observer);
772*6777b538SAndroid Build Coastguard Worker }
773*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohFailures_NonConsecutive)774*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_NonConsecutive) {
775*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
776*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
777*6777b538SAndroid Build Coastguard Worker DnsConfig config =
778*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
779*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
780*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
781*6777b538SAndroid Build Coastguard Worker false /* network_change */);
782*6777b538SAndroid Build Coastguard Worker
783*6777b538SAndroid Build Coastguard Worker TestDohStatusObserver observer;
784*6777b538SAndroid Build Coastguard Worker context.RegisterDohStatusObserver(&observer);
785*6777b538SAndroid Build Coastguard Worker
786*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
787*6777b538SAndroid Build Coastguard Worker session.get());
788*6777b538SAndroid Build Coastguard Worker
789*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit - 1; i++) {
790*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
791*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
792*6777b538SAndroid Build Coastguard Worker
793*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
794*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
795*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
796*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
797*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
798*6777b538SAndroid Build Coastguard Worker }
799*6777b538SAndroid Build Coastguard Worker {
800*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
801*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
802*6777b538SAndroid Build Coastguard Worker
803*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
804*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
805*6777b538SAndroid Build Coastguard Worker }
806*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
807*6777b538SAndroid Build Coastguard Worker
808*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
809*6777b538SAndroid Build Coastguard Worker session.get());
810*6777b538SAndroid Build Coastguard Worker {
811*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
812*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
813*6777b538SAndroid Build Coastguard Worker
814*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
815*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
816*6777b538SAndroid Build Coastguard Worker }
817*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
818*6777b538SAndroid Build Coastguard Worker
819*6777b538SAndroid Build Coastguard Worker // Expect a single additional failure should not make a DoH server unavailable
820*6777b538SAndroid Build Coastguard Worker // because the success resets failure tracking.
821*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
822*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
823*6777b538SAndroid Build Coastguard Worker {
824*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
825*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
826*6777b538SAndroid Build Coastguard Worker
827*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
828*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
829*6777b538SAndroid Build Coastguard Worker }
830*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
831*6777b538SAndroid Build Coastguard Worker
832*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, observer.server_unavailable_notifications());
833*6777b538SAndroid Build Coastguard Worker
834*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
835*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
836*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
837*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
838*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
839*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
840*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
841*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
842*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
843*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
844*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
845*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
846*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kSuccessWithSomePriorFailures,
847*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
848*6777b538SAndroid Build Coastguard Worker
849*6777b538SAndroid Build Coastguard Worker context.UnregisterDohStatusObserver(&observer);
850*6777b538SAndroid Build Coastguard Worker }
851*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohFailures_SuccessAfterFailures)852*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_SuccessAfterFailures) {
853*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
854*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
855*6777b538SAndroid Build Coastguard Worker DnsConfig config =
856*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
857*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
858*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
859*6777b538SAndroid Build Coastguard Worker false /* network_change */);
860*6777b538SAndroid Build Coastguard Worker
861*6777b538SAndroid Build Coastguard Worker TestDohStatusObserver observer;
862*6777b538SAndroid Build Coastguard Worker context.RegisterDohStatusObserver(&observer);
863*6777b538SAndroid Build Coastguard Worker
864*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
865*6777b538SAndroid Build Coastguard Worker session.get());
866*6777b538SAndroid Build Coastguard Worker
867*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
868*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
869*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
870*6777b538SAndroid Build Coastguard Worker }
871*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(0u, context.NumAvailableDohServers(session.get()));
872*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, observer.server_unavailable_notifications());
873*6777b538SAndroid Build Coastguard Worker
874*6777b538SAndroid Build Coastguard Worker // Expect a single success to make an unavailable DoH server available again.
875*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
876*6777b538SAndroid Build Coastguard Worker session.get());
877*6777b538SAndroid Build Coastguard Worker {
878*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
879*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
880*6777b538SAndroid Build Coastguard Worker
881*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
882*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
883*6777b538SAndroid Build Coastguard Worker }
884*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
885*6777b538SAndroid Build Coastguard Worker
886*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, observer.server_unavailable_notifications());
887*6777b538SAndroid Build Coastguard Worker
888*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
889*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
890*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
891*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
892*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
893*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
894*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
895*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
896*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
897*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
898*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
899*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
900*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kSuccessWithSomePriorFailures,
901*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
902*6777b538SAndroid Build Coastguard Worker
903*6777b538SAndroid Build Coastguard Worker context.UnregisterDohStatusObserver(&observer);
904*6777b538SAndroid Build Coastguard Worker }
905*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohFailures_NoSession)906*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_NoSession) {
907*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
908*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
909*6777b538SAndroid Build Coastguard Worker DnsConfig config =
910*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
911*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
912*6777b538SAndroid Build Coastguard Worker
913*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
914*6777b538SAndroid Build Coastguard Worker session.get());
915*6777b538SAndroid Build Coastguard Worker
916*6777b538SAndroid Build Coastguard Worker // No expected change from recording failures.
917*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
918*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
919*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
920*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
921*6777b538SAndroid Build Coastguard Worker }
922*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
923*6777b538SAndroid Build Coastguard Worker }
924*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohFailures_DifferentSession)925*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_DifferentSession) {
926*6777b538SAndroid Build Coastguard Worker DnsConfig config1 =
927*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
928*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
929*6777b538SAndroid Build Coastguard Worker
930*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
931*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
932*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
933*6777b538SAndroid Build Coastguard Worker
934*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
935*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
936*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session2.get(),
937*6777b538SAndroid Build Coastguard Worker true /* network_change */);
938*6777b538SAndroid Build Coastguard Worker
939*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
940*6777b538SAndroid Build Coastguard Worker session2.get());
941*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1u, context.NumAvailableDohServers(session2.get()));
942*6777b538SAndroid Build Coastguard Worker
943*6777b538SAndroid Build Coastguard Worker // No change from recording failures to wrong session.
944*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
945*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session2.get()));
946*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
947*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session1.get());
948*6777b538SAndroid Build Coastguard Worker }
949*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, context.NumAvailableDohServers(session2.get()));
950*6777b538SAndroid Build Coastguard Worker }
951*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,DohFailures_NeverSuccessful)952*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_NeverSuccessful) {
953*6777b538SAndroid Build Coastguard Worker DnsConfig config = CreateDnsConfig(/*num_servers=*/2, /*num_doh_servers=*/2);
954*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
955*6777b538SAndroid Build Coastguard Worker ResolveContext context(/*url_request_context=*/nullptr,
956*6777b538SAndroid Build Coastguard Worker /*enable_caching=*/false);
957*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
958*6777b538SAndroid Build Coastguard Worker /*network_change=*/false);
959*6777b538SAndroid Build Coastguard Worker
960*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(/*server_index=*/0u, /*is_doh_server=*/true,
961*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
962*6777b538SAndroid Build Coastguard Worker
963*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
964*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
965*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
966*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
967*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
968*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
969*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
970*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
971*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
972*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
973*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
974*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
975*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kFailureWithNoPriorSuccesses,
976*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
977*6777b538SAndroid Build Coastguard Worker }
978*6777b538SAndroid Build Coastguard Worker
979*6777b538SAndroid Build Coastguard Worker // Test that metrics are recorded properly when auto-upgrade is never successful
980*6777b538SAndroid Build Coastguard Worker // for a provider that is in the list of providers where we can auto-upgrade
981*6777b538SAndroid Build Coastguard Worker // insecure DNS queries to secure DNS queries.
TEST_F(ResolveContextTest,DohFailures_NeverSuccessfulKnownProviderConfig)982*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, DohFailures_NeverSuccessfulKnownProviderConfig) {
983*6777b538SAndroid Build Coastguard Worker ResolveContext context(/*url_request_context=*/nullptr,
984*6777b538SAndroid Build Coastguard Worker /*enable_caching=*/false);
985*6777b538SAndroid Build Coastguard Worker DnsConfig config = CreateDnsConfigWithKnownDohProviderConfig();
986*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
987*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
988*6777b538SAndroid Build Coastguard Worker /*network_change=*/false);
989*6777b538SAndroid Build Coastguard Worker
990*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(/*server_index=*/0u, /*is_doh_server=*/true,
991*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
992*6777b538SAndroid Build Coastguard Worker
993*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
994*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
995*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
996*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
997*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
998*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
999*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
1000*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
1001*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Google.Status",
1002*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
1003*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
1004*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Google.Status",
1005*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kFailureWithNoPriorSuccesses,
1006*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
1007*6777b538SAndroid Build Coastguard Worker }
1008*6777b538SAndroid Build Coastguard Worker
1009*6777b538SAndroid Build Coastguard Worker // Test 2 of 3 DoH servers failing.
TEST_F(ResolveContextTest,TwoDohFailures)1010*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, TwoDohFailures) {
1011*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1012*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1013*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1014*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 3 /* num_doh_servers */);
1015*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1016*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1017*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1018*6777b538SAndroid Build Coastguard Worker
1019*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
1020*6777b538SAndroid Build Coastguard Worker session.get());
1021*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
1022*6777b538SAndroid Build Coastguard Worker session.get());
1023*6777b538SAndroid Build Coastguard Worker context.RecordServerSuccess(2u /* server_index */, true /* is_doh_server */,
1024*6777b538SAndroid Build Coastguard Worker session.get());
1025*6777b538SAndroid Build Coastguard Worker
1026*6777b538SAndroid Build Coastguard Worker // Expect server preference to change after |config.attempts| failures.
1027*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < config.attempts; i++) {
1028*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
1029*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
1030*6777b538SAndroid Build Coastguard Worker
1031*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
1032*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
1033*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
1034*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
1035*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
1036*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
1037*6777b538SAndroid Build Coastguard Worker
1038*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(0u /* server_index */, true /* is_doh_server */,
1039*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
1040*6777b538SAndroid Build Coastguard Worker context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
1041*6777b538SAndroid Build Coastguard Worker ERR_FAILED, session.get());
1042*6777b538SAndroid Build Coastguard Worker }
1043*6777b538SAndroid Build Coastguard Worker
1044*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
1045*6777b538SAndroid Build Coastguard Worker session->config(), SecureDnsMode::kAutomatic, session.get());
1046*6777b538SAndroid Build Coastguard Worker
1047*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(doh_itr->AttemptAvailable());
1048*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
1049*6777b538SAndroid Build Coastguard Worker
1050*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1051*6777b538SAndroid Build Coastguard Worker context.StartDohAutoupgradeSuccessTimer(session.get());
1052*6777b538SAndroid Build Coastguard Worker // Fast-forward by enough time for the timer to trigger. Add one millisecond
1053*6777b538SAndroid Build Coastguard Worker // just to make it clear that afterwards the timeout should definitely have
1054*6777b538SAndroid Build Coastguard Worker // occurred (although this may not be strictly necessary).
1055*6777b538SAndroid Build Coastguard Worker FastForwardBy(ResolveContext::kDohAutoupgradeSuccessMetricTimeout +
1056*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1));
1057*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectTotalCount(
1058*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
1059*6777b538SAndroid Build Coastguard Worker /*expected_count=*/3);
1060*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
1061*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
1062*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kSuccessWithSomePriorFailures,
1063*6777b538SAndroid Build Coastguard Worker /*expected_count=*/2);
1064*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectBucketCount(
1065*6777b538SAndroid Build Coastguard Worker "Net.DNS.ResolveContext.DohAutoupgrade.Other.Status",
1066*6777b538SAndroid Build Coastguard Worker DohServerAutoupgradeStatus::kSuccessWithNoPriorFailures,
1067*6777b538SAndroid Build Coastguard Worker /*expected_count=*/1);
1068*6777b538SAndroid Build Coastguard Worker }
1069*6777b538SAndroid Build Coastguard Worker
1070*6777b538SAndroid Build Coastguard Worker // Expect default calculated fallback period to be within 10ms of
1071*6777b538SAndroid Build Coastguard Worker // |DnsConfig::fallback_period|.
TEST_F(ResolveContextTest,FallbackPeriod_Default)1072*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, FallbackPeriod_Default) {
1073*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1074*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1075*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1076*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1077*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1078*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1079*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1080*6777b538SAndroid Build Coastguard Worker
1081*6777b538SAndroid Build Coastguard Worker base::TimeDelta delta =
1082*6777b538SAndroid Build Coastguard Worker context.NextClassicFallbackPeriod(0 /* server_index */, 0 /* attempt */,
1083*6777b538SAndroid Build Coastguard Worker session.get()) -
1084*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1085*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1086*6777b538SAndroid Build Coastguard Worker delta =
1087*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(0 /* doh_server_index */, session.get()) -
1088*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1089*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1090*6777b538SAndroid Build Coastguard Worker }
1091*6777b538SAndroid Build Coastguard Worker
1092*6777b538SAndroid Build Coastguard Worker // Expect short calculated fallback period to be within 10ms of
1093*6777b538SAndroid Build Coastguard Worker // |DnsConfig::fallback_period|.
TEST_F(ResolveContextTest,FallbackPeriod_ShortConfigured)1094*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, FallbackPeriod_ShortConfigured) {
1095*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1096*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1097*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1098*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1099*6777b538SAndroid Build Coastguard Worker config.fallback_period = base::Milliseconds(15);
1100*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1101*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1102*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1103*6777b538SAndroid Build Coastguard Worker
1104*6777b538SAndroid Build Coastguard Worker base::TimeDelta delta =
1105*6777b538SAndroid Build Coastguard Worker context.NextClassicFallbackPeriod(0 /* server_index */, 0 /* attempt */,
1106*6777b538SAndroid Build Coastguard Worker session.get()) -
1107*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1108*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1109*6777b538SAndroid Build Coastguard Worker delta =
1110*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(0 /* doh_server_index */, session.get()) -
1111*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1112*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1113*6777b538SAndroid Build Coastguard Worker }
1114*6777b538SAndroid Build Coastguard Worker
1115*6777b538SAndroid Build Coastguard Worker // Expect long calculated fallback period to be equal to
1116*6777b538SAndroid Build Coastguard Worker // |DnsConfig::fallback_period|. (Default max fallback period is 5 seconds, so
1117*6777b538SAndroid Build Coastguard Worker // NextClassicFallbackPeriod() should return exactly the config fallback
1118*6777b538SAndroid Build Coastguard Worker // period.)
TEST_F(ResolveContextTest,FallbackPeriod_LongConfigured)1119*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, FallbackPeriod_LongConfigured) {
1120*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1121*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1122*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1123*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1124*6777b538SAndroid Build Coastguard Worker config.fallback_period = base::Seconds(15);
1125*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1126*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1127*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1128*6777b538SAndroid Build Coastguard Worker
1129*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.NextClassicFallbackPeriod(0 /* server_index */,
1130*6777b538SAndroid Build Coastguard Worker 0 /* attempt */, session.get()),
1131*6777b538SAndroid Build Coastguard Worker config.fallback_period);
1132*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1133*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(0 /* doh_server_index */, session.get()),
1134*6777b538SAndroid Build Coastguard Worker config.fallback_period);
1135*6777b538SAndroid Build Coastguard Worker }
1136*6777b538SAndroid Build Coastguard Worker
1137*6777b538SAndroid Build Coastguard Worker // Expect fallback periods to increase on recording long round-trip times.
TEST_F(ResolveContextTest,FallbackPeriod_LongRtt)1138*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, FallbackPeriod_LongRtt) {
1139*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1140*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1141*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1142*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1143*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1144*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1145*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1146*6777b538SAndroid Build Coastguard Worker
1147*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1148*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
1149*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1150*6777b538SAndroid Build Coastguard Worker context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
1151*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1152*6777b538SAndroid Build Coastguard Worker }
1153*6777b538SAndroid Build Coastguard Worker
1154*6777b538SAndroid Build Coastguard Worker // Expect servers with high recorded RTT to have increased fallback periods
1155*6777b538SAndroid Build Coastguard Worker // (>10ms).
1156*6777b538SAndroid Build Coastguard Worker base::TimeDelta delta =
1157*6777b538SAndroid Build Coastguard Worker context.NextClassicFallbackPeriod(0u /* server_index */, 0 /* attempt */,
1158*6777b538SAndroid Build Coastguard Worker session.get()) -
1159*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1160*6777b538SAndroid Build Coastguard Worker EXPECT_GT(delta, base::Milliseconds(10));
1161*6777b538SAndroid Build Coastguard Worker delta =
1162*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(1u, session.get()) - config.fallback_period;
1163*6777b538SAndroid Build Coastguard Worker EXPECT_GT(delta, base::Milliseconds(10));
1164*6777b538SAndroid Build Coastguard Worker
1165*6777b538SAndroid Build Coastguard Worker // Servers without recorded RTT expected to remain the same (<=10ms).
1166*6777b538SAndroid Build Coastguard Worker delta = context.NextClassicFallbackPeriod(1u /* server_index */,
1167*6777b538SAndroid Build Coastguard Worker 0 /* attempt */, session.get()) -
1168*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1169*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1170*6777b538SAndroid Build Coastguard Worker delta =
1171*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(0u /* doh_server_index */, session.get()) -
1172*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1173*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1174*6777b538SAndroid Build Coastguard Worker }
1175*6777b538SAndroid Build Coastguard Worker
1176*6777b538SAndroid Build Coastguard Worker // Expect recording round-trip times to have no affect on fallback period
1177*6777b538SAndroid Build Coastguard Worker // without a current session.
TEST_F(ResolveContextTest,FallbackPeriod_NoSession)1178*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, FallbackPeriod_NoSession) {
1179*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1180*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1181*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1182*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1183*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1184*6777b538SAndroid Build Coastguard Worker
1185*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1186*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
1187*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1188*6777b538SAndroid Build Coastguard Worker context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
1189*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1190*6777b538SAndroid Build Coastguard Worker }
1191*6777b538SAndroid Build Coastguard Worker
1192*6777b538SAndroid Build Coastguard Worker base::TimeDelta delta =
1193*6777b538SAndroid Build Coastguard Worker context.NextClassicFallbackPeriod(0u /* server_index */, 0 /* attempt */,
1194*6777b538SAndroid Build Coastguard Worker session.get()) -
1195*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1196*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1197*6777b538SAndroid Build Coastguard Worker delta =
1198*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(1u /* doh_server_index */, session.get()) -
1199*6777b538SAndroid Build Coastguard Worker config.fallback_period;
1200*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1201*6777b538SAndroid Build Coastguard Worker }
1202*6777b538SAndroid Build Coastguard Worker
1203*6777b538SAndroid Build Coastguard Worker // Expect recording round-trip times to have no affect on fallback periods
1204*6777b538SAndroid Build Coastguard Worker // without a current session.
TEST_F(ResolveContextTest,FallbackPeriod_DifferentSession)1205*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, FallbackPeriod_DifferentSession) {
1206*6777b538SAndroid Build Coastguard Worker DnsConfig config1 =
1207*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
1208*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
1209*6777b538SAndroid Build Coastguard Worker
1210*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
1211*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1212*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
1213*6777b538SAndroid Build Coastguard Worker
1214*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1215*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1216*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session2.get(),
1217*6777b538SAndroid Build Coastguard Worker true /* network_change */);
1218*6777b538SAndroid Build Coastguard Worker
1219*6777b538SAndroid Build Coastguard Worker // Record RTT's to increase fallback periods for current session.
1220*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1221*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
1222*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session2.get());
1223*6777b538SAndroid Build Coastguard Worker context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
1224*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session2.get());
1225*6777b538SAndroid Build Coastguard Worker }
1226*6777b538SAndroid Build Coastguard Worker
1227*6777b538SAndroid Build Coastguard Worker // Expect normal short fallback periods for other session.
1228*6777b538SAndroid Build Coastguard Worker base::TimeDelta delta =
1229*6777b538SAndroid Build Coastguard Worker context.NextClassicFallbackPeriod(0u /* server_index */, 0 /* attempt */,
1230*6777b538SAndroid Build Coastguard Worker session1.get()) -
1231*6777b538SAndroid Build Coastguard Worker config1.fallback_period;
1232*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1233*6777b538SAndroid Build Coastguard Worker delta =
1234*6777b538SAndroid Build Coastguard Worker context.NextDohFallbackPeriod(0u /* doh_server_index */, session1.get()) -
1235*6777b538SAndroid Build Coastguard Worker config1.fallback_period;
1236*6777b538SAndroid Build Coastguard Worker EXPECT_LE(delta, base::Milliseconds(10));
1237*6777b538SAndroid Build Coastguard Worker
1238*6777b538SAndroid Build Coastguard Worker // Recording RTT's for other session should have no effect on current session
1239*6777b538SAndroid Build Coastguard Worker // fallback periods.
1240*6777b538SAndroid Build Coastguard Worker base::TimeDelta fallback_period = context.NextClassicFallbackPeriod(
1241*6777b538SAndroid Build Coastguard Worker 0u /* server_index */, 0 /* attempt */, session2.get());
1242*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1243*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
1244*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1), OK, session1.get());
1245*6777b538SAndroid Build Coastguard Worker }
1246*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(fallback_period,
1247*6777b538SAndroid Build Coastguard Worker context.NextClassicFallbackPeriod(0u /* server_index */,
1248*6777b538SAndroid Build Coastguard Worker 0 /* attempt */, session2.get()));
1249*6777b538SAndroid Build Coastguard Worker }
1250*6777b538SAndroid Build Coastguard Worker
1251*6777b538SAndroid Build Coastguard Worker // Expect minimum timeout will be used when fallback period is small.
TEST_F(ResolveContextTest,SecureTransactionTimeout_SmallFallbackPeriod)1252*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SecureTransactionTimeout_SmallFallbackPeriod) {
1253*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1254*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1255*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1256*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(0 /* num_servers */, 1 /* num_doh_servers */);
1257*6777b538SAndroid Build Coastguard Worker config.fallback_period = base::TimeDelta();
1258*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1259*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1260*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1261*6777b538SAndroid Build Coastguard Worker
1262*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1263*6777b538SAndroid Build Coastguard Worker context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
1264*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1265*6777b538SAndroid Build Coastguard Worker }
1266*6777b538SAndroid Build Coastguard Worker
1267*6777b538SAndroid Build Coastguard Worker // Expect multiplier on fallback period to be used when larger than minimum
1268*6777b538SAndroid Build Coastguard Worker // timeout.
TEST_F(ResolveContextTest,SecureTransactionTimeout_LongFallbackPeriod)1269*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SecureTransactionTimeout_LongFallbackPeriod) {
1270*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1271*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1272*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kFallbackPeriod = base::Minutes(5);
1273*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1274*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(0 /* num_servers */, 1 /* num_doh_servers */);
1275*6777b538SAndroid Build Coastguard Worker config.fallback_period = kFallbackPeriod;
1276*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1277*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1278*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1279*6777b538SAndroid Build Coastguard Worker
1280*6777b538SAndroid Build Coastguard Worker base::TimeDelta expected =
1281*6777b538SAndroid Build Coastguard Worker kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
1282*6777b538SAndroid Build Coastguard Worker ASSERT_GT(expected, features::kDnsMinTransactionTimeout.Get());
1283*6777b538SAndroid Build Coastguard Worker
1284*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1285*6777b538SAndroid Build Coastguard Worker context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
1286*6777b538SAndroid Build Coastguard Worker expected);
1287*6777b538SAndroid Build Coastguard Worker }
1288*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,SecureTransactionTimeout_LongRtt)1289*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SecureTransactionTimeout_LongRtt) {
1290*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1291*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1292*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1293*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(0 /* num_servers */, 2 /* num_doh_servers */);
1294*6777b538SAndroid Build Coastguard Worker config.fallback_period = base::TimeDelta();
1295*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1296*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1297*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1298*6777b538SAndroid Build Coastguard Worker
1299*6777b538SAndroid Build Coastguard Worker // Record long RTTs for only 1 server.
1300*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1301*6777b538SAndroid Build Coastguard Worker context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
1302*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1303*6777b538SAndroid Build Coastguard Worker }
1304*6777b538SAndroid Build Coastguard Worker
1305*6777b538SAndroid Build Coastguard Worker // No expected change from recording RTT to single server because lowest
1306*6777b538SAndroid Build Coastguard Worker // fallback period is used.
1307*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1308*6777b538SAndroid Build Coastguard Worker context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
1309*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1310*6777b538SAndroid Build Coastguard Worker
1311*6777b538SAndroid Build Coastguard Worker // Record long RTTs for remaining server.
1312*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1313*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0u /* server_index */, true /* is_doh_server */,
1314*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1315*6777b538SAndroid Build Coastguard Worker }
1316*6777b538SAndroid Build Coastguard Worker
1317*6777b538SAndroid Build Coastguard Worker // Expect longer timeouts.
1318*6777b538SAndroid Build Coastguard Worker EXPECT_GT(
1319*6777b538SAndroid Build Coastguard Worker context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
1320*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1321*6777b538SAndroid Build Coastguard Worker }
1322*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,SecureTransactionTimeout_DifferentSession)1323*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SecureTransactionTimeout_DifferentSession) {
1324*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kFallbackPeriod = base::Minutes(5);
1325*6777b538SAndroid Build Coastguard Worker DnsConfig config1 =
1326*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(0 /* num_servers */, 1 /* num_doh_servers */);
1327*6777b538SAndroid Build Coastguard Worker config1.fallback_period = kFallbackPeriod;
1328*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
1329*6777b538SAndroid Build Coastguard Worker
1330*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
1331*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1332*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
1333*6777b538SAndroid Build Coastguard Worker
1334*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1335*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1336*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session1.get(),
1337*6777b538SAndroid Build Coastguard Worker true /* network_change */);
1338*6777b538SAndroid Build Coastguard Worker
1339*6777b538SAndroid Build Coastguard Worker // Confirm that if session data were used, the timeout would be higher than
1340*6777b538SAndroid Build Coastguard Worker // the min.
1341*6777b538SAndroid Build Coastguard Worker base::TimeDelta multiplier_expected =
1342*6777b538SAndroid Build Coastguard Worker kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
1343*6777b538SAndroid Build Coastguard Worker ASSERT_GT(multiplier_expected, features::kDnsMinTransactionTimeout.Get());
1344*6777b538SAndroid Build Coastguard Worker
1345*6777b538SAndroid Build Coastguard Worker // Expect timeout always minimum with wrong session.
1346*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1347*6777b538SAndroid Build Coastguard Worker context.SecureTransactionTimeout(SecureDnsMode::kSecure, session2.get()),
1348*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1349*6777b538SAndroid Build Coastguard Worker }
1350*6777b538SAndroid Build Coastguard Worker
1351*6777b538SAndroid Build Coastguard Worker // Expect minimum timeout will be used when fallback period is small.
TEST_F(ResolveContextTest,ClassicTransactionTimeout_SmallFallbackPeriod)1352*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, ClassicTransactionTimeout_SmallFallbackPeriod) {
1353*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1354*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1355*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1356*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 0 /* num_doh_servers */);
1357*6777b538SAndroid Build Coastguard Worker config.fallback_period = base::TimeDelta();
1358*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1359*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1360*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1361*6777b538SAndroid Build Coastguard Worker
1362*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.ClassicTransactionTimeout(session.get()),
1363*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1364*6777b538SAndroid Build Coastguard Worker }
1365*6777b538SAndroid Build Coastguard Worker
1366*6777b538SAndroid Build Coastguard Worker // Expect multiplier on fallback period to be used when larger than minimum
1367*6777b538SAndroid Build Coastguard Worker // timeout.
TEST_F(ResolveContextTest,ClassicTransactionTimeout_LongFallbackPeriod)1368*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, ClassicTransactionTimeout_LongFallbackPeriod) {
1369*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1370*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1371*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kFallbackPeriod = base::Minutes(5);
1372*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1373*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 0 /* num_doh_servers */);
1374*6777b538SAndroid Build Coastguard Worker config.fallback_period = kFallbackPeriod;
1375*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1376*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1377*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1378*6777b538SAndroid Build Coastguard Worker
1379*6777b538SAndroid Build Coastguard Worker base::TimeDelta expected =
1380*6777b538SAndroid Build Coastguard Worker kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
1381*6777b538SAndroid Build Coastguard Worker ASSERT_GT(expected, features::kDnsMinTransactionTimeout.Get());
1382*6777b538SAndroid Build Coastguard Worker
1383*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.ClassicTransactionTimeout(session.get()), expected);
1384*6777b538SAndroid Build Coastguard Worker }
1385*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,ClassicTransactionTimeout_LongRtt)1386*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, ClassicTransactionTimeout_LongRtt) {
1387*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1388*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1389*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1390*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 0 /* num_doh_servers */);
1391*6777b538SAndroid Build Coastguard Worker config.fallback_period = base::TimeDelta();
1392*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1393*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1394*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1395*6777b538SAndroid Build Coastguard Worker
1396*6777b538SAndroid Build Coastguard Worker // Record long RTTs for only 1 server.
1397*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1398*6777b538SAndroid Build Coastguard Worker context.RecordRtt(1u /* server_index */, false /* is_doh_server */,
1399*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1400*6777b538SAndroid Build Coastguard Worker }
1401*6777b538SAndroid Build Coastguard Worker
1402*6777b538SAndroid Build Coastguard Worker // No expected change from recording RTT to single server because lowest
1403*6777b538SAndroid Build Coastguard Worker // fallback period is used.
1404*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.ClassicTransactionTimeout(session.get()),
1405*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1406*6777b538SAndroid Build Coastguard Worker
1407*6777b538SAndroid Build Coastguard Worker // Record long RTTs for remaining server.
1408*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 50; ++i) {
1409*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
1410*6777b538SAndroid Build Coastguard Worker base::Minutes(10), OK, session.get());
1411*6777b538SAndroid Build Coastguard Worker }
1412*6777b538SAndroid Build Coastguard Worker
1413*6777b538SAndroid Build Coastguard Worker // Expect longer timeouts.
1414*6777b538SAndroid Build Coastguard Worker EXPECT_GT(context.ClassicTransactionTimeout(session.get()),
1415*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1416*6777b538SAndroid Build Coastguard Worker }
1417*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,ClassicTransactionTimeout_DifferentSession)1418*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, ClassicTransactionTimeout_DifferentSession) {
1419*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kFallbackPeriod = base::Minutes(5);
1420*6777b538SAndroid Build Coastguard Worker DnsConfig config1 =
1421*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(1 /* num_servers */, 0 /* num_doh_servers */);
1422*6777b538SAndroid Build Coastguard Worker config1.fallback_period = kFallbackPeriod;
1423*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
1424*6777b538SAndroid Build Coastguard Worker
1425*6777b538SAndroid Build Coastguard Worker DnsConfig config2 =
1426*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1427*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
1428*6777b538SAndroid Build Coastguard Worker
1429*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1430*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1431*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session1.get(),
1432*6777b538SAndroid Build Coastguard Worker true /* network_change */);
1433*6777b538SAndroid Build Coastguard Worker
1434*6777b538SAndroid Build Coastguard Worker // Confirm that if session data were used, the timeout would be higher than
1435*6777b538SAndroid Build Coastguard Worker // the min. If timeout defaults are ever changed to break this assertion, then
1436*6777b538SAndroid Build Coastguard Worker // the expected wrong-session timeout could be the same as an actual
1437*6777b538SAndroid Build Coastguard Worker // from-session timeout, making this test seem to pass even if the behavior
1438*6777b538SAndroid Build Coastguard Worker // under test were broken.
1439*6777b538SAndroid Build Coastguard Worker base::TimeDelta multiplier_expected =
1440*6777b538SAndroid Build Coastguard Worker kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
1441*6777b538SAndroid Build Coastguard Worker ASSERT_GT(multiplier_expected, features::kDnsMinTransactionTimeout.Get());
1442*6777b538SAndroid Build Coastguard Worker
1443*6777b538SAndroid Build Coastguard Worker // Expect timeout always minimum with wrong session.
1444*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(context.ClassicTransactionTimeout(session2.get()),
1445*6777b538SAndroid Build Coastguard Worker features::kDnsMinTransactionTimeout.Get());
1446*6777b538SAndroid Build Coastguard Worker }
1447*6777b538SAndroid Build Coastguard Worker
1448*6777b538SAndroid Build Coastguard Worker // Ensures that reported negative RTT values don't cause a crash. Regression
1449*6777b538SAndroid Build Coastguard Worker // test for https://crbug.com/753568.
TEST_F(ResolveContextTest,NegativeRtt)1450*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, NegativeRtt) {
1451*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1452*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1453*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1454*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
1455*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1456*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1457*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1458*6777b538SAndroid Build Coastguard Worker
1459*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0 /* server_index */, false /* is_doh_server */,
1460*6777b538SAndroid Build Coastguard Worker base::Milliseconds(-1), OK /* rv */, session.get());
1461*6777b538SAndroid Build Coastguard Worker context.RecordRtt(0 /* server_index */, true /* is_doh_server */,
1462*6777b538SAndroid Build Coastguard Worker base::Milliseconds(-1), OK /* rv */, session.get());
1463*6777b538SAndroid Build Coastguard Worker }
1464*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,SessionChange)1465*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SessionChange) {
1466*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1467*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1468*6777b538SAndroid Build Coastguard Worker
1469*6777b538SAndroid Build Coastguard Worker TestDohStatusObserver observer;
1470*6777b538SAndroid Build Coastguard Worker context.RegisterDohStatusObserver(&observer);
1471*6777b538SAndroid Build Coastguard Worker
1472*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1473*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 3 /* num_doh_servers */);
1474*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1475*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1476*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1477*6777b538SAndroid Build Coastguard Worker
1478*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(observer.session_changes(), 1);
1479*6777b538SAndroid Build Coastguard Worker // Should get a server unavailable notification because there is >0 DoH
1480*6777b538SAndroid Build Coastguard Worker // servers that are reset on cache invalidation.
1481*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(observer.server_unavailable_notifications(), 1);
1482*6777b538SAndroid Build Coastguard Worker
1483*6777b538SAndroid Build Coastguard Worker context.UnregisterDohStatusObserver(&observer);
1484*6777b538SAndroid Build Coastguard Worker }
1485*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,SessionChange_NoSession)1486*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SessionChange_NoSession) {
1487*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1488*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1489*6777b538SAndroid Build Coastguard Worker
1490*6777b538SAndroid Build Coastguard Worker TestDohStatusObserver observer;
1491*6777b538SAndroid Build Coastguard Worker context.RegisterDohStatusObserver(&observer);
1492*6777b538SAndroid Build Coastguard Worker
1493*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(nullptr /* new_session */,
1494*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1495*6777b538SAndroid Build Coastguard Worker
1496*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(observer.session_changes(), 1);
1497*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(observer.server_unavailable_notifications(), 0);
1498*6777b538SAndroid Build Coastguard Worker
1499*6777b538SAndroid Build Coastguard Worker context.UnregisterDohStatusObserver(&observer);
1500*6777b538SAndroid Build Coastguard Worker }
1501*6777b538SAndroid Build Coastguard Worker
TEST_F(ResolveContextTest,SessionChange_NoDohServers)1502*6777b538SAndroid Build Coastguard Worker TEST_F(ResolveContextTest, SessionChange_NoDohServers) {
1503*6777b538SAndroid Build Coastguard Worker ResolveContext context(nullptr /* url_request_context */,
1504*6777b538SAndroid Build Coastguard Worker false /* enable_caching */);
1505*6777b538SAndroid Build Coastguard Worker
1506*6777b538SAndroid Build Coastguard Worker TestDohStatusObserver observer;
1507*6777b538SAndroid Build Coastguard Worker context.RegisterDohStatusObserver(&observer);
1508*6777b538SAndroid Build Coastguard Worker
1509*6777b538SAndroid Build Coastguard Worker DnsConfig config =
1510*6777b538SAndroid Build Coastguard Worker CreateDnsConfig(2 /* num_servers */, 0 /* num_doh_servers */);
1511*6777b538SAndroid Build Coastguard Worker scoped_refptr<DnsSession> session = CreateDnsSession(config);
1512*6777b538SAndroid Build Coastguard Worker context.InvalidateCachesAndPerSessionData(session.get(),
1513*6777b538SAndroid Build Coastguard Worker false /* network_change */);
1514*6777b538SAndroid Build Coastguard Worker
1515*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(observer.session_changes(), 1);
1516*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(observer.server_unavailable_notifications(), 0);
1517*6777b538SAndroid Build Coastguard Worker
1518*6777b538SAndroid Build Coastguard Worker context.UnregisterDohStatusObserver(&observer);
1519*6777b538SAndroid Build Coastguard Worker }
1520*6777b538SAndroid Build Coastguard Worker
1521*6777b538SAndroid Build Coastguard Worker } // namespace
1522*6777b538SAndroid Build Coastguard Worker } // namespace net
1523