resolve_context_unittest.cc 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/dns/resolve_context.h"
  5. #include <stdint.h>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/memory/ref_counted.h"
  11. #include "base/run_loop.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/time/time.h"
  14. #include "net/base/address_list.h"
  15. #include "net/base/features.h"
  16. #include "net/base/ip_address.h"
  17. #include "net/base/ip_endpoint.h"
  18. #include "net/base/mock_network_change_notifier.h"
  19. #include "net/base/network_change_notifier.h"
  20. #include "net/base/network_isolation_key.h"
  21. #include "net/dns/dns_config.h"
  22. #include "net/dns/dns_server_iterator.h"
  23. #include "net/dns/dns_session.h"
  24. #include "net/dns/host_cache.h"
  25. #include "net/dns/public/dns_over_https_config.h"
  26. #include "net/dns/public/dns_over_https_server_config.h"
  27. #include "net/dns/public/dns_protocol.h"
  28. #include "net/dns/public/dns_query_type.h"
  29. #include "net/dns/public/host_resolver_source.h"
  30. #include "net/socket/socket_test_util.h"
  31. #include "net/test/test_with_task_environment.h"
  32. #include "net/url_request/url_request_context.h"
  33. #include "net/url_request/url_request_context_builder.h"
  34. #include "net/url_request/url_request_test_util.h"
  35. #include "testing/gmock/include/gmock/gmock.h"
  36. #include "testing/gtest/include/gtest/gtest.h"
  37. namespace net {
  38. namespace {
  39. class ResolveContextTest : public TestWithTaskEnvironment {
  40. public:
  41. ResolveContextTest() = default;
  42. scoped_refptr<DnsSession> CreateDnsSession(const DnsConfig& config) {
  43. auto null_random_callback =
  44. base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
  45. return base::MakeRefCounted<DnsSession>(config, null_random_callback,
  46. nullptr /* netlog */);
  47. }
  48. protected:
  49. test::ScopedMockNetworkChangeNotifier mock_notifier_;
  50. private:
  51. std::unique_ptr<MockClientSocketFactory> socket_factory_ =
  52. std::make_unique<MockClientSocketFactory>();
  53. };
  54. DnsConfig CreateDnsConfig(int num_servers, int num_doh_servers) {
  55. DnsConfig config;
  56. for (int i = 0; i < num_servers; ++i) {
  57. IPEndPoint dns_endpoint(IPAddress(192, 168, 1, static_cast<uint8_t>(i)),
  58. dns_protocol::kDefaultPort);
  59. config.nameservers.push_back(dns_endpoint);
  60. }
  61. std::vector<std::string> templates;
  62. templates.reserve(num_doh_servers);
  63. for (int i = 0; i < num_doh_servers; ++i) {
  64. templates.push_back(
  65. base::StringPrintf("https://mock.http/doh_test_%d{?dns}", i));
  66. }
  67. config.doh_config =
  68. *DnsOverHttpsConfig::FromTemplatesForTesting(std::move(templates));
  69. return config;
  70. }
  71. // Simulate a new session with the same pointer as an old deleted session by
  72. // invalidating WeakPtrs.
  73. TEST_F(ResolveContextTest, ReusedSessionPointer) {
  74. DnsConfig config =
  75. CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
  76. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  77. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  78. ResolveContext context(request_context.get(), true /* enable_caching */);
  79. context.InvalidateCachesAndPerSessionData(session.get(),
  80. false /* network_change */);
  81. // Mark probe success for the "original" (pre-invalidation) session.
  82. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  83. session.get());
  84. ASSERT_TRUE(context.GetDohServerAvailability(1u, session.get()));
  85. // Simulate session destruction and recreation on the same pointer.
  86. session->InvalidateWeakPtrsForTesting();
  87. // Expect |session| should now be treated as a new session, not matching
  88. // |context|'s "current" session. Expect availability from the "old" session
  89. // should not be read and RecordServerSuccess() should have no effect because
  90. // the "new" session has not yet been marked as "current" through
  91. // InvalidateCaches().
  92. EXPECT_FALSE(context.GetDohServerAvailability(1u, session.get()));
  93. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  94. session.get());
  95. EXPECT_FALSE(context.GetDohServerAvailability(1u, session.get()));
  96. }
  97. TEST_F(ResolveContextTest, DohServerAvailability_InitialAvailability) {
  98. DnsConfig config =
  99. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  100. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  101. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  102. ResolveContext context(request_context.get(), true /* enable_caching */);
  103. context.InvalidateCachesAndPerSessionData(session.get(),
  104. false /* network_change */);
  105. EXPECT_EQ(context.NumAvailableDohServers(session.get()), 0u);
  106. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  107. session->config(), SecureDnsMode::kAutomatic, session.get());
  108. EXPECT_FALSE(doh_itr->AttemptAvailable());
  109. }
  110. TEST_F(ResolveContextTest, DohServerAvailability_RecordedSuccess) {
  111. DnsConfig config =
  112. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  113. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  114. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  115. ResolveContext context(request_context.get(), true /* enable_caching */);
  116. context.InvalidateCachesAndPerSessionData(session.get(),
  117. false /* network_change */);
  118. ASSERT_EQ(context.NumAvailableDohServers(session.get()), 0u);
  119. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  120. session.get());
  121. EXPECT_EQ(context.NumAvailableDohServers(session.get()), 1u);
  122. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  123. session->config(), SecureDnsMode::kAutomatic, session.get());
  124. ASSERT_TRUE(doh_itr->AttemptAvailable());
  125. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  126. }
  127. TEST_F(ResolveContextTest, DohServerAvailability_NoCurrentSession) {
  128. DnsConfig config =
  129. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  130. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  131. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  132. ResolveContext context(request_context.get(), true /* enable_caching */);
  133. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  134. session.get());
  135. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  136. session->config(), SecureDnsMode::kAutomatic, session.get());
  137. EXPECT_FALSE(doh_itr->AttemptAvailable());
  138. EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
  139. EXPECT_FALSE(context.GetDohServerAvailability(1, session.get()));
  140. }
  141. TEST_F(ResolveContextTest, DohServerAvailability_DifferentSession) {
  142. DnsConfig config1 =
  143. CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
  144. scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
  145. DnsConfig config2 =
  146. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  147. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  148. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  149. ResolveContext context(request_context.get(), true /* enable_caching */);
  150. context.InvalidateCachesAndPerSessionData(session2.get(),
  151. true /* network_change */);
  152. // Use current session to set a probe result.
  153. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  154. session2.get());
  155. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  156. session1->config(), SecureDnsMode::kAutomatic, session1.get());
  157. EXPECT_FALSE(doh_itr->AttemptAvailable());
  158. EXPECT_EQ(0u, context.NumAvailableDohServers(session1.get()));
  159. EXPECT_FALSE(context.GetDohServerAvailability(1u, session1.get()));
  160. // Different session for RecordServerFailure() should have no effect.
  161. ASSERT_TRUE(context.GetDohServerAvailability(1u, session2.get()));
  162. for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
  163. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  164. ERR_FAILED, session1.get());
  165. }
  166. EXPECT_TRUE(context.GetDohServerAvailability(1u, session2.get()));
  167. }
  168. TEST_F(ResolveContextTest, DohServerIndexToUse) {
  169. DnsConfig config =
  170. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  171. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  172. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  173. ResolveContext context(request_context.get(), true /* enable_caching */);
  174. context.InvalidateCachesAndPerSessionData(session.get(),
  175. false /* network_change */);
  176. context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
  177. session.get());
  178. EXPECT_EQ(context.NumAvailableDohServers(session.get()), 1u);
  179. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  180. session->config(), SecureDnsMode::kAutomatic, session.get());
  181. ASSERT_TRUE(doh_itr->AttemptAvailable());
  182. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
  183. EXPECT_FALSE(doh_itr->AttemptAvailable());
  184. }
  185. TEST_F(ResolveContextTest, DohServerIndexToUse_NoneEligible) {
  186. DnsConfig config =
  187. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  188. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  189. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  190. ResolveContext context(request_context.get(), true /* enable_caching */);
  191. context.InvalidateCachesAndPerSessionData(session.get(),
  192. false /* network_change */);
  193. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  194. session->config(), SecureDnsMode::kAutomatic, session.get());
  195. EXPECT_FALSE(doh_itr->AttemptAvailable());
  196. }
  197. TEST_F(ResolveContextTest, DohServerIndexToUse_SecureMode) {
  198. DnsConfig config =
  199. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  200. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  201. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  202. ResolveContext context(request_context.get(), true /* enable_caching */);
  203. context.InvalidateCachesAndPerSessionData(session.get(),
  204. false /* network_change */);
  205. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  206. session->config(), SecureDnsMode::kSecure, session.get());
  207. ASSERT_TRUE(doh_itr->AttemptAvailable());
  208. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
  209. ASSERT_TRUE(doh_itr->AttemptAvailable());
  210. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  211. }
  212. class TestDnsObserver : public NetworkChangeNotifier::DNSObserver {
  213. public:
  214. void OnDNSChanged() override { ++dns_changed_calls_; }
  215. int dns_changed_calls() const { return dns_changed_calls_; }
  216. private:
  217. int dns_changed_calls_ = 0;
  218. };
  219. TEST_F(ResolveContextTest, DohServerAvailabilityNotification) {
  220. TestDnsObserver config_observer;
  221. NetworkChangeNotifier::AddDNSObserver(&config_observer);
  222. DnsConfig config =
  223. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  224. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  225. auto request_context = CreateTestURLRequestContextBuilder()->Build();
  226. ResolveContext context(request_context.get(), true /* enable_caching */);
  227. context.InvalidateCachesAndPerSessionData(session.get(),
  228. false /* network_change */);
  229. base::RunLoop().RunUntilIdle(); // Notifications are async.
  230. EXPECT_EQ(0, config_observer.dns_changed_calls());
  231. // Expect notification on first available DoH server.
  232. ASSERT_EQ(0u, context.NumAvailableDohServers(session.get()));
  233. context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
  234. session.get());
  235. ASSERT_EQ(1u, context.NumAvailableDohServers(session.get()));
  236. base::RunLoop().RunUntilIdle(); // Notifications are async.
  237. EXPECT_EQ(1, config_observer.dns_changed_calls());
  238. // No notifications as additional servers are available or unavailable.
  239. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  240. session.get());
  241. base::RunLoop().RunUntilIdle(); // Notifications are async.
  242. EXPECT_EQ(1, config_observer.dns_changed_calls());
  243. for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
  244. ASSERT_EQ(2u, context.NumAvailableDohServers(session.get()));
  245. context.RecordServerFailure(0u /* server_index */, true /* is_doh_server */,
  246. ERR_FAILED, session.get());
  247. base::RunLoop().RunUntilIdle(); // Notifications are async.
  248. EXPECT_EQ(1, config_observer.dns_changed_calls());
  249. }
  250. ASSERT_EQ(1u, context.NumAvailableDohServers(session.get()));
  251. // Expect notification on last server unavailable.
  252. for (int i = 0; i < ResolveContext::kAutomaticModeFailureLimit; ++i) {
  253. ASSERT_EQ(1u, context.NumAvailableDohServers(session.get()));
  254. base::RunLoop().RunUntilIdle(); // Notifications are async.
  255. EXPECT_EQ(1, config_observer.dns_changed_calls());
  256. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  257. ERR_FAILED, session.get());
  258. }
  259. ASSERT_EQ(0u, context.NumAvailableDohServers(session.get()));
  260. base::RunLoop().RunUntilIdle(); // Notifications are async.
  261. EXPECT_EQ(2, config_observer.dns_changed_calls());
  262. NetworkChangeNotifier::RemoveDNSObserver(&config_observer);
  263. }
  264. TEST_F(ResolveContextTest, HostCacheInvalidation) {
  265. ResolveContext context(nullptr /* url_request_context */,
  266. true /* enable_caching */);
  267. base::TimeTicks now;
  268. HostCache::Key key("example.com", DnsQueryType::UNSPECIFIED, 0,
  269. HostResolverSource::ANY, NetworkIsolationKey());
  270. context.host_cache()->Set(
  271. key,
  272. HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
  273. HostCache::Entry::SOURCE_UNKNOWN),
  274. now, base::Seconds(10));
  275. ASSERT_TRUE(context.host_cache()->Lookup(key, now));
  276. DnsConfig config =
  277. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  278. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  279. context.InvalidateCachesAndPerSessionData(session.get(),
  280. false /* network_change */);
  281. EXPECT_FALSE(context.host_cache()->Lookup(key, now));
  282. // Re-add to the host cache and now add some DoH server status.
  283. context.host_cache()->Set(
  284. key,
  285. HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
  286. HostCache::Entry::SOURCE_UNKNOWN),
  287. now, base::Seconds(10));
  288. context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
  289. session.get());
  290. ASSERT_TRUE(context.host_cache()->Lookup(key, now));
  291. ASSERT_TRUE(context.GetDohServerAvailability(0u, session.get()));
  292. // Invalidate again.
  293. DnsConfig config2 =
  294. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  295. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  296. context.InvalidateCachesAndPerSessionData(session2.get(),
  297. true /* network_change */);
  298. EXPECT_FALSE(context.host_cache()->Lookup(key, now));
  299. EXPECT_FALSE(context.GetDohServerAvailability(0u, session.get()));
  300. EXPECT_FALSE(context.GetDohServerAvailability(0u, session2.get()));
  301. }
  302. TEST_F(ResolveContextTest, HostCacheInvalidation_SameSession) {
  303. ResolveContext context(nullptr /* url_request_context */,
  304. true /* enable_caching */);
  305. DnsConfig config =
  306. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  307. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  308. // Initial invalidation just to set the session.
  309. context.InvalidateCachesAndPerSessionData(session.get(),
  310. false /* network_change */);
  311. // Add to the host cache and add some DoH server status.
  312. base::TimeTicks now;
  313. HostCache::Key key("example.com", DnsQueryType::UNSPECIFIED, 0,
  314. HostResolverSource::ANY, NetworkIsolationKey());
  315. context.host_cache()->Set(
  316. key,
  317. HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{"example.com"},
  318. HostCache::Entry::SOURCE_UNKNOWN),
  319. now, base::Seconds(10));
  320. context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
  321. session.get());
  322. ASSERT_TRUE(context.host_cache()->Lookup(key, now));
  323. ASSERT_TRUE(context.GetDohServerAvailability(0u, session.get()));
  324. // Invalidate again with the same session.
  325. context.InvalidateCachesAndPerSessionData(session.get(),
  326. false /* network_change */);
  327. // Expect host cache to be invalidated but not the per-session data.
  328. EXPECT_FALSE(context.host_cache()->Lookup(key, now));
  329. EXPECT_TRUE(context.GetDohServerAvailability(0u, session.get()));
  330. }
  331. TEST_F(ResolveContextTest, Failures_Consecutive) {
  332. ResolveContext context(nullptr /* url_request_context */,
  333. false /* enable_caching */);
  334. DnsConfig config =
  335. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  336. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  337. context.InvalidateCachesAndPerSessionData(session.get(),
  338. false /* network_change */);
  339. // Expect server preference to change after |config.attempts| failures.
  340. for (int i = 0; i < config.attempts; i++) {
  341. std::unique_ptr<DnsServerIterator> classic_itr =
  342. context.GetClassicDnsIterator(session->config(), session.get());
  343. ASSERT_TRUE(classic_itr->AttemptAvailable());
  344. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  345. ASSERT_TRUE(classic_itr->AttemptAvailable());
  346. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  347. context.RecordServerFailure(1u /* server_index */,
  348. false /* is_doh_server */, ERR_FAILED,
  349. session.get());
  350. }
  351. {
  352. std::unique_ptr<DnsServerIterator> classic_itr =
  353. context.GetClassicDnsIterator(session->config(), session.get());
  354. ASSERT_TRUE(classic_itr->AttemptAvailable());
  355. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  356. ASSERT_TRUE(classic_itr->AttemptAvailable());
  357. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  358. }
  359. // Expect failures to be reset on successful request.
  360. context.RecordServerSuccess(1u /* server_index */, false /* is_doh_server */,
  361. session.get());
  362. {
  363. std::unique_ptr<DnsServerIterator> classic_itr =
  364. context.GetClassicDnsIterator(session->config(), session.get());
  365. ASSERT_TRUE(classic_itr->AttemptAvailable());
  366. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  367. ASSERT_TRUE(classic_itr->AttemptAvailable());
  368. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  369. }
  370. }
  371. TEST_F(ResolveContextTest, Failures_NonConsecutive) {
  372. ResolveContext context(nullptr /* url_request_context */,
  373. false /* enable_caching */);
  374. DnsConfig config =
  375. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  376. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  377. context.InvalidateCachesAndPerSessionData(session.get(),
  378. false /* network_change */);
  379. for (int i = 0; i < config.attempts - 1; i++) {
  380. std::unique_ptr<DnsServerIterator> classic_itr =
  381. context.GetClassicDnsIterator(session->config(), session.get());
  382. ASSERT_TRUE(classic_itr->AttemptAvailable());
  383. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  384. ASSERT_TRUE(classic_itr->AttemptAvailable());
  385. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  386. context.RecordServerFailure(1u /* server_index */,
  387. false /* is_doh_server */, ERR_FAILED,
  388. session.get());
  389. }
  390. {
  391. std::unique_ptr<DnsServerIterator> classic_itr =
  392. context.GetClassicDnsIterator(session->config(), session.get());
  393. ASSERT_TRUE(classic_itr->AttemptAvailable());
  394. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  395. ASSERT_TRUE(classic_itr->AttemptAvailable());
  396. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  397. }
  398. context.RecordServerSuccess(1u /* server_index */, false /* is_doh_server */,
  399. session.get());
  400. {
  401. std::unique_ptr<DnsServerIterator> classic_itr =
  402. context.GetClassicDnsIterator(session->config(), session.get());
  403. ASSERT_TRUE(classic_itr->AttemptAvailable());
  404. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  405. ASSERT_TRUE(classic_itr->AttemptAvailable());
  406. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  407. }
  408. // Expect server stay preferred through non-consecutive failures.
  409. context.RecordServerFailure(1u /* server_index */, false /* is_doh_server */,
  410. ERR_FAILED, session.get());
  411. {
  412. std::unique_ptr<DnsServerIterator> classic_itr =
  413. context.GetClassicDnsIterator(session->config(), session.get());
  414. ASSERT_TRUE(classic_itr->AttemptAvailable());
  415. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  416. ASSERT_TRUE(classic_itr->AttemptAvailable());
  417. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  418. }
  419. }
  420. TEST_F(ResolveContextTest, Failures_NoSession) {
  421. ResolveContext context(nullptr /* url_request_context */,
  422. false /* enable_caching */);
  423. DnsConfig config =
  424. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  425. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  426. // No expected change from recording failures.
  427. for (int i = 0; i < config.attempts; i++) {
  428. std::unique_ptr<DnsServerIterator> classic_itr =
  429. context.GetClassicDnsIterator(session->config(), session.get());
  430. EXPECT_FALSE(classic_itr->AttemptAvailable());
  431. context.RecordServerFailure(1u /* server_index */,
  432. false /* is_doh_server */, ERR_FAILED,
  433. session.get());
  434. }
  435. std::unique_ptr<DnsServerIterator> classic_itr =
  436. context.GetClassicDnsIterator(session->config(), session.get());
  437. EXPECT_FALSE(classic_itr->AttemptAvailable());
  438. }
  439. TEST_F(ResolveContextTest, Failures_DifferentSession) {
  440. DnsConfig config1 =
  441. CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
  442. scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
  443. DnsConfig config2 =
  444. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  445. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  446. ResolveContext context(nullptr /* url_request_context */,
  447. false /* enable_caching */);
  448. context.InvalidateCachesAndPerSessionData(session2.get(),
  449. true /* network_change */);
  450. // No change from recording failures to wrong session.
  451. for (int i = 0; i < config1.attempts; i++) {
  452. std::unique_ptr<DnsServerIterator> classic_itr =
  453. context.GetClassicDnsIterator(session2->config(), session2.get());
  454. ASSERT_TRUE(classic_itr->AttemptAvailable());
  455. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  456. ASSERT_TRUE(classic_itr->AttemptAvailable());
  457. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  458. context.RecordServerFailure(1u /* server_index */,
  459. false /* is_doh_server */, ERR_FAILED,
  460. session1.get());
  461. }
  462. std::unique_ptr<DnsServerIterator> classic_itr =
  463. context.GetClassicDnsIterator(session2->config(), session2.get());
  464. ASSERT_TRUE(classic_itr->AttemptAvailable());
  465. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  466. ASSERT_TRUE(classic_itr->AttemptAvailable());
  467. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  468. }
  469. // Test 2 of 3 servers failing.
  470. TEST_F(ResolveContextTest, TwoFailures) {
  471. ResolveContext context(nullptr /* url_request_context */,
  472. false /* enable_caching */);
  473. DnsConfig config =
  474. CreateDnsConfig(3 /* num_servers */, 2 /* num_doh_servers */);
  475. config.attempts = 1;
  476. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  477. context.InvalidateCachesAndPerSessionData(session.get(),
  478. false /* network_change */);
  479. // Expect server preference to change after |config.attempts| failures.
  480. for (int i = 0; i < config.attempts; i++) {
  481. std::unique_ptr<DnsServerIterator> classic_itr =
  482. context.GetClassicDnsIterator(session->config(), session.get());
  483. ASSERT_TRUE(classic_itr->AttemptAvailable());
  484. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  485. ASSERT_TRUE(classic_itr->AttemptAvailable());
  486. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  487. ASSERT_TRUE(classic_itr->AttemptAvailable());
  488. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 2u);
  489. context.RecordServerFailure(0u /* server_index */,
  490. false /* is_doh_server */, ERR_FAILED,
  491. session.get());
  492. context.RecordServerFailure(1u /* server_index */,
  493. false /* is_doh_server */, ERR_FAILED,
  494. session.get());
  495. }
  496. {
  497. std::unique_ptr<DnsServerIterator> classic_itr =
  498. context.GetClassicDnsIterator(session->config(), session.get());
  499. ASSERT_TRUE(classic_itr->AttemptAvailable());
  500. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 2u);
  501. ASSERT_TRUE(classic_itr->AttemptAvailable());
  502. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  503. ASSERT_TRUE(classic_itr->AttemptAvailable());
  504. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  505. }
  506. // Expect failures to be reset on successful request.
  507. context.RecordServerSuccess(0u /* server_index */, false /* is_doh_server */,
  508. session.get());
  509. context.RecordServerSuccess(1u /* server_index */, false /* is_doh_server */,
  510. session.get());
  511. {
  512. std::unique_ptr<DnsServerIterator> classic_itr =
  513. context.GetClassicDnsIterator(session->config(), session.get());
  514. ASSERT_TRUE(classic_itr->AttemptAvailable());
  515. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 0u);
  516. ASSERT_TRUE(classic_itr->AttemptAvailable());
  517. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 1u);
  518. ASSERT_TRUE(classic_itr->AttemptAvailable());
  519. EXPECT_EQ(classic_itr->GetNextAttemptIndex(), 2u);
  520. }
  521. }
  522. class TestDohStatusObserver : public ResolveContext::DohStatusObserver {
  523. public:
  524. void OnSessionChanged() override { ++session_changes_; }
  525. void OnDohServerUnavailable(bool network_change) override {
  526. ++server_unavailable_notifications_;
  527. }
  528. int session_changes() const { return session_changes_; }
  529. int server_unavailable_notifications() const {
  530. return server_unavailable_notifications_;
  531. }
  532. private:
  533. int session_changes_ = 0;
  534. int server_unavailable_notifications_ = 0;
  535. };
  536. TEST_F(ResolveContextTest, DohFailures_Consecutive) {
  537. ResolveContext context(nullptr /* url_request_context */,
  538. false /* enable_caching */);
  539. DnsConfig config =
  540. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  541. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  542. context.InvalidateCachesAndPerSessionData(session.get(),
  543. false /* network_change */);
  544. TestDohStatusObserver observer;
  545. context.RegisterDohStatusObserver(&observer);
  546. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  547. session.get());
  548. for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
  549. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  550. session->config(), SecureDnsMode::kAutomatic, session.get());
  551. ASSERT_TRUE(doh_itr->AttemptAvailable());
  552. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  553. EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
  554. EXPECT_EQ(0, observer.server_unavailable_notifications());
  555. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  556. ERR_FAILED, session.get());
  557. }
  558. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  559. session->config(), SecureDnsMode::kAutomatic, session.get());
  560. EXPECT_FALSE(doh_itr->AttemptAvailable());
  561. EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
  562. EXPECT_EQ(1, observer.server_unavailable_notifications());
  563. context.UnregisterDohStatusObserver(&observer);
  564. }
  565. TEST_F(ResolveContextTest, DohFailures_NonConsecutive) {
  566. ResolveContext context(nullptr /* url_request_context */,
  567. false /* enable_caching */);
  568. DnsConfig config =
  569. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  570. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  571. context.InvalidateCachesAndPerSessionData(session.get(),
  572. false /* network_change */);
  573. TestDohStatusObserver observer;
  574. context.RegisterDohStatusObserver(&observer);
  575. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  576. session.get());
  577. for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit - 1; i++) {
  578. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  579. session->config(), SecureDnsMode::kAutomatic, session.get());
  580. ASSERT_TRUE(doh_itr->AttemptAvailable());
  581. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  582. EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
  583. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  584. ERR_FAILED, session.get());
  585. }
  586. {
  587. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  588. session->config(), SecureDnsMode::kAutomatic, session.get());
  589. ASSERT_TRUE(doh_itr->AttemptAvailable());
  590. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  591. }
  592. EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
  593. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  594. session.get());
  595. {
  596. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  597. session->config(), SecureDnsMode::kAutomatic, session.get());
  598. ASSERT_TRUE(doh_itr->AttemptAvailable());
  599. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  600. }
  601. EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
  602. // Expect a single additional failure should not make a DoH server unavailable
  603. // because the success resets failure tracking.
  604. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  605. ERR_FAILED, session.get());
  606. {
  607. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  608. session->config(), SecureDnsMode::kAutomatic, session.get());
  609. ASSERT_TRUE(doh_itr->AttemptAvailable());
  610. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  611. }
  612. EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
  613. EXPECT_EQ(0, observer.server_unavailable_notifications());
  614. context.UnregisterDohStatusObserver(&observer);
  615. }
  616. TEST_F(ResolveContextTest, DohFailures_SuccessAfterFailures) {
  617. ResolveContext context(nullptr /* url_request_context */,
  618. false /* enable_caching */);
  619. DnsConfig config =
  620. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  621. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  622. context.InvalidateCachesAndPerSessionData(session.get(),
  623. false /* network_change */);
  624. TestDohStatusObserver observer;
  625. context.RegisterDohStatusObserver(&observer);
  626. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  627. session.get());
  628. for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
  629. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  630. ERR_FAILED, session.get());
  631. }
  632. ASSERT_EQ(0u, context.NumAvailableDohServers(session.get()));
  633. EXPECT_EQ(1, observer.server_unavailable_notifications());
  634. // Expect a single success to make an unavailable DoH server available again.
  635. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  636. session.get());
  637. {
  638. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  639. session->config(), SecureDnsMode::kAutomatic, session.get());
  640. ASSERT_TRUE(doh_itr->AttemptAvailable());
  641. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  642. }
  643. EXPECT_EQ(1u, context.NumAvailableDohServers(session.get()));
  644. EXPECT_EQ(1, observer.server_unavailable_notifications());
  645. context.UnregisterDohStatusObserver(&observer);
  646. }
  647. TEST_F(ResolveContextTest, DohFailures_NoSession) {
  648. ResolveContext context(nullptr /* url_request_context */,
  649. false /* enable_caching */);
  650. DnsConfig config =
  651. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  652. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  653. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  654. session.get());
  655. // No expected change from recording failures.
  656. for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
  657. EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
  658. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  659. ERR_FAILED, session.get());
  660. }
  661. EXPECT_EQ(0u, context.NumAvailableDohServers(session.get()));
  662. }
  663. TEST_F(ResolveContextTest, DohFailures_DifferentSession) {
  664. DnsConfig config1 =
  665. CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
  666. scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
  667. DnsConfig config2 =
  668. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  669. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  670. ResolveContext context(nullptr /* url_request_context */,
  671. false /* enable_caching */);
  672. context.InvalidateCachesAndPerSessionData(session2.get(),
  673. true /* network_change */);
  674. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  675. session2.get());
  676. ASSERT_EQ(1u, context.NumAvailableDohServers(session2.get()));
  677. // No change from recording failures to wrong session.
  678. for (size_t i = 0; i < ResolveContext::kAutomaticModeFailureLimit; i++) {
  679. EXPECT_EQ(1u, context.NumAvailableDohServers(session2.get()));
  680. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  681. ERR_FAILED, session1.get());
  682. }
  683. EXPECT_EQ(1u, context.NumAvailableDohServers(session2.get()));
  684. }
  685. // Test 2 of 3 DoH servers failing.
  686. TEST_F(ResolveContextTest, TwoDohFailures) {
  687. ResolveContext context(nullptr /* url_request_context */,
  688. false /* enable_caching */);
  689. DnsConfig config =
  690. CreateDnsConfig(2 /* num_servers */, 3 /* num_doh_servers */);
  691. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  692. context.InvalidateCachesAndPerSessionData(session.get(),
  693. false /* network_change */);
  694. context.RecordServerSuccess(0u /* server_index */, true /* is_doh_server */,
  695. session.get());
  696. context.RecordServerSuccess(1u /* server_index */, true /* is_doh_server */,
  697. session.get());
  698. context.RecordServerSuccess(2u /* server_index */, true /* is_doh_server */,
  699. session.get());
  700. // Expect server preference to change after |config.attempts| failures.
  701. for (int i = 0; i < config.attempts; i++) {
  702. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  703. session->config(), SecureDnsMode::kAutomatic, session.get());
  704. ASSERT_TRUE(doh_itr->AttemptAvailable());
  705. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 0u);
  706. ASSERT_TRUE(doh_itr->AttemptAvailable());
  707. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 1u);
  708. ASSERT_TRUE(doh_itr->AttemptAvailable());
  709. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
  710. context.RecordServerFailure(0u /* server_index */, true /* is_doh_server */,
  711. ERR_FAILED, session.get());
  712. context.RecordServerFailure(1u /* server_index */, true /* is_doh_server */,
  713. ERR_FAILED, session.get());
  714. }
  715. std::unique_ptr<DnsServerIterator> doh_itr = context.GetDohIterator(
  716. session->config(), SecureDnsMode::kAutomatic, session.get());
  717. ASSERT_TRUE(doh_itr->AttemptAvailable());
  718. EXPECT_EQ(doh_itr->GetNextAttemptIndex(), 2u);
  719. }
  720. // Expect default calculated fallback period to be within 10ms of
  721. // |DnsConfig::fallback_period|.
  722. TEST_F(ResolveContextTest, FallbackPeriod_Default) {
  723. ResolveContext context(nullptr /* url_request_context */,
  724. false /* enable_caching */);
  725. DnsConfig config =
  726. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  727. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  728. context.InvalidateCachesAndPerSessionData(session.get(),
  729. false /* network_change */);
  730. base::TimeDelta delta =
  731. context.NextClassicFallbackPeriod(0 /* server_index */, 0 /* attempt */,
  732. session.get()) -
  733. config.fallback_period;
  734. EXPECT_LE(delta, base::Milliseconds(10));
  735. delta =
  736. context.NextDohFallbackPeriod(0 /* doh_server_index */, session.get()) -
  737. config.fallback_period;
  738. EXPECT_LE(delta, base::Milliseconds(10));
  739. }
  740. // Expect short calculated fallback period to be within 10ms of
  741. // |DnsConfig::fallback_period|.
  742. TEST_F(ResolveContextTest, FallbackPeriod_ShortConfigured) {
  743. ResolveContext context(nullptr /* url_request_context */,
  744. false /* enable_caching */);
  745. DnsConfig config =
  746. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  747. config.fallback_period = base::Milliseconds(15);
  748. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  749. context.InvalidateCachesAndPerSessionData(session.get(),
  750. false /* network_change */);
  751. base::TimeDelta delta =
  752. context.NextClassicFallbackPeriod(0 /* server_index */, 0 /* attempt */,
  753. session.get()) -
  754. config.fallback_period;
  755. EXPECT_LE(delta, base::Milliseconds(10));
  756. delta =
  757. context.NextDohFallbackPeriod(0 /* doh_server_index */, session.get()) -
  758. config.fallback_period;
  759. EXPECT_LE(delta, base::Milliseconds(10));
  760. }
  761. // Expect long calculated fallback period to be equal to
  762. // |DnsConfig::fallback_period|. (Default max fallback period is 5 seconds, so
  763. // NextClassicFallbackPeriod() should return exactly the config fallback
  764. // period.)
  765. TEST_F(ResolveContextTest, FallbackPeriod_LongConfigured) {
  766. ResolveContext context(nullptr /* url_request_context */,
  767. false /* enable_caching */);
  768. DnsConfig config =
  769. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  770. config.fallback_period = base::Seconds(15);
  771. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  772. context.InvalidateCachesAndPerSessionData(session.get(),
  773. false /* network_change */);
  774. EXPECT_EQ(context.NextClassicFallbackPeriod(0 /* server_index */,
  775. 0 /* attempt */, session.get()),
  776. config.fallback_period);
  777. EXPECT_EQ(
  778. context.NextDohFallbackPeriod(0 /* doh_server_index */, session.get()),
  779. config.fallback_period);
  780. }
  781. // Expect fallback periods to increase on recording long round-trip times.
  782. TEST_F(ResolveContextTest, FallbackPeriod_LongRtt) {
  783. ResolveContext context(nullptr /* url_request_context */,
  784. false /* enable_caching */);
  785. DnsConfig config =
  786. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  787. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  788. context.InvalidateCachesAndPerSessionData(session.get(),
  789. false /* network_change */);
  790. for (int i = 0; i < 50; ++i) {
  791. context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
  792. base::Minutes(10), OK, session.get());
  793. context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
  794. base::Minutes(10), OK, session.get());
  795. }
  796. // Expect servers with high recorded RTT to have increased fallback periods
  797. // (>10ms).
  798. base::TimeDelta delta =
  799. context.NextClassicFallbackPeriod(0u /* server_index */, 0 /* attempt */,
  800. session.get()) -
  801. config.fallback_period;
  802. EXPECT_GT(delta, base::Milliseconds(10));
  803. delta =
  804. context.NextDohFallbackPeriod(1u, session.get()) - config.fallback_period;
  805. EXPECT_GT(delta, base::Milliseconds(10));
  806. // Servers without recorded RTT expected to remain the same (<=10ms).
  807. delta = context.NextClassicFallbackPeriod(1u /* server_index */,
  808. 0 /* attempt */, session.get()) -
  809. config.fallback_period;
  810. EXPECT_LE(delta, base::Milliseconds(10));
  811. delta =
  812. context.NextDohFallbackPeriod(0u /* doh_server_index */, session.get()) -
  813. config.fallback_period;
  814. EXPECT_LE(delta, base::Milliseconds(10));
  815. }
  816. // Expect recording round-trip times to have no affect on fallback period
  817. // without a current session.
  818. TEST_F(ResolveContextTest, FallbackPeriod_NoSession) {
  819. ResolveContext context(nullptr /* url_request_context */,
  820. false /* enable_caching */);
  821. DnsConfig config =
  822. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  823. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  824. for (int i = 0; i < 50; ++i) {
  825. context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
  826. base::Minutes(10), OK, session.get());
  827. context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
  828. base::Minutes(10), OK, session.get());
  829. }
  830. base::TimeDelta delta =
  831. context.NextClassicFallbackPeriod(0u /* server_index */, 0 /* attempt */,
  832. session.get()) -
  833. config.fallback_period;
  834. EXPECT_LE(delta, base::Milliseconds(10));
  835. delta =
  836. context.NextDohFallbackPeriod(1u /* doh_server_index */, session.get()) -
  837. config.fallback_period;
  838. EXPECT_LE(delta, base::Milliseconds(10));
  839. }
  840. // Expect recording round-trip times to have no affect on fallback periods
  841. // without a current session.
  842. TEST_F(ResolveContextTest, FallbackPeriod_DifferentSession) {
  843. DnsConfig config1 =
  844. CreateDnsConfig(1 /* num_servers */, 3 /* num_doh_servers */);
  845. scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
  846. DnsConfig config2 =
  847. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  848. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  849. ResolveContext context(nullptr /* url_request_context */,
  850. false /* enable_caching */);
  851. context.InvalidateCachesAndPerSessionData(session2.get(),
  852. true /* network_change */);
  853. // Record RTT's to increase fallback periods for current session.
  854. for (int i = 0; i < 50; ++i) {
  855. context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
  856. base::Minutes(10), OK, session2.get());
  857. context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
  858. base::Minutes(10), OK, session2.get());
  859. }
  860. // Expect normal short fallback periods for other session.
  861. base::TimeDelta delta =
  862. context.NextClassicFallbackPeriod(0u /* server_index */, 0 /* attempt */,
  863. session1.get()) -
  864. config1.fallback_period;
  865. EXPECT_LE(delta, base::Milliseconds(10));
  866. delta =
  867. context.NextDohFallbackPeriod(0u /* doh_server_index */, session1.get()) -
  868. config1.fallback_period;
  869. EXPECT_LE(delta, base::Milliseconds(10));
  870. // Recording RTT's for other session should have no effect on current session
  871. // fallback periods.
  872. base::TimeDelta fallback_period = context.NextClassicFallbackPeriod(
  873. 0u /* server_index */, 0 /* attempt */, session2.get());
  874. for (int i = 0; i < 50; ++i) {
  875. context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
  876. base::Milliseconds(1), OK, session1.get());
  877. }
  878. EXPECT_EQ(fallback_period,
  879. context.NextClassicFallbackPeriod(0u /* server_index */,
  880. 0 /* attempt */, session2.get()));
  881. }
  882. // Expect minimum timeout will be used when fallback period is small.
  883. TEST_F(ResolveContextTest, SecureTransactionTimeout_SmallFallbackPeriod) {
  884. ResolveContext context(nullptr /* url_request_context */,
  885. false /* enable_caching */);
  886. DnsConfig config =
  887. CreateDnsConfig(0 /* num_servers */, 1 /* num_doh_servers */);
  888. config.fallback_period = base::TimeDelta();
  889. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  890. context.InvalidateCachesAndPerSessionData(session.get(),
  891. false /* network_change */);
  892. EXPECT_EQ(
  893. context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
  894. features::kDnsMinTransactionTimeout.Get());
  895. }
  896. // Expect multiplier on fallback period to be used when larger than minimum
  897. // timeout.
  898. TEST_F(ResolveContextTest, SecureTransactionTimeout_LongFallbackPeriod) {
  899. ResolveContext context(nullptr /* url_request_context */,
  900. false /* enable_caching */);
  901. const base::TimeDelta kFallbackPeriod = base::Minutes(5);
  902. DnsConfig config =
  903. CreateDnsConfig(0 /* num_servers */, 1 /* num_doh_servers */);
  904. config.fallback_period = kFallbackPeriod;
  905. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  906. context.InvalidateCachesAndPerSessionData(session.get(),
  907. false /* network_change */);
  908. base::TimeDelta expected =
  909. kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
  910. ASSERT_GT(expected, features::kDnsMinTransactionTimeout.Get());
  911. EXPECT_EQ(
  912. context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
  913. expected);
  914. }
  915. TEST_F(ResolveContextTest, SecureTransactionTimeout_LongRtt) {
  916. ResolveContext context(nullptr /* url_request_context */,
  917. false /* enable_caching */);
  918. DnsConfig config =
  919. CreateDnsConfig(0 /* num_servers */, 2 /* num_doh_servers */);
  920. config.fallback_period = base::TimeDelta();
  921. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  922. context.InvalidateCachesAndPerSessionData(session.get(),
  923. false /* network_change */);
  924. // Record long RTTs for only 1 server.
  925. for (int i = 0; i < 50; ++i) {
  926. context.RecordRtt(1u /* server_index */, true /* is_doh_server */,
  927. base::Minutes(10), OK, session.get());
  928. }
  929. // No expected change from recording RTT to single server because lowest
  930. // fallback period is used.
  931. EXPECT_EQ(
  932. context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
  933. features::kDnsMinTransactionTimeout.Get());
  934. // Record long RTTs for remaining server.
  935. for (int i = 0; i < 50; ++i) {
  936. context.RecordRtt(0u /* server_index */, true /* is_doh_server */,
  937. base::Minutes(10), OK, session.get());
  938. }
  939. // Expect longer timeouts.
  940. EXPECT_GT(
  941. context.SecureTransactionTimeout(SecureDnsMode::kSecure, session.get()),
  942. features::kDnsMinTransactionTimeout.Get());
  943. }
  944. TEST_F(ResolveContextTest, SecureTransactionTimeout_DifferentSession) {
  945. const base::TimeDelta kFallbackPeriod = base::Minutes(5);
  946. DnsConfig config1 =
  947. CreateDnsConfig(0 /* num_servers */, 1 /* num_doh_servers */);
  948. config1.fallback_period = kFallbackPeriod;
  949. scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
  950. DnsConfig config2 =
  951. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  952. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  953. ResolveContext context(nullptr /* url_request_context */,
  954. false /* enable_caching */);
  955. context.InvalidateCachesAndPerSessionData(session1.get(),
  956. true /* network_change */);
  957. // Confirm that if session data were used, the timeout would be higher than
  958. // the min.
  959. base::TimeDelta multiplier_expected =
  960. kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
  961. ASSERT_GT(multiplier_expected, features::kDnsMinTransactionTimeout.Get());
  962. // Expect timeout always minimum with wrong session.
  963. EXPECT_EQ(
  964. context.SecureTransactionTimeout(SecureDnsMode::kSecure, session2.get()),
  965. features::kDnsMinTransactionTimeout.Get());
  966. }
  967. // Expect minimum timeout will be used when fallback period is small.
  968. TEST_F(ResolveContextTest, ClassicTransactionTimeout_SmallFallbackPeriod) {
  969. ResolveContext context(nullptr /* url_request_context */,
  970. false /* enable_caching */);
  971. DnsConfig config =
  972. CreateDnsConfig(1 /* num_servers */, 0 /* num_doh_servers */);
  973. config.fallback_period = base::TimeDelta();
  974. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  975. context.InvalidateCachesAndPerSessionData(session.get(),
  976. false /* network_change */);
  977. EXPECT_EQ(context.ClassicTransactionTimeout(session.get()),
  978. features::kDnsMinTransactionTimeout.Get());
  979. }
  980. // Expect multiplier on fallback period to be used when larger than minimum
  981. // timeout.
  982. TEST_F(ResolveContextTest, ClassicTransactionTimeout_LongFallbackPeriod) {
  983. ResolveContext context(nullptr /* url_request_context */,
  984. false /* enable_caching */);
  985. const base::TimeDelta kFallbackPeriod = base::Minutes(5);
  986. DnsConfig config =
  987. CreateDnsConfig(1 /* num_servers */, 0 /* num_doh_servers */);
  988. config.fallback_period = kFallbackPeriod;
  989. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  990. context.InvalidateCachesAndPerSessionData(session.get(),
  991. false /* network_change */);
  992. base::TimeDelta expected =
  993. kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
  994. ASSERT_GT(expected, features::kDnsMinTransactionTimeout.Get());
  995. EXPECT_EQ(context.ClassicTransactionTimeout(session.get()), expected);
  996. }
  997. TEST_F(ResolveContextTest, ClassicTransactionTimeout_LongRtt) {
  998. ResolveContext context(nullptr /* url_request_context */,
  999. false /* enable_caching */);
  1000. DnsConfig config =
  1001. CreateDnsConfig(2 /* num_servers */, 0 /* num_doh_servers */);
  1002. config.fallback_period = base::TimeDelta();
  1003. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  1004. context.InvalidateCachesAndPerSessionData(session.get(),
  1005. false /* network_change */);
  1006. // Record long RTTs for only 1 server.
  1007. for (int i = 0; i < 50; ++i) {
  1008. context.RecordRtt(1u /* server_index */, false /* is_doh_server */,
  1009. base::Minutes(10), OK, session.get());
  1010. }
  1011. // No expected change from recording RTT to single server because lowest
  1012. // fallback period is used.
  1013. EXPECT_EQ(context.ClassicTransactionTimeout(session.get()),
  1014. features::kDnsMinTransactionTimeout.Get());
  1015. // Record long RTTs for remaining server.
  1016. for (int i = 0; i < 50; ++i) {
  1017. context.RecordRtt(0u /* server_index */, false /* is_doh_server */,
  1018. base::Minutes(10), OK, session.get());
  1019. }
  1020. // Expect longer timeouts.
  1021. EXPECT_GT(context.ClassicTransactionTimeout(session.get()),
  1022. features::kDnsMinTransactionTimeout.Get());
  1023. }
  1024. TEST_F(ResolveContextTest, ClassicTransactionTimeout_DifferentSession) {
  1025. const base::TimeDelta kFallbackPeriod = base::Minutes(5);
  1026. DnsConfig config1 =
  1027. CreateDnsConfig(1 /* num_servers */, 0 /* num_doh_servers */);
  1028. config1.fallback_period = kFallbackPeriod;
  1029. scoped_refptr<DnsSession> session1 = CreateDnsSession(config1);
  1030. DnsConfig config2 =
  1031. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  1032. scoped_refptr<DnsSession> session2 = CreateDnsSession(config2);
  1033. ResolveContext context(nullptr /* url_request_context */,
  1034. false /* enable_caching */);
  1035. context.InvalidateCachesAndPerSessionData(session1.get(),
  1036. true /* network_change */);
  1037. // Confirm that if session data were used, the timeout would be higher than
  1038. // the min. If timeout defaults are ever changed to break this assertion, then
  1039. // the expected wrong-session timeout could be the same as an actual
  1040. // from-session timeout, making this test seem to pass even if the behavior
  1041. // under test were broken.
  1042. base::TimeDelta multiplier_expected =
  1043. kFallbackPeriod * features::kDnsTransactionTimeoutMultiplier.Get();
  1044. ASSERT_GT(multiplier_expected, features::kDnsMinTransactionTimeout.Get());
  1045. // Expect timeout always minimum with wrong session.
  1046. EXPECT_EQ(context.ClassicTransactionTimeout(session2.get()),
  1047. features::kDnsMinTransactionTimeout.Get());
  1048. }
  1049. // Ensures that reported negative RTT values don't cause a crash. Regression
  1050. // test for https://crbug.com/753568.
  1051. TEST_F(ResolveContextTest, NegativeRtt) {
  1052. ResolveContext context(nullptr /* url_request_context */,
  1053. false /* enable_caching */);
  1054. DnsConfig config =
  1055. CreateDnsConfig(2 /* num_servers */, 2 /* num_doh_servers */);
  1056. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  1057. context.InvalidateCachesAndPerSessionData(session.get(),
  1058. false /* network_change */);
  1059. context.RecordRtt(0 /* server_index */, false /* is_doh_server */,
  1060. base::Milliseconds(-1), OK /* rv */, session.get());
  1061. context.RecordRtt(0 /* server_index */, true /* is_doh_server */,
  1062. base::Milliseconds(-1), OK /* rv */, session.get());
  1063. }
  1064. TEST_F(ResolveContextTest, SessionChange) {
  1065. ResolveContext context(nullptr /* url_request_context */,
  1066. false /* enable_caching */);
  1067. TestDohStatusObserver observer;
  1068. context.RegisterDohStatusObserver(&observer);
  1069. DnsConfig config =
  1070. CreateDnsConfig(2 /* num_servers */, 3 /* num_doh_servers */);
  1071. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  1072. context.InvalidateCachesAndPerSessionData(session.get(),
  1073. false /* network_change */);
  1074. EXPECT_EQ(observer.session_changes(), 1);
  1075. // Should get a server unavailable notification because there is >0 DoH
  1076. // servers that are reset on cache invalidation.
  1077. EXPECT_EQ(observer.server_unavailable_notifications(), 1);
  1078. context.UnregisterDohStatusObserver(&observer);
  1079. }
  1080. TEST_F(ResolveContextTest, SessionChange_NoSession) {
  1081. ResolveContext context(nullptr /* url_request_context */,
  1082. false /* enable_caching */);
  1083. TestDohStatusObserver observer;
  1084. context.RegisterDohStatusObserver(&observer);
  1085. context.InvalidateCachesAndPerSessionData(nullptr /* new_session */,
  1086. false /* network_change */);
  1087. EXPECT_EQ(observer.session_changes(), 1);
  1088. EXPECT_EQ(observer.server_unavailable_notifications(), 0);
  1089. context.UnregisterDohStatusObserver(&observer);
  1090. }
  1091. TEST_F(ResolveContextTest, SessionChange_NoDohServers) {
  1092. ResolveContext context(nullptr /* url_request_context */,
  1093. false /* enable_caching */);
  1094. TestDohStatusObserver observer;
  1095. context.RegisterDohStatusObserver(&observer);
  1096. DnsConfig config =
  1097. CreateDnsConfig(2 /* num_servers */, 0 /* num_doh_servers */);
  1098. scoped_refptr<DnsSession> session = CreateDnsSession(config);
  1099. context.InvalidateCachesAndPerSessionData(session.get(),
  1100. false /* network_change */);
  1101. EXPECT_EQ(observer.session_changes(), 1);
  1102. EXPECT_EQ(observer.server_unavailable_notifications(), 0);
  1103. context.UnregisterDohStatusObserver(&observer);
  1104. }
  1105. } // namespace
  1106. } // namespace net