1 // Copyright (c) 2012 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 
5 #include "net/http/http_server_properties.h"
6 
7 #include <memory>
8 #include <string>
9 #include <vector>
10 
11 #include "base/bind.h"
12 #include "base/check.h"
13 #include "base/feature_list.h"
14 #include "base/json/json_writer.h"
15 #include "base/run_loop.h"
16 #include "base/test/scoped_feature_list.h"
17 #include "base/test/simple_test_clock.h"
18 #include "base/test/task_environment.h"
19 #include "base/values.h"
20 #include "net/base/features.h"
21 #include "net/base/host_port_pair.h"
22 #include "net/base/ip_address.h"
23 #include "net/http/http_network_session.h"
24 #include "net/test/test_with_task_environment.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/gurl.h"
27 
28 namespace net {
29 
30 const base::TimeDelta BROKEN_ALT_SVC_EXPIRE_DELAYS[10] = {
31     base::TimeDelta::FromSeconds(300),   base::TimeDelta::FromSeconds(600),
32     base::TimeDelta::FromSeconds(1200),  base::TimeDelta::FromSeconds(2400),
33     base::TimeDelta::FromSeconds(4800),  base::TimeDelta::FromSeconds(9600),
34     base::TimeDelta::FromSeconds(19200), base::TimeDelta::FromSeconds(38400),
35     base::TimeDelta::FromSeconds(76800), base::TimeDelta::FromSeconds(153600),
36 };
37 
38 class HttpServerPropertiesPeer {
39  public:
AddBrokenAlternativeServiceWithExpirationTime(HttpServerProperties * impl,const AlternativeService & alternative_service,base::TimeTicks when,const NetworkIsolationKey network_isolation_key=NetworkIsolationKey ())40   static void AddBrokenAlternativeServiceWithExpirationTime(
41       HttpServerProperties* impl,
42       const AlternativeService& alternative_service,
43       base::TimeTicks when,
44       const NetworkIsolationKey network_isolation_key = NetworkIsolationKey()) {
45     BrokenAlternativeService broken_alternative_service(
46         alternative_service, network_isolation_key,
47         true /* use_network_isolation_key */);
48     BrokenAlternativeServiceList::iterator unused_it;
49     impl->broken_alternative_services_.AddToBrokenListAndMap(
50         broken_alternative_service, when, &unused_it);
51     auto it =
52         impl->broken_alternative_services_.recently_broken_alternative_services_
53             .Get(broken_alternative_service);
54     if (it == impl->broken_alternative_services_
55                   .recently_broken_alternative_services_.end()) {
56       impl->broken_alternative_services_.recently_broken_alternative_services_
57           .Put(broken_alternative_service, 1);
58     } else {
59       it->second++;
60     }
61   }
62 
ExpireBrokenAlternateProtocolMappings(HttpServerProperties * impl)63   static void ExpireBrokenAlternateProtocolMappings(
64       HttpServerProperties* impl) {
65     impl->broken_alternative_services_.ExpireBrokenAlternateProtocolMappings();
66   }
67 };
68 
69 namespace {
70 
71 // Creates a ServerInfoMapKey without a NetworkIsolationKey.
CreateSimpleKey(const url::SchemeHostPort & server)72 HttpServerProperties::ServerInfoMapKey CreateSimpleKey(
73     const url::SchemeHostPort& server) {
74   return HttpServerProperties::ServerInfoMapKey(
75       server, net::NetworkIsolationKey(),
76       false /* use_network_isolation_key */);
77 }
78 
79 class HttpServerPropertiesTest : public TestWithTaskEnvironment {
80  protected:
HttpServerPropertiesTest()81   HttpServerPropertiesTest()
82       : TestWithTaskEnvironment(
83             base::test::TaskEnvironment::TimeSource::MOCK_TIME),
84         test_tick_clock_(GetMockTickClock()),
85         impl_(nullptr /* pref_delegate */,
86               nullptr /* net_log */,
87               test_tick_clock_,
88               &test_clock_) {
89     // Set |test_clock_| to some random time.
90     test_clock_.Advance(base::TimeDelta::FromSeconds(12345));
91 
92     url::Origin origin1 = url::Origin::Create(GURL("https://foo.test/"));
93     network_isolation_key1_ = NetworkIsolationKey(origin1, origin1);
94     url::Origin origin2 = url::Origin::Create(GURL("https://bar.test/"));
95     network_isolation_key2_ = NetworkIsolationKey(origin2, origin2);
96   }
97 
HasAlternativeService(const url::SchemeHostPort & origin,const NetworkIsolationKey & network_isolation_key)98   bool HasAlternativeService(const url::SchemeHostPort& origin,
99                              const NetworkIsolationKey& network_isolation_key) {
100     const AlternativeServiceInfoVector alternative_service_info_vector =
101         impl_.GetAlternativeServiceInfos(origin, network_isolation_key);
102     return !alternative_service_info_vector.empty();
103   }
104 
SetAlternativeService(const url::SchemeHostPort & origin,const AlternativeService & alternative_service)105   void SetAlternativeService(const url::SchemeHostPort& origin,
106                              const AlternativeService& alternative_service) {
107     const base::Time expiration =
108         test_clock_.Now() + base::TimeDelta::FromDays(1);
109     if (alternative_service.protocol == kProtoQUIC) {
110       impl_.SetQuicAlternativeService(origin, NetworkIsolationKey(),
111                                       alternative_service, expiration,
112                                       DefaultSupportedQuicVersions());
113     } else {
114       impl_.SetHttp2AlternativeService(origin, NetworkIsolationKey(),
115                                        alternative_service, expiration);
116     }
117   }
118 
MarkBrokenAndLetExpireAlternativeServiceNTimes(const AlternativeService & alternative_service,int num_times)119   void MarkBrokenAndLetExpireAlternativeServiceNTimes(
120       const AlternativeService& alternative_service,
121       int num_times) {}
122 
123   const base::TickClock* test_tick_clock_;
124   base::SimpleTestClock test_clock_;
125 
126   // Two different non-empty network isolation keys for use in tests that need
127   // them.
128   NetworkIsolationKey network_isolation_key1_;
129   NetworkIsolationKey network_isolation_key2_;
130 
131   HttpServerProperties impl_;
132 };
133 
TEST_F(HttpServerPropertiesTest,SetSupportsSpdy)134 TEST_F(HttpServerPropertiesTest, SetSupportsSpdy) {
135   // Check spdy servers are correctly set with SchemeHostPort key.
136   url::SchemeHostPort https_www_server("https", "www.google.com", 443);
137   url::SchemeHostPort http_photo_server("http", "photos.google.com", 80);
138   url::SchemeHostPort https_mail_server("https", "mail.google.com", 443);
139   // Servers with port equal to default port in scheme will drop port components
140   // when calling Serialize().
141 
142   url::SchemeHostPort http_google_server("http", "www.google.com", 443);
143   url::SchemeHostPort https_photos_server("https", "photos.google.com", 443);
144   url::SchemeHostPort valid_google_server((GURL("https://www.google.com")));
145 
146   impl_.SetSupportsSpdy(https_www_server, NetworkIsolationKey(), true);
147   impl_.SetSupportsSpdy(http_photo_server, NetworkIsolationKey(), true);
148   impl_.SetSupportsSpdy(https_mail_server, NetworkIsolationKey(), false);
149   EXPECT_TRUE(impl_.GetSupportsSpdy(https_www_server, NetworkIsolationKey()));
150   EXPECT_TRUE(
151       impl_.SupportsRequestPriority(https_www_server, NetworkIsolationKey()));
152   EXPECT_TRUE(impl_.GetSupportsSpdy(http_photo_server, NetworkIsolationKey()));
153   EXPECT_TRUE(
154       impl_.SupportsRequestPriority(http_photo_server, NetworkIsolationKey()));
155   EXPECT_FALSE(impl_.GetSupportsSpdy(https_mail_server, NetworkIsolationKey()));
156   EXPECT_FALSE(
157       impl_.SupportsRequestPriority(https_mail_server, NetworkIsolationKey()));
158   EXPECT_FALSE(
159       impl_.GetSupportsSpdy(http_google_server, NetworkIsolationKey()));
160   EXPECT_FALSE(
161       impl_.SupportsRequestPriority(http_google_server, NetworkIsolationKey()));
162   EXPECT_FALSE(
163       impl_.GetSupportsSpdy(https_photos_server, NetworkIsolationKey()));
164   EXPECT_FALSE(impl_.SupportsRequestPriority(https_photos_server,
165                                              NetworkIsolationKey()));
166   EXPECT_TRUE(
167       impl_.GetSupportsSpdy(valid_google_server, NetworkIsolationKey()));
168   EXPECT_TRUE(impl_.SupportsRequestPriority(valid_google_server,
169                                             NetworkIsolationKey()));
170 
171   // Flip values of two servers.
172   impl_.SetSupportsSpdy(https_www_server, NetworkIsolationKey(), false);
173   impl_.SetSupportsSpdy(https_mail_server, NetworkIsolationKey(), true);
174   EXPECT_FALSE(impl_.GetSupportsSpdy(https_www_server, NetworkIsolationKey()));
175   EXPECT_FALSE(
176       impl_.SupportsRequestPriority(https_www_server, NetworkIsolationKey()));
177   EXPECT_TRUE(impl_.GetSupportsSpdy(https_mail_server, NetworkIsolationKey()));
178   EXPECT_TRUE(
179       impl_.SupportsRequestPriority(https_mail_server, NetworkIsolationKey()));
180 }
181 
TEST_F(HttpServerPropertiesTest,SetSupportsSpdyWebSockets)182 TEST_F(HttpServerPropertiesTest, SetSupportsSpdyWebSockets) {
183   // The https and wss servers should be treated as the same server, as should
184   // the http and ws servers.
185   url::SchemeHostPort https_server("https", "www.test.com", 443);
186   url::SchemeHostPort wss_server("wss", "www.test.com", 443);
187   url::SchemeHostPort http_server("http", "www.test.com", 443);
188   url::SchemeHostPort ws_server("ws", "www.test.com", 443);
189 
190   EXPECT_FALSE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
191   EXPECT_FALSE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
192   EXPECT_FALSE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
193   EXPECT_FALSE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));
194 
195   impl_.SetSupportsSpdy(wss_server, NetworkIsolationKey(), true);
196   EXPECT_TRUE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
197   EXPECT_TRUE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
198   EXPECT_FALSE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
199   EXPECT_FALSE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));
200 
201   impl_.SetSupportsSpdy(http_server, NetworkIsolationKey(), true);
202   EXPECT_TRUE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
203   EXPECT_TRUE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
204   EXPECT_TRUE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
205   EXPECT_TRUE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));
206 
207   impl_.SetSupportsSpdy(https_server, NetworkIsolationKey(), false);
208   EXPECT_FALSE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
209   EXPECT_FALSE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
210   EXPECT_TRUE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
211   EXPECT_TRUE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));
212 
213   impl_.SetSupportsSpdy(ws_server, NetworkIsolationKey(), false);
214   EXPECT_FALSE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
215   EXPECT_FALSE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
216   EXPECT_FALSE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
217   EXPECT_FALSE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));
218 }
219 
TEST_F(HttpServerPropertiesTest,SetSupportsSpdyWithNetworkIsolationKey)220 TEST_F(HttpServerPropertiesTest, SetSupportsSpdyWithNetworkIsolationKey) {
221   const url::SchemeHostPort kServer("https", "foo.test", 443);
222 
223   EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, network_isolation_key1_));
224   EXPECT_FALSE(impl_.SupportsRequestPriority(kServer, network_isolation_key1_));
225   EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, NetworkIsolationKey()));
226   EXPECT_FALSE(impl_.SupportsRequestPriority(kServer, NetworkIsolationKey()));
227 
228   // Without network isolation keys enabled for HttpServerProperties, passing in
229   // a NetworkIsolationKey should have no effect on behavior.
230   for (const auto& network_isolation_key_to_set :
231        {NetworkIsolationKey(), network_isolation_key1_}) {
232     impl_.SetSupportsSpdy(kServer, network_isolation_key_to_set, true);
233     EXPECT_TRUE(impl_.GetSupportsSpdy(kServer, network_isolation_key1_));
234     EXPECT_TRUE(
235         impl_.SupportsRequestPriority(kServer, network_isolation_key1_));
236     EXPECT_TRUE(impl_.GetSupportsSpdy(kServer, NetworkIsolationKey()));
237     EXPECT_TRUE(impl_.SupportsRequestPriority(kServer, NetworkIsolationKey()));
238 
239     impl_.SetSupportsSpdy(kServer, network_isolation_key_to_set, false);
240     EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, network_isolation_key1_));
241     EXPECT_FALSE(
242         impl_.SupportsRequestPriority(kServer, network_isolation_key1_));
243     EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, NetworkIsolationKey()));
244     EXPECT_FALSE(impl_.SupportsRequestPriority(kServer, NetworkIsolationKey()));
245   }
246 
247   // With network isolation keys enabled for HttpServerProperties, the
248   // NetworkIsolationKey argument should be respected.
249 
250   base::test::ScopedFeatureList feature_list;
251   feature_list.InitAndEnableFeature(
252       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
253   // Since HttpServerProperties caches the feature value, have to create a new
254   // one.
255   HttpServerProperties properties(nullptr /* pref_delegate */,
256                                   nullptr /* net_log */, test_tick_clock_,
257                                   &test_clock_);
258 
259   EXPECT_FALSE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
260   EXPECT_FALSE(
261       properties.SupportsRequestPriority(kServer, network_isolation_key1_));
262   EXPECT_FALSE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
263   EXPECT_FALSE(
264       properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));
265 
266   properties.SetSupportsSpdy(kServer, network_isolation_key1_, true);
267   EXPECT_TRUE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
268   EXPECT_TRUE(
269       properties.SupportsRequestPriority(kServer, network_isolation_key1_));
270   EXPECT_FALSE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
271   EXPECT_FALSE(
272       properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));
273 
274   properties.SetSupportsSpdy(kServer, NetworkIsolationKey(), true);
275   EXPECT_TRUE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
276   EXPECT_TRUE(
277       properties.SupportsRequestPriority(kServer, network_isolation_key1_));
278   EXPECT_TRUE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
279   EXPECT_TRUE(
280       properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));
281 
282   properties.SetSupportsSpdy(kServer, network_isolation_key1_, false);
283   EXPECT_FALSE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
284   EXPECT_FALSE(
285       properties.SupportsRequestPriority(kServer, network_isolation_key1_));
286   EXPECT_TRUE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
287   EXPECT_TRUE(
288       properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));
289 
290   properties.SetSupportsSpdy(kServer, NetworkIsolationKey(), false);
291   EXPECT_FALSE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
292   EXPECT_FALSE(
293       properties.SupportsRequestPriority(kServer, network_isolation_key1_));
294   EXPECT_FALSE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
295   EXPECT_FALSE(
296       properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));
297 }
298 
TEST_F(HttpServerPropertiesTest,LoadSupportsSpdy)299 TEST_F(HttpServerPropertiesTest, LoadSupportsSpdy) {
300   HttpServerProperties::ServerInfo supports_spdy;
301   supports_spdy.supports_spdy = true;
302   HttpServerProperties::ServerInfo no_spdy;
303   no_spdy.supports_spdy = false;
304 
305   url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
306   url::SchemeHostPort spdy_server_photos("https", "photos.google.com", 443);
307   url::SchemeHostPort spdy_server_docs("https", "docs.google.com", 443);
308   url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);
309 
310   // Check by initializing empty spdy servers.
311   std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers =
312       std::make_unique<HttpServerProperties::ServerInfoMap>();
313   impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers));
314   EXPECT_FALSE(
315       impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
316 
317   // Check by initializing www.google.com:443 and photos.google.com:443 as spdy
318   // servers.
319   std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers1 =
320       std::make_unique<HttpServerProperties::ServerInfoMap>();
321   spdy_servers1->Put(CreateSimpleKey(spdy_server_google), supports_spdy);
322   spdy_servers1->Put(CreateSimpleKey(spdy_server_photos), no_spdy);
323   impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers1));
324   // Note: these calls affect MRU order.
325   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
326   EXPECT_FALSE(
327       impl_.GetSupportsSpdy(spdy_server_photos, NetworkIsolationKey()));
328 
329   // Verify google and photos are in the list in MRU order.
330   ASSERT_EQ(2U, impl_.server_info_map_for_testing().size());
331   auto it = impl_.server_info_map_for_testing().begin();
332   EXPECT_EQ(spdy_server_photos, it->first.server);
333   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
334   ASSERT_TRUE(it->second.supports_spdy.has_value());
335   EXPECT_FALSE(*it->second.supports_spdy);
336   ++it;
337   EXPECT_EQ(spdy_server_google, it->first.server);
338   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
339   ASSERT_TRUE(it->second.supports_spdy.has_value());
340   EXPECT_TRUE(*it->second.supports_spdy);
341 
342   // Check by initializing mail.google.com:443 and docs.google.com:443.
343   std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers2 =
344       std::make_unique<HttpServerProperties::ServerInfoMap>();
345   spdy_servers2->Put(CreateSimpleKey(spdy_server_mail), supports_spdy);
346   spdy_servers2->Put(CreateSimpleKey(spdy_server_docs), supports_spdy);
347   impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers2));
348 
349   // Verify all the servers are in the list in MRU order. Note that
350   // OnServerInfoLoadedForTesting will put existing spdy server entries in
351   // front of newly added entries.
352   ASSERT_EQ(4U, impl_.server_info_map_for_testing().size());
353   it = impl_.server_info_map_for_testing().begin();
354   EXPECT_EQ(spdy_server_photos, it->first.server);
355   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
356   ASSERT_TRUE(it->second.supports_spdy.has_value());
357   EXPECT_FALSE(*it->second.supports_spdy);
358   ++it;
359   EXPECT_EQ(spdy_server_google, it->first.server);
360   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
361   ASSERT_TRUE(it->second.supports_spdy.has_value());
362   EXPECT_TRUE(*it->second.supports_spdy);
363   ++it;
364   EXPECT_EQ(spdy_server_docs, it->first.server);
365   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
366   ASSERT_TRUE(it->second.supports_spdy.has_value());
367   EXPECT_TRUE(*it->second.supports_spdy);
368   ++it;
369   EXPECT_EQ(spdy_server_mail, it->first.server);
370   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
371   ASSERT_TRUE(it->second.supports_spdy.has_value());
372   EXPECT_TRUE(*it->second.supports_spdy);
373 
374   // Check these in reverse MRU order so that MRU order stays the same.
375   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));
376   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_docs, NetworkIsolationKey()));
377   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
378   EXPECT_FALSE(
379       impl_.GetSupportsSpdy(spdy_server_photos, NetworkIsolationKey()));
380 
381   // Verify that old values loaded from disk take precedence over newer learned
382   // values and also verify the recency list order is unchanged.
383   std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers3 =
384       std::make_unique<HttpServerProperties::ServerInfoMap>();
385   spdy_servers3->Put(CreateSimpleKey(spdy_server_mail), no_spdy);
386   spdy_servers3->Put(CreateSimpleKey(spdy_server_photos), supports_spdy);
387   impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers3));
388 
389   // Verify the entries are in the same order.
390   ASSERT_EQ(4U, impl_.server_info_map_for_testing().size());
391   it = impl_.server_info_map_for_testing().begin();
392   EXPECT_EQ(spdy_server_photos, it->first.server);
393   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
394   ASSERT_TRUE(it->second.supports_spdy.has_value());
395   EXPECT_TRUE(*it->second.supports_spdy);
396   ++it;
397   EXPECT_EQ(spdy_server_google, it->first.server);
398   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
399   ASSERT_TRUE(it->second.supports_spdy.has_value());
400   EXPECT_TRUE(*it->second.supports_spdy);
401   ++it;
402   EXPECT_EQ(spdy_server_docs, it->first.server);
403   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
404   ASSERT_TRUE(it->second.supports_spdy.has_value());
405   EXPECT_TRUE(*it->second.supports_spdy);
406   ++it;
407   EXPECT_EQ(spdy_server_mail, it->first.server);
408   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
409   ASSERT_TRUE(it->second.supports_spdy.has_value());
410   EXPECT_FALSE(*it->second.supports_spdy);
411 
412   // Verify photos server doesn't support SPDY and other servers support SPDY.
413   EXPECT_FALSE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));
414   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_docs, NetworkIsolationKey()));
415   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
416   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_photos, NetworkIsolationKey()));
417 }
418 
TEST_F(HttpServerPropertiesTest,SupportsRequestPriority)419 TEST_F(HttpServerPropertiesTest, SupportsRequestPriority) {
420   url::SchemeHostPort spdy_server_empty("https", std::string(), 443);
421   EXPECT_FALSE(
422       impl_.SupportsRequestPriority(spdy_server_empty, NetworkIsolationKey()));
423 
424   // Add www.google.com:443 as supporting SPDY.
425   url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
426   impl_.SetSupportsSpdy(spdy_server_google, NetworkIsolationKey(), true);
427   EXPECT_TRUE(
428       impl_.SupportsRequestPriority(spdy_server_google, NetworkIsolationKey()));
429 
430   // Add mail.google.com:443 as not supporting SPDY.
431   url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);
432   EXPECT_FALSE(
433       impl_.SupportsRequestPriority(spdy_server_mail, NetworkIsolationKey()));
434 
435   // Add docs.google.com:443 as supporting SPDY.
436   url::SchemeHostPort spdy_server_docs("https", "docs.google.com", 443);
437   impl_.SetSupportsSpdy(spdy_server_docs, NetworkIsolationKey(), true);
438   EXPECT_TRUE(
439       impl_.SupportsRequestPriority(spdy_server_docs, NetworkIsolationKey()));
440 
441   // Add www.youtube.com:443 as supporting QUIC.
442   url::SchemeHostPort youtube_server("https", "www.youtube.com", 443);
443   const AlternativeService alternative_service1(kProtoQUIC, "www.youtube.com",
444                                                 443);
445   SetAlternativeService(youtube_server, alternative_service1);
446   EXPECT_TRUE(
447       impl_.SupportsRequestPriority(youtube_server, NetworkIsolationKey()));
448 
449   // Add www.example.com:443 with two alternative services, one supporting QUIC.
450   url::SchemeHostPort example_server("https", "www.example.com", 443);
451   const AlternativeService alternative_service2(kProtoHTTP2, "", 443);
452   SetAlternativeService(example_server, alternative_service2);
453   SetAlternativeService(example_server, alternative_service1);
454   EXPECT_TRUE(
455       impl_.SupportsRequestPriority(example_server, NetworkIsolationKey()));
456 
457   // Verify all the entries are the same after additions.
458   EXPECT_TRUE(
459       impl_.SupportsRequestPriority(spdy_server_google, NetworkIsolationKey()));
460   EXPECT_FALSE(
461       impl_.SupportsRequestPriority(spdy_server_mail, NetworkIsolationKey()));
462   EXPECT_TRUE(
463       impl_.SupportsRequestPriority(spdy_server_docs, NetworkIsolationKey()));
464   EXPECT_TRUE(
465       impl_.SupportsRequestPriority(youtube_server, NetworkIsolationKey()));
466   EXPECT_TRUE(
467       impl_.SupportsRequestPriority(example_server, NetworkIsolationKey()));
468 }
469 
TEST_F(HttpServerPropertiesTest,ClearSupportsSpdy)470 TEST_F(HttpServerPropertiesTest, ClearSupportsSpdy) {
471   // Add www.google.com:443 and mail.google.com:443 as supporting SPDY.
472   url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
473   impl_.SetSupportsSpdy(spdy_server_google, NetworkIsolationKey(), true);
474   url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);
475   impl_.SetSupportsSpdy(spdy_server_mail, NetworkIsolationKey(), true);
476 
477   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
478   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));
479 
480   base::RunLoop run_loop;
481   bool callback_invoked_ = false;
482   impl_.Clear(base::BindOnce(
483       [](bool* callback_invoked, base::OnceClosure quit_closure) {
484         *callback_invoked = true;
485         std::move(quit_closure).Run();
486       },
487       &callback_invoked_, run_loop.QuitClosure()));
488   EXPECT_FALSE(
489       impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
490   EXPECT_FALSE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));
491 
492   // Callback should be run asynchronously.
493   EXPECT_FALSE(callback_invoked_);
494   run_loop.Run();
495   EXPECT_TRUE(callback_invoked_);
496 }
497 
TEST_F(HttpServerPropertiesTest,MRUOfServerInfoMap)498 TEST_F(HttpServerPropertiesTest, MRUOfServerInfoMap) {
499   url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
500   url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);
501 
502   // Add www.google.com:443 as supporting SPDY.
503   impl_.SetSupportsSpdy(spdy_server_google, NetworkIsolationKey(), true);
504   ASSERT_EQ(1u, impl_.server_info_map_for_testing().size());
505   auto it = impl_.server_info_map_for_testing().begin();
506   ASSERT_EQ(spdy_server_google, it->first.server);
507   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
508 
509   // Add mail.google.com:443 as supporting SPDY. Verify mail.google.com:443 and
510   // www.google.com:443 are in the list.
511   impl_.SetSupportsSpdy(spdy_server_mail, NetworkIsolationKey(), true);
512   ASSERT_EQ(2u, impl_.server_info_map_for_testing().size());
513   it = impl_.server_info_map_for_testing().begin();
514   ASSERT_EQ(spdy_server_mail, it->first.server);
515   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
516   ++it;
517   ASSERT_EQ(spdy_server_google, it->first.server);
518   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
519 
520   // Get www.google.com:443. It should become the most-recently-used server.
521   EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
522   ASSERT_EQ(2u, impl_.server_info_map_for_testing().size());
523   it = impl_.server_info_map_for_testing().begin();
524   ASSERT_EQ(spdy_server_google, it->first.server);
525   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
526   ++it;
527   ASSERT_EQ(spdy_server_mail, it->first.server);
528   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
529 }
530 
531 typedef HttpServerPropertiesTest AlternateProtocolServerPropertiesTest;
532 
TEST_F(AlternateProtocolServerPropertiesTest,Basic)533 TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
534   url::SchemeHostPort test_server("http", "foo", 80);
535   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
536 
537   AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
538   SetAlternativeService(test_server, alternative_service);
539   const AlternativeServiceInfoVector alternative_service_info_vector =
540       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
541   ASSERT_EQ(1u, alternative_service_info_vector.size());
542   EXPECT_EQ(alternative_service,
543             alternative_service_info_vector[0].alternative_service());
544 
545   impl_.Clear(base::OnceClosure());
546   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
547 }
548 
TEST_F(AlternateProtocolServerPropertiesTest,ExcludeOrigin)549 TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) {
550   AlternativeServiceInfoVector alternative_service_info_vector;
551   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
552   // Same hostname, same port, TCP: should be ignored.
553   AlternativeServiceInfo alternative_service_info1 =
554       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
555           AlternativeService(kProtoHTTP2, "foo", 443), expiration);
556   alternative_service_info_vector.push_back(alternative_service_info1);
557   // Different hostname: GetAlternativeServiceInfos should return this one.
558   AlternativeServiceInfo alternative_service_info2 =
559       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
560           AlternativeService(kProtoHTTP2, "bar", 443), expiration);
561   alternative_service_info_vector.push_back(alternative_service_info2);
562   // Different port: GetAlternativeServiceInfos should return this one too.
563   AlternativeServiceInfo alternative_service_info3 =
564       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
565           AlternativeService(kProtoHTTP2, "foo", 80), expiration);
566   alternative_service_info_vector.push_back(alternative_service_info3);
567   // QUIC: GetAlternativeServices should return this one too.
568   AlternativeServiceInfo alternative_service_info4 =
569       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
570           AlternativeService(kProtoQUIC, "foo", 443), expiration,
571           DefaultSupportedQuicVersions());
572   alternative_service_info_vector.push_back(alternative_service_info4);
573 
574   url::SchemeHostPort test_server("https", "foo", 443);
575   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
576                                alternative_service_info_vector);
577 
578   const AlternativeServiceInfoVector alternative_service_info_vector2 =
579       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
580   ASSERT_EQ(3u, alternative_service_info_vector2.size());
581   EXPECT_EQ(alternative_service_info2, alternative_service_info_vector2[0]);
582   EXPECT_EQ(alternative_service_info3, alternative_service_info_vector2[1]);
583   EXPECT_EQ(alternative_service_info4, alternative_service_info_vector2[2]);
584 }
585 
TEST_F(AlternateProtocolServerPropertiesTest,Set)586 TEST_F(AlternateProtocolServerPropertiesTest, Set) {
587   // |test_server1| has an alternative service, which will not be
588   // affected by OnServerInfoLoadedForTesting(), because
589   // |server_info_map| does not have an entry for
590   // |test_server1|.
591   url::SchemeHostPort test_server1("http", "foo1", 80);
592   const AlternativeService alternative_service1(kProtoHTTP2, "bar1", 443);
593   const base::Time now = test_clock_.Now();
594   base::Time expiration1 = now + base::TimeDelta::FromDays(1);
595   // 1st entry in the memory.
596   impl_.SetHttp2AlternativeService(test_server1, NetworkIsolationKey(),
597                                    alternative_service1, expiration1);
598 
599   // |test_server2| has an alternative service, which will be
600   // overwritten by OnServerInfoLoadedForTesting(), because
601   // |server_info_map| has an entry for |test_server2|.
602   AlternativeServiceInfoVector alternative_service_info_vector;
603   const AlternativeService alternative_service2(kProtoHTTP2, "bar2", 443);
604   base::Time expiration2 = now + base::TimeDelta::FromDays(2);
605   alternative_service_info_vector.push_back(
606       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
607           alternative_service2, expiration2));
608   url::SchemeHostPort test_server2("http", "foo2", 80);
609   // 0th entry in the memory.
610   impl_.SetAlternativeServices(test_server2, NetworkIsolationKey(),
611                                alternative_service_info_vector);
612 
613   // Prepare |server_info_map| to be loaded by OnServerInfoLoadedForTesting().
614   std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
615       std::make_unique<HttpServerProperties::ServerInfoMap>();
616   const AlternativeService alternative_service3(kProtoHTTP2, "bar3", 123);
617   base::Time expiration3 = now + base::TimeDelta::FromDays(3);
618   const AlternativeServiceInfo alternative_service_info1 =
619       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
620           alternative_service3, expiration3);
621   // Simulate updating data for 0th entry with data from Preferences.
622   server_info_map->GetOrPut(CreateSimpleKey(test_server2))
623       ->second.alternative_services =
624       AlternativeServiceInfoVector(/*size=*/1, alternative_service_info1);
625 
626   url::SchemeHostPort test_server3("http", "foo3", 80);
627   const AlternativeService alternative_service4(kProtoHTTP2, "bar4", 1234);
628   base::Time expiration4 = now + base::TimeDelta::FromDays(4);
629   const AlternativeServiceInfo alternative_service_info2 =
630       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
631           alternative_service4, expiration4);
632   // Add an old entry from Preferences, this will be added to end of recency
633   // list.
634   server_info_map->GetOrPut(CreateSimpleKey(test_server3))
635       ->second.alternative_services =
636       AlternativeServiceInfoVector(/*size=*/1, alternative_service_info2);
637 
638   // MRU list will be test_server2, test_server1, test_server3.
639   impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));
640 
641   // Verify server_info_map.
642   const HttpServerProperties::ServerInfoMap& map =
643       impl_.server_info_map_for_testing();
644   ASSERT_EQ(3u, map.size());
645   auto map_it = map.begin();
646 
647   EXPECT_EQ(test_server2, map_it->first.server);
648   EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
649   ASSERT_TRUE(map_it->second.alternative_services.has_value());
650   const AlternativeServiceInfoVector* service_info =
651       &map_it->second.alternative_services.value();
652   ASSERT_EQ(1u, service_info->size());
653   EXPECT_EQ(alternative_service3, (*service_info)[0].alternative_service());
654   EXPECT_EQ(expiration3, (*service_info)[0].expiration());
655 
656   ++map_it;
657   EXPECT_EQ(test_server1, map_it->first.server);
658   EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
659   ASSERT_TRUE(map_it->second.alternative_services.has_value());
660   service_info = &map_it->second.alternative_services.value();
661   ASSERT_EQ(1u, service_info->size());
662   EXPECT_EQ(alternative_service1, (*service_info)[0].alternative_service());
663   EXPECT_EQ(expiration1, (*service_info)[0].expiration());
664 
665   ++map_it;
666   EXPECT_EQ(map_it->first.server, test_server3);
667   EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
668   ASSERT_TRUE(map_it->second.alternative_services.has_value());
669   service_info = &map_it->second.alternative_services.value();
670   ASSERT_EQ(1u, service_info->size());
671   EXPECT_EQ(alternative_service4, (*service_info)[0].alternative_service());
672   EXPECT_EQ(expiration4, (*service_info)[0].expiration());
673 }
674 
TEST_F(AlternateProtocolServerPropertiesTest,SetWebSockets)675 TEST_F(AlternateProtocolServerPropertiesTest, SetWebSockets) {
676   // The https and wss servers should be treated as the same server, as should
677   // the http and ws servers.
678   url::SchemeHostPort https_server("https", "www.test.com", 443);
679   url::SchemeHostPort wss_server("wss", "www.test.com", 443);
680   url::SchemeHostPort http_server("http", "www.test.com", 443);
681   url::SchemeHostPort ws_server("ws", "www.test.com", 443);
682 
683   AlternativeService alternative_service(kProtoHTTP2, "bar", 443);
684 
685   EXPECT_EQ(
686       0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
687               .size());
688   EXPECT_EQ(0u,
689             impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
690                 .size());
691   EXPECT_EQ(0u,
692             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
693                 .size());
694   EXPECT_EQ(0u,
695             impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
696                 .size());
697 
698   SetAlternativeService(wss_server, alternative_service);
699   EXPECT_EQ(
700       1u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
701               .size());
702   EXPECT_EQ(1u,
703             impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
704                 .size());
705   EXPECT_EQ(0u,
706             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
707                 .size());
708   EXPECT_EQ(0u,
709             impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
710                 .size());
711 
712   SetAlternativeService(http_server, alternative_service);
713   EXPECT_EQ(
714       1u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
715               .size());
716   EXPECT_EQ(1u,
717             impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
718                 .size());
719   EXPECT_EQ(1u,
720             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
721                 .size());
722   EXPECT_EQ(1u,
723             impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
724                 .size());
725 
726   impl_.SetAlternativeServices(https_server, NetworkIsolationKey(),
727                                AlternativeServiceInfoVector());
728   EXPECT_EQ(
729       0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
730               .size());
731   EXPECT_EQ(0u,
732             impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
733                 .size());
734   EXPECT_EQ(1u,
735             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
736                 .size());
737   EXPECT_EQ(1u,
738             impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
739                 .size());
740 
741   impl_.SetAlternativeServices(ws_server, NetworkIsolationKey(),
742                                AlternativeServiceInfoVector());
743   EXPECT_EQ(
744       0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
745               .size());
746   EXPECT_EQ(0u,
747             impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
748                 .size());
749   EXPECT_EQ(0u,
750             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
751                 .size());
752   EXPECT_EQ(0u,
753             impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
754                 .size());
755 }
756 
TEST_F(AlternateProtocolServerPropertiesTest,SetWithNetworkIsolationKey)757 TEST_F(AlternateProtocolServerPropertiesTest, SetWithNetworkIsolationKey) {
758   const url::SchemeHostPort kServer("https", "foo.test", 443);
759   const AlternativeServiceInfoVector kAlternativeServices(
760       {AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
761           AlternativeService(kProtoHTTP2, "foo", 443),
762           base::Time::Now() + base::TimeDelta::FromDays(1) /* expiration */)});
763 
764   EXPECT_TRUE(impl_.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
765                   .empty());
766   EXPECT_TRUE(
767       impl_.GetAlternativeServiceInfos(kServer, NetworkIsolationKey()).empty());
768 
769   // Without network isolation keys enabled for HttpServerProperties, passing in
770   // a NetworkIsolationKey should have no effect on behavior.
771   for (const auto& network_isolation_key_to_set :
772        {NetworkIsolationKey(), network_isolation_key1_}) {
773     impl_.SetAlternativeServices(kServer, network_isolation_key_to_set,
774                                  kAlternativeServices);
775     EXPECT_EQ(kAlternativeServices, impl_.GetAlternativeServiceInfos(
776                                         kServer, network_isolation_key1_));
777     EXPECT_EQ(kAlternativeServices,
778               impl_.GetAlternativeServiceInfos(kServer, NetworkIsolationKey()));
779 
780     impl_.SetAlternativeServices(kServer, network_isolation_key_to_set,
781                                  AlternativeServiceInfoVector());
782     EXPECT_TRUE(
783         impl_.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
784             .empty());
785     EXPECT_TRUE(impl_.GetAlternativeServiceInfos(kServer, NetworkIsolationKey())
786                     .empty());
787   }
788 
789   // Check that with network isolation keys enabled for HttpServerProperties,
790   // the NetworkIsolationKey argument is respected.
791 
792   base::test::ScopedFeatureList feature_list;
793   feature_list.InitAndEnableFeature(
794       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
795   // Since HttpServerProperties caches the feature value, have to create a new
796   // one.
797   HttpServerProperties properties(nullptr /* pref_delegate */,
798                                   nullptr /* net_log */, test_tick_clock_,
799                                   &test_clock_);
800 
801   properties.SetAlternativeServices(kServer, network_isolation_key1_,
802                                     kAlternativeServices);
803   EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
804                                       kServer, network_isolation_key1_));
805   EXPECT_TRUE(
806       properties.GetAlternativeServiceInfos(kServer, NetworkIsolationKey())
807           .empty());
808 
809   properties.SetAlternativeServices(kServer, NetworkIsolationKey(),
810                                     kAlternativeServices);
811   EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
812                                       kServer, network_isolation_key1_));
813   EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
814                                       kServer, NetworkIsolationKey()));
815 
816   properties.SetAlternativeServices(kServer, network_isolation_key1_,
817                                     AlternativeServiceInfoVector());
818   EXPECT_TRUE(
819       properties.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
820           .empty());
821   EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
822                                       kServer, NetworkIsolationKey()));
823 
824   properties.SetAlternativeServices(kServer, NetworkIsolationKey(),
825                                     AlternativeServiceInfoVector());
826   EXPECT_TRUE(
827       properties.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
828           .empty());
829   EXPECT_TRUE(
830       properties.GetAlternativeServiceInfos(kServer, NetworkIsolationKey())
831           .empty());
832 }
833 
834 // Regression test for https://crbug.com/504032:
835 // OnServerInfoLoadedForTesting() should not crash if there is an
836 // empty hostname is the mapping.
TEST_F(AlternateProtocolServerPropertiesTest,SetWithEmptyHostname)837 TEST_F(AlternateProtocolServerPropertiesTest, SetWithEmptyHostname) {
838   url::SchemeHostPort server("https", "foo", 443);
839   const AlternativeService alternative_service_with_empty_hostname(kProtoHTTP2,
840                                                                    "", 1234);
841   const AlternativeService alternative_service_with_foo_hostname(kProtoHTTP2,
842                                                                  "foo", 1234);
843   SetAlternativeService(server, alternative_service_with_empty_hostname);
844   impl_.MarkAlternativeServiceBroken(alternative_service_with_foo_hostname,
845                                      NetworkIsolationKey());
846 
847   std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
848       std::make_unique<HttpServerProperties::ServerInfoMap>();
849   impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));
850 
851   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(
852       alternative_service_with_foo_hostname, NetworkIsolationKey()));
853   const AlternativeServiceInfoVector alternative_service_info_vector =
854       impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey());
855   ASSERT_EQ(1u, alternative_service_info_vector.size());
856   EXPECT_EQ(alternative_service_with_foo_hostname,
857             alternative_service_info_vector[0].alternative_service());
858 }
859 
860 // Regression test for https://crbug.com/516486:
861 // GetAlternativeServiceInfos() should remove |server_info_map_|
862 // elements with empty value.
TEST_F(AlternateProtocolServerPropertiesTest,EmptyVector)863 TEST_F(AlternateProtocolServerPropertiesTest, EmptyVector) {
864   url::SchemeHostPort server("https", "foo", 443);
865   const AlternativeService alternative_service(kProtoHTTP2, "bar", 443);
866   base::Time expiration = test_clock_.Now() - base::TimeDelta::FromDays(1);
867   const AlternativeServiceInfo alternative_service_info =
868       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
869           alternative_service, expiration);
870   std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
871       std::make_unique<HttpServerProperties::ServerInfoMap>();
872   server_info_map->GetOrPut(CreateSimpleKey(server))
873       ->second.alternative_services = AlternativeServiceInfoVector(
874       /*size=*/1, alternative_service_info);
875 
876   // Prepare |server_info_map_| with a single key that has a single
877   // AlternativeServiceInfo with identical hostname and port.
878   impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));
879 
880   // GetAlternativeServiceInfos() should remove such AlternativeServiceInfo from
881   // |server_info_map_|, emptying the AlternativeServiceInfoVector
882   // corresponding to |server|.
883   ASSERT_TRUE(
884       impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());
885 
886   // GetAlternativeServiceInfos() should remove this key from
887   // |server_info_map_|, and SetAlternativeServices() should not crash.
888   impl_.SetAlternativeServices(
889       server, NetworkIsolationKey(),
890       AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));
891 
892   // There should still be no alternative service assigned to |server|.
893   ASSERT_TRUE(
894       impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());
895 }
896 
897 // Regression test for https://crbug.com/516486 for the canonical host case.
TEST_F(AlternateProtocolServerPropertiesTest,EmptyVectorForCanonical)898 TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) {
899   url::SchemeHostPort server("https", "foo.c.youtube.com", 443);
900   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
901   const AlternativeService alternative_service(kProtoHTTP2, "", 443);
902   base::Time expiration = test_clock_.Now() - base::TimeDelta::FromDays(1);
903   const AlternativeServiceInfo alternative_service_info =
904       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
905           alternative_service, expiration);
906   std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
907       std::make_unique<HttpServerProperties::ServerInfoMap>();
908   server_info_map->GetOrPut(CreateSimpleKey(canonical_server))
909       ->second.alternative_services =
910       AlternativeServiceInfoVector(/*size=*/1, alternative_service_info);
911 
912   // Prepare |server_info_map_| with a single key that has a single
913   // AlternativeServiceInfo with identical hostname and port.
914   impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));
915 
916   // GetAlternativeServiceInfos() should remove such AlternativeServiceInfo from
917   // |server_info_map_|, emptying the AlternativeServiceInfoVector
918   // corresponding to |canonical_server|, even when looking up
919   // alternative services for |server|.
920   ASSERT_TRUE(
921       impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());
922 
923   // GetAlternativeServiceInfos() should remove this key from
924   // |server_info_map_|, and SetAlternativeServices() should not crash.
925   impl_.SetAlternativeServices(
926       canonical_server, NetworkIsolationKey(),
927       AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));
928 
929   // There should still be no alternative service assigned to
930   // |canonical_server|.
931   ASSERT_TRUE(
932       impl_.GetAlternativeServiceInfos(canonical_server, NetworkIsolationKey())
933           .empty());
934 }
935 
TEST_F(AlternateProtocolServerPropertiesTest,ClearServerWithCanonical)936 TEST_F(AlternateProtocolServerPropertiesTest, ClearServerWithCanonical) {
937   url::SchemeHostPort server("https", "foo.c.youtube.com", 443);
938   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
939   const AlternativeService alternative_service(kProtoQUIC, "", 443);
940   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
941   const AlternativeServiceInfo alternative_service_info =
942       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
943           alternative_service, expiration, DefaultSupportedQuicVersions());
944 
945   impl_.SetAlternativeServices(
946       canonical_server, NetworkIsolationKey(),
947       AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));
948 
949   // Make sure the canonical service is returned for the other server.
950   const AlternativeServiceInfoVector alternative_service_info_vector =
951       impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey());
952   ASSERT_EQ(1u, alternative_service_info_vector.size());
953   EXPECT_EQ(kProtoQUIC,
954             alternative_service_info_vector[0].alternative_service().protocol);
955   EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);
956 
957   // Now clear the alternatives for the other server and make sure it stays
958   // cleared.
959   // GetAlternativeServices() should remove this key from
960   // |server_info_map_|, and SetAlternativeServices() should not crash.
961   impl_.SetAlternativeServices(server, NetworkIsolationKey(),
962                                AlternativeServiceInfoVector());
963 
964   ASSERT_TRUE(
965       impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());
966 }
967 
TEST_F(AlternateProtocolServerPropertiesTest,MRUOfGetAlternativeServiceInfos)968 TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServiceInfos) {
969   url::SchemeHostPort test_server1("http", "foo1", 80);
970   const AlternativeService alternative_service1(kProtoHTTP2, "foo1", 443);
971   SetAlternativeService(test_server1, alternative_service1);
972   url::SchemeHostPort test_server2("http", "foo2", 80);
973   const AlternativeService alternative_service2(kProtoHTTP2, "foo2", 1234);
974   SetAlternativeService(test_server2, alternative_service2);
975 
976   const HttpServerProperties::ServerInfoMap& map =
977       impl_.server_info_map_for_testing();
978   auto it = map.begin();
979   EXPECT_EQ(test_server2, it->first.server);
980   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
981   ASSERT_TRUE(it->second.alternative_services.has_value());
982   ASSERT_EQ(1u, it->second.alternative_services->size());
983   EXPECT_EQ(alternative_service2,
984             it->second.alternative_services.value()[0].alternative_service());
985 
986   const AlternativeServiceInfoVector alternative_service_info_vector =
987       impl_.GetAlternativeServiceInfos(test_server1, NetworkIsolationKey());
988   ASSERT_EQ(1u, alternative_service_info_vector.size());
989   EXPECT_EQ(alternative_service1,
990             alternative_service_info_vector[0].alternative_service());
991 
992   // GetAlternativeServices should reorder the AlternateProtocol map.
993   it = map.begin();
994   EXPECT_EQ(test_server1, it->first.server);
995   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
996   ASSERT_TRUE(it->second.alternative_services.has_value());
997   ASSERT_EQ(1u, it->second.alternative_services->size());
998   EXPECT_EQ(alternative_service1,
999             it->second.alternative_services.value()[0].alternative_service());
1000 }
1001 
TEST_F(AlternateProtocolServerPropertiesTest,SetBroken)1002 TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
1003   url::SchemeHostPort test_server("http", "foo", 80);
1004   const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
1005   SetAlternativeService(test_server, alternative_service1);
1006   AlternativeServiceInfoVector alternative_service_info_vector =
1007       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1008   ASSERT_EQ(1u, alternative_service_info_vector.size());
1009   EXPECT_EQ(alternative_service1,
1010             alternative_service_info_vector[0].alternative_service());
1011   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
1012                                                 NetworkIsolationKey()));
1013 
1014   // GetAlternativeServiceInfos should return the broken alternative service.
1015   impl_.MarkAlternativeServiceBroken(alternative_service1,
1016                                      NetworkIsolationKey());
1017   alternative_service_info_vector =
1018       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1019   ASSERT_EQ(1u, alternative_service_info_vector.size());
1020   EXPECT_EQ(alternative_service1,
1021             alternative_service_info_vector[0].alternative_service());
1022   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
1023                                                NetworkIsolationKey()));
1024 
1025   // SetAlternativeServices should add a broken alternative service to the map.
1026   AlternativeServiceInfoVector alternative_service_info_vector2;
1027   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
1028   alternative_service_info_vector2.push_back(
1029       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1030           alternative_service1, expiration));
1031   const AlternativeService alternative_service2(kProtoHTTP2, "foo", 1234);
1032   alternative_service_info_vector2.push_back(
1033       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1034           alternative_service2, expiration));
1035   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
1036                                alternative_service_info_vector2);
1037   alternative_service_info_vector =
1038       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1039   ASSERT_EQ(2u, alternative_service_info_vector.size());
1040   EXPECT_EQ(alternative_service1,
1041             alternative_service_info_vector[0].alternative_service());
1042   EXPECT_EQ(alternative_service2,
1043             alternative_service_info_vector[1].alternative_service());
1044   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
1045                                                NetworkIsolationKey()));
1046   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
1047                                                 NetworkIsolationKey()));
1048 
1049   // SetAlternativeService should add a broken alternative service to the map.
1050   SetAlternativeService(test_server, alternative_service1);
1051   alternative_service_info_vector =
1052       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1053   ASSERT_EQ(1u, alternative_service_info_vector.size());
1054   EXPECT_EQ(alternative_service1,
1055             alternative_service_info_vector[0].alternative_service());
1056   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
1057                                                NetworkIsolationKey()));
1058 }
1059 
TEST_F(AlternateProtocolServerPropertiesTest,SetBrokenUntilDefaultNetworkChanges)1060 TEST_F(AlternateProtocolServerPropertiesTest,
1061        SetBrokenUntilDefaultNetworkChanges) {
1062   url::SchemeHostPort test_server("http", "foo", 80);
1063   const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
1064   SetAlternativeService(test_server, alternative_service1);
1065   AlternativeServiceInfoVector alternative_service_info_vector =
1066       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1067   ASSERT_EQ(1u, alternative_service_info_vector.size());
1068   EXPECT_EQ(alternative_service1,
1069             alternative_service_info_vector[0].alternative_service());
1070   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
1071                                                 NetworkIsolationKey()));
1072 
1073   // Mark the alternative service as broken until the default network changes.
1074   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1075       alternative_service1, NetworkIsolationKey());
1076   // The alternative service should be persisted and marked as broken.
1077   alternative_service_info_vector =
1078       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1079   ASSERT_EQ(1u, alternative_service_info_vector.size());
1080   EXPECT_EQ(alternative_service1,
1081             alternative_service_info_vector[0].alternative_service());
1082   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
1083                                                NetworkIsolationKey()));
1084 
1085   // SetAlternativeServices should add a broken alternative service to the map.
1086   AlternativeServiceInfoVector alternative_service_info_vector2;
1087   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
1088   alternative_service_info_vector2.push_back(
1089       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1090           alternative_service1, expiration));
1091   const AlternativeService alternative_service2(kProtoHTTP2, "foo", 1234);
1092   alternative_service_info_vector2.push_back(
1093       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1094           alternative_service2, expiration));
1095   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
1096                                alternative_service_info_vector2);
1097   alternative_service_info_vector =
1098       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1099   ASSERT_EQ(2u, alternative_service_info_vector.size());
1100   EXPECT_EQ(alternative_service1,
1101             alternative_service_info_vector[0].alternative_service());
1102   EXPECT_EQ(alternative_service2,
1103             alternative_service_info_vector[1].alternative_service());
1104   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
1105                                                NetworkIsolationKey()));
1106   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
1107                                                 NetworkIsolationKey()));
1108 
1109   // SetAlternativeService should add a broken alternative service to the map.
1110   SetAlternativeService(test_server, alternative_service1);
1111   alternative_service_info_vector =
1112       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1113   ASSERT_EQ(1u, alternative_service_info_vector.size());
1114   EXPECT_EQ(alternative_service1,
1115             alternative_service_info_vector[0].alternative_service());
1116   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
1117                                                NetworkIsolationKey()));
1118 }
1119 
TEST_F(AlternateProtocolServerPropertiesTest,MaxAge)1120 TEST_F(AlternateProtocolServerPropertiesTest, MaxAge) {
1121   AlternativeServiceInfoVector alternative_service_info_vector;
1122   base::Time now = test_clock_.Now();
1123   base::TimeDelta one_day = base::TimeDelta::FromDays(1);
1124 
1125   // First alternative service expired one day ago, should not be returned by
1126   // GetAlternativeServiceInfos().
1127   const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
1128   alternative_service_info_vector.push_back(
1129       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1130           alternative_service1, now - one_day));
1131 
1132   // Second alterrnative service will expire one day from now, should be
1133   // returned by GetAlternativeSerices().
1134   const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
1135   alternative_service_info_vector.push_back(
1136       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1137           alternative_service2, now + one_day));
1138 
1139   url::SchemeHostPort test_server("http", "foo", 80);
1140   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
1141                                alternative_service_info_vector);
1142 
1143   AlternativeServiceInfoVector alternative_service_info_vector2 =
1144       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1145   ASSERT_EQ(1u, alternative_service_info_vector2.size());
1146   EXPECT_EQ(alternative_service2,
1147             alternative_service_info_vector2[0].alternative_service());
1148 }
1149 
TEST_F(AlternateProtocolServerPropertiesTest,MaxAgeCanonical)1150 TEST_F(AlternateProtocolServerPropertiesTest, MaxAgeCanonical) {
1151   AlternativeServiceInfoVector alternative_service_info_vector;
1152   base::Time now = test_clock_.Now();
1153   base::TimeDelta one_day = base::TimeDelta::FromDays(1);
1154 
1155   // First alternative service expired one day ago, should not be returned by
1156   // GetAlternativeServiceInfos().
1157   const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
1158   alternative_service_info_vector.push_back(
1159       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1160           alternative_service1, now - one_day));
1161 
1162   // Second alterrnative service will expire one day from now, should be
1163   // returned by GetAlternativeSerices().
1164   const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
1165   alternative_service_info_vector.push_back(
1166       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1167           alternative_service2, now + one_day));
1168 
1169   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
1170   impl_.SetAlternativeServices(canonical_server, NetworkIsolationKey(),
1171                                alternative_service_info_vector);
1172 
1173   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1174   AlternativeServiceInfoVector alternative_service_info_vector2 =
1175       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1176   ASSERT_EQ(1u, alternative_service_info_vector2.size());
1177   EXPECT_EQ(alternative_service2,
1178             alternative_service_info_vector2[0].alternative_service());
1179 }
1180 
TEST_F(AlternateProtocolServerPropertiesTest,AlternativeServiceWithScheme)1181 TEST_F(AlternateProtocolServerPropertiesTest, AlternativeServiceWithScheme) {
1182   AlternativeServiceInfoVector alternative_service_info_vector;
1183   const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
1184   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
1185   alternative_service_info_vector.push_back(
1186       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1187           alternative_service1, expiration));
1188   const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
1189   alternative_service_info_vector.push_back(
1190       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1191           alternative_service2, expiration));
1192   // Set Alt-Svc list for |http_server|.
1193   url::SchemeHostPort http_server("http", "foo", 80);
1194   impl_.SetAlternativeServices(http_server, NetworkIsolationKey(),
1195                                alternative_service_info_vector);
1196 
1197   const net::HttpServerProperties::ServerInfoMap& map =
1198       impl_.server_info_map_for_testing();
1199   auto it = map.begin();
1200   EXPECT_EQ(http_server, it->first.server);
1201   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
1202   ASSERT_TRUE(it->second.alternative_services.has_value());
1203   ASSERT_EQ(2u, it->second.alternative_services->size());
1204   EXPECT_EQ(alternative_service1,
1205             it->second.alternative_services.value()[0].alternative_service());
1206   EXPECT_EQ(alternative_service2,
1207             it->second.alternative_services.value()[1].alternative_service());
1208 
1209   // Check Alt-Svc list should not be set for |https_server|.
1210   url::SchemeHostPort https_server("https", "foo", 80);
1211   EXPECT_EQ(
1212       0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
1213               .size());
1214 
1215   // Set Alt-Svc list for |https_server|.
1216   impl_.SetAlternativeServices(https_server, NetworkIsolationKey(),
1217                                alternative_service_info_vector);
1218   EXPECT_EQ(
1219       2u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
1220               .size());
1221   EXPECT_EQ(2u,
1222             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
1223                 .size());
1224 
1225   // Clear Alt-Svc list for |http_server|.
1226   impl_.SetAlternativeServices(http_server, NetworkIsolationKey(),
1227                                AlternativeServiceInfoVector());
1228 
1229   EXPECT_EQ(0u,
1230             impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
1231                 .size());
1232   EXPECT_EQ(
1233       2u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
1234               .size());
1235 }
1236 
TEST_F(AlternateProtocolServerPropertiesTest,ClearAlternativeServices)1237 TEST_F(AlternateProtocolServerPropertiesTest, ClearAlternativeServices) {
1238   AlternativeServiceInfoVector alternative_service_info_vector;
1239   const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
1240   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
1241   alternative_service_info_vector.push_back(
1242       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1243           alternative_service1, expiration));
1244   const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
1245   alternative_service_info_vector.push_back(
1246       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1247           alternative_service2, expiration));
1248   url::SchemeHostPort test_server("http", "foo", 80);
1249   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
1250                                alternative_service_info_vector);
1251 
1252   const net::HttpServerProperties::ServerInfoMap& map =
1253       impl_.server_info_map_for_testing();
1254   auto it = map.begin();
1255   EXPECT_EQ(test_server, it->first.server);
1256   EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
1257   ASSERT_TRUE(it->second.alternative_services.has_value());
1258   ASSERT_EQ(2u, it->second.alternative_services->size());
1259   EXPECT_EQ(alternative_service1,
1260             it->second.alternative_services.value()[0].alternative_service());
1261   EXPECT_EQ(alternative_service2,
1262             it->second.alternative_services.value()[1].alternative_service());
1263 
1264   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
1265                                AlternativeServiceInfoVector());
1266   EXPECT_TRUE(map.empty());
1267 }
1268 
1269 // A broken alternative service in the mapping carries meaningful information,
1270 // therefore it should not be ignored by SetAlternativeService().  In
1271 // particular, an alternative service mapped to an origin shadows alternative
1272 // services of canonical hosts.
TEST_F(AlternateProtocolServerPropertiesTest,BrokenShadowsCanonical)1273 TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
1274   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1275   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
1276   AlternativeService canonical_alternative_service(kProtoQUIC,
1277                                                    "bar.c.youtube.com", 1234);
1278   SetAlternativeService(canonical_server, canonical_alternative_service);
1279   AlternativeServiceInfoVector alternative_service_info_vector =
1280       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1281   ASSERT_EQ(1u, alternative_service_info_vector.size());
1282   EXPECT_EQ(canonical_alternative_service,
1283             alternative_service_info_vector[0].alternative_service());
1284 
1285   const AlternativeService broken_alternative_service(kProtoHTTP2, "foo", 443);
1286   impl_.MarkAlternativeServiceBroken(broken_alternative_service,
1287                                      NetworkIsolationKey());
1288   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service,
1289                                                NetworkIsolationKey()));
1290 
1291   SetAlternativeService(test_server, broken_alternative_service);
1292   alternative_service_info_vector =
1293       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1294   ASSERT_EQ(1u, alternative_service_info_vector.size());
1295   EXPECT_EQ(broken_alternative_service,
1296             alternative_service_info_vector[0].alternative_service());
1297   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service,
1298                                                NetworkIsolationKey()));
1299 }
1300 
TEST_F(AlternateProtocolServerPropertiesTest,ClearBroken)1301 TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
1302   url::SchemeHostPort test_server("http", "foo", 80);
1303   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1304   SetAlternativeService(test_server, alternative_service);
1305   impl_.MarkAlternativeServiceBroken(alternative_service,
1306                                      NetworkIsolationKey());
1307   ASSERT_TRUE(HasAlternativeService(test_server, NetworkIsolationKey()));
1308   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1309                                                NetworkIsolationKey()));
1310   // SetAlternativeServices should leave a broken alternative service marked
1311   // as such.
1312   impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
1313                                AlternativeServiceInfoVector());
1314   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1315                                                NetworkIsolationKey()));
1316 }
1317 
TEST_F(AlternateProtocolServerPropertiesTest,MarkBrokenWithNetworkIsolationKey)1318 TEST_F(AlternateProtocolServerPropertiesTest,
1319        MarkBrokenWithNetworkIsolationKey) {
1320   url::SchemeHostPort server("http", "foo", 80);
1321   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1322   const base::Time expiration =
1323       test_clock_.Now() + base::TimeDelta::FromDays(1);
1324 
1325   // Without NetworkIsolationKeys enabled, the NetworkIsolationKey parameter
1326   // should be ignored.
1327   impl_.SetHttp2AlternativeService(server, network_isolation_key1_,
1328                                    alternative_service, expiration);
1329   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1330                                                 network_isolation_key1_));
1331   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1332       alternative_service, network_isolation_key1_));
1333   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1334                                                 network_isolation_key2_));
1335   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1336       alternative_service, network_isolation_key2_));
1337 
1338   impl_.MarkAlternativeServiceBroken(alternative_service,
1339                                      network_isolation_key1_);
1340   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1341                                                network_isolation_key1_));
1342   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
1343       alternative_service, network_isolation_key1_));
1344   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1345                                                network_isolation_key2_));
1346   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
1347       alternative_service, network_isolation_key2_));
1348 
1349   impl_.ConfirmAlternativeService(alternative_service, network_isolation_key2_);
1350   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1351                                                 network_isolation_key1_));
1352   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1353       alternative_service, network_isolation_key1_));
1354   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1355                                                 network_isolation_key2_));
1356   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1357       alternative_service, network_isolation_key2_));
1358 
1359   base::test::ScopedFeatureList feature_list;
1360   feature_list.InitAndEnableFeature(
1361       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
1362   // Since HttpServerProperties caches the feature value, have to create a new
1363   // one.
1364   HttpServerProperties properties(nullptr /* pref_delegate */,
1365                                   nullptr /* net_log */, test_tick_clock_,
1366                                   &test_clock_);
1367 
1368   properties.SetHttp2AlternativeService(server, network_isolation_key1_,
1369                                         alternative_service, expiration);
1370   properties.SetHttp2AlternativeService(server, network_isolation_key2_,
1371                                         alternative_service, expiration);
1372 
1373   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1374                                                      network_isolation_key1_));
1375   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1376       alternative_service, network_isolation_key1_));
1377   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1378                                                      network_isolation_key2_));
1379   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1380       alternative_service, network_isolation_key2_));
1381 
1382   properties.MarkAlternativeServiceBroken(alternative_service,
1383                                           network_isolation_key1_);
1384   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1385                                                     network_isolation_key1_));
1386   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1387       alternative_service, network_isolation_key1_));
1388   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1389                                                      network_isolation_key2_));
1390   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1391       alternative_service, network_isolation_key2_));
1392 
1393   properties.MarkAlternativeServiceBroken(alternative_service,
1394                                           network_isolation_key2_);
1395   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1396                                                     network_isolation_key1_));
1397   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1398       alternative_service, network_isolation_key1_));
1399   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1400                                                     network_isolation_key2_));
1401   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1402       alternative_service, network_isolation_key2_));
1403 
1404   properties.ConfirmAlternativeService(alternative_service,
1405                                        network_isolation_key1_);
1406   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1407                                                      network_isolation_key1_));
1408   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1409       alternative_service, network_isolation_key1_));
1410   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1411                                                     network_isolation_key2_));
1412   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1413       alternative_service, network_isolation_key2_));
1414 
1415   properties.ConfirmAlternativeService(alternative_service,
1416                                        network_isolation_key2_);
1417   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1418                                                      network_isolation_key1_));
1419   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1420       alternative_service, network_isolation_key1_));
1421   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1422                                                      network_isolation_key2_));
1423   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1424       alternative_service, network_isolation_key2_));
1425 }
1426 
TEST_F(AlternateProtocolServerPropertiesTest,MarkRecentlyBroken)1427 TEST_F(AlternateProtocolServerPropertiesTest, MarkRecentlyBroken) {
1428   url::SchemeHostPort server("http", "foo", 80);
1429   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1430   SetAlternativeService(server, alternative_service);
1431 
1432   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1433                                                 NetworkIsolationKey()));
1434   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1435       alternative_service, NetworkIsolationKey()));
1436 
1437   impl_.MarkAlternativeServiceRecentlyBroken(alternative_service,
1438                                              NetworkIsolationKey());
1439   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1440                                                 NetworkIsolationKey()));
1441   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1442                                                         NetworkIsolationKey()));
1443 
1444   impl_.ConfirmAlternativeService(alternative_service, NetworkIsolationKey());
1445   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1446                                                 NetworkIsolationKey()));
1447   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1448       alternative_service, NetworkIsolationKey()));
1449 }
1450 
TEST_F(AlternateProtocolServerPropertiesTest,MarkRecentlyBrokenWithNetworkIsolationKey)1451 TEST_F(AlternateProtocolServerPropertiesTest,
1452        MarkRecentlyBrokenWithNetworkIsolationKey) {
1453   url::SchemeHostPort server("http", "foo", 80);
1454   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1455   const base::Time expiration =
1456       test_clock_.Now() + base::TimeDelta::FromDays(1);
1457 
1458   // Without NetworkIsolationKeys enabled, the NetworkIsolationKey parameter
1459   // should be ignored.
1460   impl_.SetHttp2AlternativeService(server, network_isolation_key1_,
1461                                    alternative_service, expiration);
1462   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1463                                                 network_isolation_key1_));
1464   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1465       alternative_service, network_isolation_key1_));
1466   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1467                                                 network_isolation_key2_));
1468   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1469       alternative_service, network_isolation_key2_));
1470 
1471   impl_.MarkAlternativeServiceRecentlyBroken(alternative_service,
1472                                              network_isolation_key1_);
1473   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1474                                                 network_isolation_key1_));
1475   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
1476       alternative_service, network_isolation_key1_));
1477   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1478                                                 network_isolation_key2_));
1479   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
1480       alternative_service, network_isolation_key2_));
1481 
1482   impl_.ConfirmAlternativeService(alternative_service, network_isolation_key2_);
1483   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1484                                                 network_isolation_key1_));
1485   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1486       alternative_service, network_isolation_key1_));
1487   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1488                                                 network_isolation_key2_));
1489   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1490       alternative_service, network_isolation_key2_));
1491 
1492   base::test::ScopedFeatureList feature_list;
1493   feature_list.InitAndEnableFeature(
1494       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
1495   // Since HttpServerProperties caches the feature value, have to create a new
1496   // one.
1497   HttpServerProperties properties(nullptr /* pref_delegate */,
1498                                   nullptr /* net_log */, test_tick_clock_,
1499                                   &test_clock_);
1500 
1501   properties.SetHttp2AlternativeService(server, network_isolation_key1_,
1502                                         alternative_service, expiration);
1503   properties.SetHttp2AlternativeService(server, network_isolation_key2_,
1504                                         alternative_service, expiration);
1505   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1506                                                      network_isolation_key1_));
1507   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1508       alternative_service, network_isolation_key1_));
1509   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1510                                                      network_isolation_key2_));
1511   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1512       alternative_service, network_isolation_key2_));
1513 
1514   properties.MarkAlternativeServiceRecentlyBroken(alternative_service,
1515                                                   network_isolation_key1_);
1516   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1517                                                      network_isolation_key1_));
1518   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1519       alternative_service, network_isolation_key1_));
1520   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1521                                                      network_isolation_key2_));
1522   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1523       alternative_service, network_isolation_key2_));
1524 
1525   properties.MarkAlternativeServiceRecentlyBroken(alternative_service,
1526                                                   network_isolation_key2_);
1527   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1528                                                      network_isolation_key1_));
1529   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1530       alternative_service, network_isolation_key1_));
1531   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1532                                                      network_isolation_key2_));
1533   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1534       alternative_service, network_isolation_key2_));
1535 
1536   properties.ConfirmAlternativeService(alternative_service,
1537                                        network_isolation_key1_);
1538   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1539                                                      network_isolation_key1_));
1540   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1541       alternative_service, network_isolation_key1_));
1542   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1543                                                      network_isolation_key2_));
1544   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1545       alternative_service, network_isolation_key2_));
1546 
1547   properties.ConfirmAlternativeService(alternative_service,
1548                                        network_isolation_key2_);
1549   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1550                                                      network_isolation_key1_));
1551   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1552       alternative_service, network_isolation_key1_));
1553   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1554                                                      network_isolation_key2_));
1555   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1556       alternative_service, network_isolation_key2_));
1557 }
1558 
TEST_F(AlternateProtocolServerPropertiesTest,MarkBrokenUntilDefaultNetworkChanges)1559 TEST_F(AlternateProtocolServerPropertiesTest,
1560        MarkBrokenUntilDefaultNetworkChanges) {
1561   url::SchemeHostPort server("http", "foo", 80);
1562   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1563   SetAlternativeService(server, alternative_service);
1564 
1565   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1566                                                 NetworkIsolationKey()));
1567   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1568       alternative_service, NetworkIsolationKey()));
1569 
1570   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1571       alternative_service, NetworkIsolationKey());
1572   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1573                                                NetworkIsolationKey()));
1574   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1575                                                         NetworkIsolationKey()));
1576 
1577   impl_.ConfirmAlternativeService(alternative_service, NetworkIsolationKey());
1578   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1579                                                 NetworkIsolationKey()));
1580   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1581       alternative_service, NetworkIsolationKey()));
1582 }
1583 
TEST_F(AlternateProtocolServerPropertiesTest,MarkBrokenUntilDefaultNetworkChangesWithNetworkIsolationKey)1584 TEST_F(AlternateProtocolServerPropertiesTest,
1585        MarkBrokenUntilDefaultNetworkChangesWithNetworkIsolationKey) {
1586   url::SchemeHostPort server("http", "foo", 80);
1587   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1588   const base::Time expiration =
1589       test_clock_.Now() + base::TimeDelta::FromDays(1);
1590 
1591   // Without NetworkIsolationKeys enabled, the NetworkIsolationKey parameter
1592   // should be ignored.
1593   impl_.SetHttp2AlternativeService(server, network_isolation_key1_,
1594                                    alternative_service, expiration);
1595 
1596   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1597                                                 network_isolation_key1_));
1598   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1599       alternative_service, network_isolation_key1_));
1600   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1601                                                 network_isolation_key2_));
1602   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1603       alternative_service, network_isolation_key2_));
1604 
1605   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1606       alternative_service, network_isolation_key1_);
1607   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1608                                                network_isolation_key1_));
1609   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
1610       alternative_service, network_isolation_key1_));
1611   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1612                                                network_isolation_key2_));
1613   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
1614       alternative_service, network_isolation_key2_));
1615 
1616   impl_.ConfirmAlternativeService(alternative_service, network_isolation_key2_);
1617   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1618                                                 network_isolation_key1_));
1619   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1620       alternative_service, network_isolation_key1_));
1621   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1622                                                 network_isolation_key2_));
1623   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1624       alternative_service, network_isolation_key2_));
1625 
1626   base::test::ScopedFeatureList feature_list;
1627   feature_list.InitAndEnableFeature(
1628       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
1629   // Since HttpServerProperties caches the feature value, have to create a new
1630   // one.
1631   HttpServerProperties properties(nullptr /* pref_delegate */,
1632                                   nullptr /* net_log */, test_tick_clock_,
1633                                   &test_clock_);
1634 
1635   properties.SetHttp2AlternativeService(server, network_isolation_key1_,
1636                                         alternative_service, expiration);
1637   properties.SetHttp2AlternativeService(server, network_isolation_key2_,
1638                                         alternative_service, expiration);
1639 
1640   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1641                                                      network_isolation_key1_));
1642   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1643       alternative_service, network_isolation_key1_));
1644   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1645                                                      network_isolation_key2_));
1646   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1647       alternative_service, network_isolation_key2_));
1648 
1649   properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1650       alternative_service, network_isolation_key1_);
1651   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1652                                                     network_isolation_key1_));
1653   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1654       alternative_service, network_isolation_key1_));
1655   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1656                                                      network_isolation_key2_));
1657   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1658       alternative_service, network_isolation_key2_));
1659 
1660   properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1661       alternative_service, network_isolation_key2_);
1662   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1663                                                     network_isolation_key1_));
1664   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1665       alternative_service, network_isolation_key1_));
1666   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1667                                                     network_isolation_key2_));
1668   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1669       alternative_service, network_isolation_key2_));
1670 
1671   properties.ConfirmAlternativeService(alternative_service,
1672                                        network_isolation_key1_);
1673   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1674                                                      network_isolation_key1_));
1675   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1676       alternative_service, network_isolation_key1_));
1677   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1678                                                     network_isolation_key2_));
1679   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1680       alternative_service, network_isolation_key2_));
1681 
1682   properties.ConfirmAlternativeService(alternative_service,
1683                                        network_isolation_key2_);
1684   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1685                                                      network_isolation_key1_));
1686   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1687       alternative_service, network_isolation_key1_));
1688   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1689                                                      network_isolation_key2_));
1690   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1691       alternative_service, network_isolation_key2_));
1692 }
1693 
TEST_F(AlternateProtocolServerPropertiesTest,OnDefaultNetworkChanged)1694 TEST_F(AlternateProtocolServerPropertiesTest, OnDefaultNetworkChanged) {
1695   url::SchemeHostPort server("http", "foo", 80);
1696   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1697 
1698   SetAlternativeService(server, alternative_service);
1699   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1700                                                 NetworkIsolationKey()));
1701   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1702       alternative_service, NetworkIsolationKey()));
1703 
1704   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1705       alternative_service, NetworkIsolationKey());
1706   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1707                                                NetworkIsolationKey()));
1708   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1709                                                         NetworkIsolationKey()));
1710 
1711   // Default network change clears alt svc broken until default network changes.
1712   impl_.OnDefaultNetworkChanged();
1713   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1714                                                 NetworkIsolationKey()));
1715   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1716       alternative_service, NetworkIsolationKey()));
1717 
1718   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1719       alternative_service, NetworkIsolationKey());
1720   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1721                                                NetworkIsolationKey()));
1722   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1723                                                         NetworkIsolationKey()));
1724 
1725   impl_.MarkAlternativeServiceBroken(alternative_service,
1726                                      NetworkIsolationKey());
1727   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1728                                                NetworkIsolationKey()));
1729   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1730                                                         NetworkIsolationKey()));
1731 
1732   // Default network change doesn't affect alt svc that was simply marked broken
1733   // most recently.
1734   impl_.OnDefaultNetworkChanged();
1735   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1736                                                NetworkIsolationKey()));
1737   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1738                                                         NetworkIsolationKey()));
1739 
1740   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1741       alternative_service, NetworkIsolationKey());
1742   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
1743                                                NetworkIsolationKey()));
1744   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
1745                                                         NetworkIsolationKey()));
1746 
1747   // Default network change clears alt svc that was marked broken until default
1748   // network change most recently even if the alt svc was initially marked
1749   // broken.
1750   impl_.OnDefaultNetworkChanged();
1751   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
1752                                                 NetworkIsolationKey()));
1753   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
1754       alternative_service, NetworkIsolationKey()));
1755 }
1756 
TEST_F(AlternateProtocolServerPropertiesTest,OnDefaultNetworkChangedWithNetworkIsolationKey)1757 TEST_F(AlternateProtocolServerPropertiesTest,
1758        OnDefaultNetworkChangedWithNetworkIsolationKey) {
1759   url::SchemeHostPort server("http", "foo", 80);
1760   const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
1761 
1762   base::test::ScopedFeatureList feature_list;
1763   feature_list.InitAndEnableFeature(
1764       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
1765   // Since HttpServerProperties caches the feature value, have to create a new
1766   // one.
1767   HttpServerProperties properties(nullptr /* pref_delegate */,
1768                                   nullptr /* net_log */, test_tick_clock_,
1769                                   &test_clock_);
1770 
1771   const base::Time expiration =
1772       test_clock_.Now() + base::TimeDelta::FromDays(1);
1773   properties.SetHttp2AlternativeService(server, network_isolation_key1_,
1774                                         alternative_service, expiration);
1775   properties.SetHttp2AlternativeService(server, network_isolation_key2_,
1776                                         alternative_service, expiration);
1777 
1778   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1779                                                      network_isolation_key1_));
1780   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1781       alternative_service, network_isolation_key1_));
1782   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1783                                                      network_isolation_key2_));
1784   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1785       alternative_service, network_isolation_key2_));
1786 
1787   properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1788       alternative_service, network_isolation_key1_);
1789   properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1790       alternative_service, network_isolation_key2_);
1791   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1792                                                     network_isolation_key1_));
1793   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1794       alternative_service, network_isolation_key1_));
1795   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
1796                                                     network_isolation_key2_));
1797   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
1798       alternative_service, network_isolation_key2_));
1799 
1800   // Default network change clears alt svc broken until default network changes.
1801   properties.OnDefaultNetworkChanged();
1802   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1803                                                      network_isolation_key1_));
1804   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1805       alternative_service, network_isolation_key1_));
1806   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
1807                                                      network_isolation_key2_));
1808   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
1809       alternative_service, network_isolation_key2_));
1810 }
1811 
TEST_F(AlternateProtocolServerPropertiesTest,Canonical)1812 TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
1813   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1814   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
1815 
1816   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
1817   EXPECT_FALSE(HasAlternativeService(canonical_server, NetworkIsolationKey()));
1818 
1819   AlternativeServiceInfoVector alternative_service_info_vector;
1820   const AlternativeService canonical_alternative_service1(
1821       kProtoQUIC, "bar.c.youtube.com", 1234);
1822   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
1823   alternative_service_info_vector.push_back(
1824       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
1825           canonical_alternative_service1, expiration,
1826           DefaultSupportedQuicVersions()));
1827   const AlternativeService canonical_alternative_service2(kProtoHTTP2, "", 443);
1828   alternative_service_info_vector.push_back(
1829       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1830           canonical_alternative_service2, expiration));
1831   impl_.SetAlternativeServices(canonical_server, NetworkIsolationKey(),
1832                                alternative_service_info_vector);
1833 
1834   // Since |test_server| does not have an alternative service itself,
1835   // GetAlternativeServiceInfos should return those of |canonical_server|.
1836   AlternativeServiceInfoVector alternative_service_info_vector2 =
1837       impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
1838   ASSERT_EQ(2u, alternative_service_info_vector2.size());
1839   EXPECT_EQ(canonical_alternative_service1,
1840             alternative_service_info_vector2[0].alternative_service());
1841 
1842   // Since |canonical_alternative_service2| has an empty host,
1843   // GetAlternativeServiceInfos should substitute the hostname of its |origin|
1844   // argument.
1845   EXPECT_EQ(test_server.host(),
1846             alternative_service_info_vector2[1].alternative_service().host);
1847   EXPECT_EQ(canonical_alternative_service2.protocol,
1848             alternative_service_info_vector2[1].alternative_service().protocol);
1849   EXPECT_EQ(canonical_alternative_service2.port,
1850             alternative_service_info_vector2[1].alternative_service().port);
1851 
1852   // Verify the canonical suffix.
1853   EXPECT_EQ(".c.youtube.com",
1854             *impl_.GetCanonicalSuffixForTesting(test_server.host()));
1855   EXPECT_EQ(".c.youtube.com",
1856             *impl_.GetCanonicalSuffixForTesting(canonical_server.host()));
1857 }
1858 
TEST_F(AlternateProtocolServerPropertiesTest,ClearCanonical)1859 TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
1860   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1861   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
1862   AlternativeService canonical_alternative_service(kProtoQUIC,
1863                                                    "bar.c.youtube.com", 1234);
1864 
1865   SetAlternativeService(canonical_server, canonical_alternative_service);
1866   impl_.SetAlternativeServices(canonical_server, NetworkIsolationKey(),
1867                                AlternativeServiceInfoVector());
1868   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
1869 }
1870 
TEST_F(AlternateProtocolServerPropertiesTest,CanonicalWithNetworkIsolationKey)1871 TEST_F(AlternateProtocolServerPropertiesTest,
1872        CanonicalWithNetworkIsolationKey) {
1873   base::test::ScopedFeatureList feature_list;
1874   feature_list.InitAndEnableFeature(
1875       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
1876   // Since HttpServerProperties caches the feature value, have to create a new
1877   // one.
1878   HttpServerProperties properties(nullptr /* pref_delegate */,
1879                                   nullptr /* net_log */, test_tick_clock_,
1880                                   &test_clock_);
1881 
1882   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1883   EXPECT_FALSE(HasAlternativeService(test_server, network_isolation_key1_));
1884 
1885   url::SchemeHostPort canonical_server1("https", "bar.c.youtube.com", 443);
1886   EXPECT_FALSE(
1887       HasAlternativeService(canonical_server1, network_isolation_key1_));
1888 
1889   AlternativeServiceInfoVector alternative_service_info_vector;
1890   const AlternativeService canonical_alternative_service1(
1891       kProtoQUIC, "bar.c.youtube.com", 1234);
1892   base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
1893   alternative_service_info_vector.push_back(
1894       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
1895           canonical_alternative_service1, expiration,
1896           DefaultSupportedQuicVersions()));
1897   const AlternativeService canonical_alternative_service2(kProtoHTTP2, "", 443);
1898   alternative_service_info_vector.push_back(
1899       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
1900           canonical_alternative_service2, expiration));
1901   properties.SetAlternativeServices(canonical_server1, network_isolation_key1_,
1902                                     alternative_service_info_vector);
1903 
1904   // Since |test_server| does not have an alternative service itself,
1905   // GetAlternativeServiceInfos should return those of |canonical_server|.
1906   AlternativeServiceInfoVector alternative_service_info_vector2 =
1907       properties.GetAlternativeServiceInfos(test_server,
1908                                             network_isolation_key1_);
1909   ASSERT_EQ(2u, alternative_service_info_vector2.size());
1910   EXPECT_EQ(canonical_alternative_service1,
1911             alternative_service_info_vector2[0].alternative_service());
1912 
1913   // Canonical information should not be visible for other NetworkIsolationKeys.
1914   EXPECT_TRUE(
1915       properties
1916           .GetAlternativeServiceInfos(test_server, network_isolation_key2_)
1917           .empty());
1918   EXPECT_TRUE(
1919       properties.GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
1920           .empty());
1921 
1922   // Now add an alternative service entry for network_isolation_key2_ for a
1923   // different server and different NetworkIsolationKey, but with the same
1924   // canonical suffix.
1925   url::SchemeHostPort canonical_server2("https", "shrimp.c.youtube.com", 443);
1926   properties.SetAlternativeServices(canonical_server2, network_isolation_key2_,
1927                                     {alternative_service_info_vector[0]});
1928 
1929   // The canonical server information should reachable, and different, for both
1930   // NetworkIsolationKeys.
1931   EXPECT_EQ(
1932       1u, properties
1933               .GetAlternativeServiceInfos(test_server, network_isolation_key2_)
1934               .size());
1935   EXPECT_EQ(
1936       2u, properties
1937               .GetAlternativeServiceInfos(test_server, network_isolation_key1_)
1938               .size());
1939   EXPECT_TRUE(
1940       properties.GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
1941           .empty());
1942 
1943   // Clearing the alternate service state of network_isolation_key1_'s canonical
1944   // server should only affect network_isolation_key1_.
1945   properties.SetAlternativeServices(canonical_server1, network_isolation_key1_,
1946                                     {});
1947   EXPECT_EQ(
1948       1u, properties
1949               .GetAlternativeServiceInfos(test_server, network_isolation_key2_)
1950               .size());
1951   EXPECT_TRUE(
1952       properties
1953           .GetAlternativeServiceInfos(test_server, network_isolation_key1_)
1954           .empty());
1955   EXPECT_TRUE(
1956       properties.GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
1957           .empty());
1958 }
1959 
TEST_F(AlternateProtocolServerPropertiesTest,CanonicalBroken)1960 TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) {
1961   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1962   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
1963   AlternativeService canonical_alternative_service(kProtoQUIC,
1964                                                    "bar.c.youtube.com", 1234);
1965 
1966   SetAlternativeService(canonical_server, canonical_alternative_service);
1967   EXPECT_TRUE(HasAlternativeService(test_server, NetworkIsolationKey()));
1968   impl_.MarkAlternativeServiceBroken(canonical_alternative_service,
1969                                      NetworkIsolationKey());
1970   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
1971 }
1972 
TEST_F(AlternateProtocolServerPropertiesTest,CanonicalBrokenUntilDefaultNetworkChanges)1973 TEST_F(AlternateProtocolServerPropertiesTest,
1974        CanonicalBrokenUntilDefaultNetworkChanges) {
1975   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
1976   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
1977   AlternativeService canonical_alternative_service(kProtoQUIC,
1978                                                    "bar.c.youtube.com", 1234);
1979 
1980   SetAlternativeService(canonical_server, canonical_alternative_service);
1981   EXPECT_TRUE(HasAlternativeService(test_server, NetworkIsolationKey()));
1982   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
1983       canonical_alternative_service, NetworkIsolationKey());
1984   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
1985 }
1986 
1987 // Adding an alternative service for a new host overrides canonical host.
TEST_F(AlternateProtocolServerPropertiesTest,CanonicalOverride)1988 TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) {
1989   url::SchemeHostPort foo_server("https", "foo.c.youtube.com", 443);
1990   url::SchemeHostPort bar_server("https", "bar.c.youtube.com", 443);
1991   AlternativeService bar_alternative_service(kProtoQUIC, "bar.c.youtube.com",
1992                                              1234);
1993   SetAlternativeService(bar_server, bar_alternative_service);
1994   AlternativeServiceInfoVector alternative_service_info_vector =
1995       impl_.GetAlternativeServiceInfos(foo_server, NetworkIsolationKey());
1996   ASSERT_EQ(1u, alternative_service_info_vector.size());
1997   EXPECT_EQ(bar_alternative_service,
1998             alternative_service_info_vector[0].alternative_service());
1999 
2000   url::SchemeHostPort qux_server("https", "qux.c.youtube.com", 443);
2001   AlternativeService qux_alternative_service(kProtoQUIC, "qux.c.youtube.com",
2002                                              443);
2003   SetAlternativeService(qux_server, qux_alternative_service);
2004   alternative_service_info_vector =
2005       impl_.GetAlternativeServiceInfos(foo_server, NetworkIsolationKey());
2006   ASSERT_EQ(1u, alternative_service_info_vector.size());
2007   EXPECT_EQ(qux_alternative_service,
2008             alternative_service_info_vector[0].alternative_service());
2009 }
2010 
TEST_F(AlternateProtocolServerPropertiesTest,ClearWithCanonical)2011 TEST_F(AlternateProtocolServerPropertiesTest, ClearWithCanonical) {
2012   url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
2013   url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
2014   AlternativeService canonical_alternative_service(kProtoQUIC,
2015                                                    "bar.c.youtube.com", 1234);
2016 
2017   SetAlternativeService(canonical_server, canonical_alternative_service);
2018   impl_.Clear(base::OnceClosure());
2019   EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
2020 }
2021 
TEST_F(AlternateProtocolServerPropertiesTest,ExpireBrokenAlternateProtocolMappings)2022 TEST_F(AlternateProtocolServerPropertiesTest,
2023        ExpireBrokenAlternateProtocolMappings) {
2024   url::SchemeHostPort server("https", "foo", 443);
2025   AlternativeService alternative_service(kProtoQUIC, "foo", 443);
2026   SetAlternativeService(server, alternative_service);
2027   EXPECT_TRUE(HasAlternativeService(server, NetworkIsolationKey()));
2028   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
2029                                                 NetworkIsolationKey()));
2030   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
2031       alternative_service, NetworkIsolationKey()));
2032 
2033   base::TimeTicks past =
2034       test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
2035   HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
2036       &impl_, alternative_service, past);
2037   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
2038                                                NetworkIsolationKey()));
2039   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
2040                                                         NetworkIsolationKey()));
2041 
2042   HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&impl_);
2043   EXPECT_FALSE(HasAlternativeService(server, NetworkIsolationKey()));
2044   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
2045                                                 NetworkIsolationKey()));
2046   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
2047                                                         NetworkIsolationKey()));
2048 }
2049 
TEST_F(AlternateProtocolServerPropertiesTest,ExpireBrokenAlternateProtocolMappingsWithNetworkIsolationKey)2050 TEST_F(AlternateProtocolServerPropertiesTest,
2051        ExpireBrokenAlternateProtocolMappingsWithNetworkIsolationKey) {
2052   url::SchemeHostPort server("https", "foo", 443);
2053   AlternativeService alternative_service(kProtoHTTP2, "foo", 444);
2054   base::TimeTicks past =
2055       test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
2056   base::TimeTicks future =
2057       test_tick_clock_->NowTicks() + base::TimeDelta::FromSeconds(42);
2058   const base::Time alt_service_expiration =
2059       test_clock_.Now() + base::TimeDelta::FromDays(1);
2060 
2061   base::test::ScopedFeatureList feature_list;
2062   feature_list.InitAndEnableFeature(
2063       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
2064   // Since HttpServerProperties caches the feature value, have to create a new
2065   // one.
2066   HttpServerProperties properties(nullptr /* pref_delegate */,
2067                                   nullptr /* net_log */, test_tick_clock_,
2068                                   &test_clock_);
2069 
2070   properties.SetHttp2AlternativeService(server, network_isolation_key1_,
2071                                         alternative_service,
2072                                         alt_service_expiration);
2073   properties.SetHttp2AlternativeService(server, network_isolation_key2_,
2074                                         alternative_service,
2075                                         alt_service_expiration);
2076 
2077   EXPECT_FALSE(
2078       properties.GetAlternativeServiceInfos(server, network_isolation_key1_)
2079           .empty());
2080   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
2081                                                      network_isolation_key1_));
2082   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
2083       alternative_service, network_isolation_key1_));
2084   EXPECT_FALSE(
2085       properties.GetAlternativeServiceInfos(server, network_isolation_key2_)
2086           .empty());
2087   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
2088                                                      network_isolation_key2_));
2089   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
2090       alternative_service, network_isolation_key2_));
2091 
2092   // Set broken alternative service with expiration date in the past for
2093   // |network_isolation_key1_|.
2094   HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
2095       &properties, alternative_service, past, network_isolation_key1_);
2096   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
2097                                                     network_isolation_key1_));
2098   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
2099       alternative_service, network_isolation_key1_));
2100   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
2101                                                      network_isolation_key2_));
2102   EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
2103       alternative_service, network_isolation_key2_));
2104 
2105   // Set broken alternative service with expiration date in the future for
2106   // |network_isolation_key1_|.
2107   HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
2108       &properties, alternative_service, future, network_isolation_key2_);
2109   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
2110                                                     network_isolation_key1_));
2111   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
2112       alternative_service, network_isolation_key1_));
2113   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
2114                                                     network_isolation_key2_));
2115   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
2116       alternative_service, network_isolation_key2_));
2117 
2118   // Only the broken entry for |network_isolation_key1_| should be expired.
2119   HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&properties);
2120   EXPECT_TRUE(
2121       properties.GetAlternativeServiceInfos(server, network_isolation_key1_)
2122           .empty());
2123   EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
2124                                                      network_isolation_key1_));
2125   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
2126       alternative_service, network_isolation_key1_));
2127   EXPECT_FALSE(
2128       properties.GetAlternativeServiceInfos(server, network_isolation_key2_)
2129           .empty());
2130   EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
2131                                                     network_isolation_key2_));
2132   EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
2133       alternative_service, network_isolation_key2_));
2134 }
2135 
2136 // Regression test for https://crbug.com/505413.
TEST_F(AlternateProtocolServerPropertiesTest,RemoveExpiredBrokenAltSvc)2137 TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc) {
2138   url::SchemeHostPort foo_server("https", "foo", 443);
2139   AlternativeService bar_alternative_service(kProtoQUIC, "bar", 443);
2140   SetAlternativeService(foo_server, bar_alternative_service);
2141   EXPECT_TRUE(HasAlternativeService(foo_server, NetworkIsolationKey()));
2142 
2143   url::SchemeHostPort bar_server1("http", "bar", 80);
2144   AlternativeService nohost_alternative_service(kProtoQUIC, "", 443);
2145   SetAlternativeService(bar_server1, nohost_alternative_service);
2146   EXPECT_TRUE(HasAlternativeService(bar_server1, NetworkIsolationKey()));
2147 
2148   url::SchemeHostPort bar_server2("https", "bar", 443);
2149   AlternativeService baz_alternative_service(kProtoQUIC, "baz", 1234);
2150   SetAlternativeService(bar_server2, baz_alternative_service);
2151   EXPECT_TRUE(HasAlternativeService(bar_server2, NetworkIsolationKey()));
2152 
2153   // Mark "bar:443" as broken.
2154   base::TimeTicks past =
2155       test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
2156   HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
2157       &impl_, bar_alternative_service, past);
2158 
2159   // Expire brokenness of "bar:443".
2160   HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&impl_);
2161 
2162   // "foo:443" should have no alternative service now.
2163   EXPECT_FALSE(HasAlternativeService(foo_server, NetworkIsolationKey()));
2164   // "bar:80" should have no alternative service now.
2165   EXPECT_FALSE(HasAlternativeService(bar_server1, NetworkIsolationKey()));
2166   // The alternative service of "bar:443" should be unaffected.
2167   EXPECT_TRUE(HasAlternativeService(bar_server2, NetworkIsolationKey()));
2168 
2169   EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(bar_alternative_service,
2170                                                         NetworkIsolationKey()));
2171   EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
2172       baz_alternative_service, NetworkIsolationKey()));
2173 }
2174 
2175 // Regression test for https://crbug.com/724302
TEST_F(AlternateProtocolServerPropertiesTest,RemoveExpiredBrokenAltSvc2)2176 TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc2) {
2177   // This test will mark an alternative service A that has already been marked
2178   // broken many times, then immediately mark another alternative service B as
2179   // broken for the first time. Because A's been marked broken many times
2180   // already, its brokenness will be scheduled to expire much further in the
2181   // future than B, even though it was marked broken before B. This test makes
2182   // sure that even though A was marked broken before B, B's brokenness should
2183   // expire before A.
2184 
2185   url::SchemeHostPort server1("https", "foo", 443);
2186   AlternativeService alternative_service1(kProtoQUIC, "foo", 443);
2187   SetAlternativeService(server1, alternative_service1);
2188 
2189   url::SchemeHostPort server2("https", "bar", 443);
2190   AlternativeService alternative_service2(kProtoQUIC, "bar", 443);
2191   SetAlternativeService(server2, alternative_service2);
2192 
2193   // Repeatedly mark alt svc 1 broken and wait for its brokenness to expire.
2194   // This will increase its time until expiration.
2195   for (int i = 0; i < 3; ++i) {
2196     impl_.MarkAlternativeServiceBroken(alternative_service1,
2197                                        NetworkIsolationKey());
2198 
2199     // |impl_| should have posted task to expire the brokenness of
2200     // |alternative_service1|
2201     EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
2202     EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
2203                                                  NetworkIsolationKey()));
2204 
2205     // Advance time by just enough so that |alternative_service1|'s brokenness
2206     // expires.
2207     FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[i]);
2208 
2209     // Ensure brokenness of |alternative_service1| has expired.
2210     EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
2211     EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
2212                                                   NetworkIsolationKey()));
2213   }
2214 
2215   impl_.MarkAlternativeServiceBroken(alternative_service1,
2216                                      NetworkIsolationKey());
2217   impl_.MarkAlternativeServiceBroken(alternative_service2,
2218                                      NetworkIsolationKey());
2219 
2220   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service2,
2221                                                NetworkIsolationKey()));
2222 
2223   // Advance time by just enough so that |alternative_service2|'s brokennness
2224   // expires.
2225   FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[0]);
2226 
2227   EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
2228                                                NetworkIsolationKey()));
2229   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
2230                                                 NetworkIsolationKey()));
2231 
2232   // Advance time by enough so that |alternative_service1|'s brokenness expires.
2233   FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[3] -
2234                 BROKEN_ALT_SVC_EXPIRE_DELAYS[0]);
2235 
2236   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
2237                                                 NetworkIsolationKey()));
2238   EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
2239                                                 NetworkIsolationKey()));
2240 }
2241 
2242 // Regression test for https://crbug.com/994537. Having a ServerInfo entry
2243 // without a populated |alternative_services| value would cause
2244 // OnExpireBrokenAlternativeService() to hang..
TEST_F(AlternateProtocolServerPropertiesTest,RemoveExpiredBrokenAltSvc3)2245 TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc3) {
2246   // Add an altertive service entry.
2247   const url::SchemeHostPort kServer1("https", "foo", 443);
2248   const AlternativeService kAltService(kProtoQUIC, "bar", 443);
2249   SetAlternativeService(kServer1, kAltService);
2250   EXPECT_TRUE(HasAlternativeService(kServer1, NetworkIsolationKey()));
2251 
2252   // Add an entry to ServerInfo for another server, without an alternative
2253   // service value.
2254   const url::SchemeHostPort kServer2("http", "bar", 80);
2255   impl_.SetSupportsSpdy(kServer2, NetworkIsolationKey(), false);
2256 
2257   // Mark kAltService as broken.
2258   base::TimeTicks past =
2259       test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
2260   HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
2261       &impl_, kAltService, past);
2262 
2263   // Expire brokenness of kAltService. This call should not hang.
2264   HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&impl_);
2265 
2266   EXPECT_FALSE(HasAlternativeService(kServer1, NetworkIsolationKey()));
2267 }
2268 
TEST_F(AlternateProtocolServerPropertiesTest,GetAlternativeServiceInfoAsValue)2269 TEST_F(AlternateProtocolServerPropertiesTest,
2270        GetAlternativeServiceInfoAsValue) {
2271   base::test::ScopedFeatureList feature_list;
2272   feature_list.InitAndDisableFeature(
2273       features::kAppendFrameOriginToNetworkIsolationKey);
2274 
2275   base::Time::Exploded now_exploded;
2276   now_exploded.year = 2018;
2277   now_exploded.month = 1;
2278   now_exploded.day_of_week = 3;
2279   now_exploded.day_of_month = 24;
2280   now_exploded.hour = 15;
2281   now_exploded.minute = 12;
2282   now_exploded.second = 53;
2283   now_exploded.millisecond = 0;
2284   base::Time now;
2285   bool result = base::Time::FromLocalExploded(now_exploded, &now);
2286   DCHECK(result);
2287   test_clock_.SetNow(now);
2288 
2289   AlternativeServiceInfoVector alternative_service_info_vector;
2290   alternative_service_info_vector.push_back(
2291       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
2292           AlternativeService(kProtoHTTP2, "foo", 443),
2293           now + base::TimeDelta::FromMinutes(1)));
2294   alternative_service_info_vector.push_back(
2295       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
2296           AlternativeService(kProtoQUIC, "bar", 443),
2297           now + base::TimeDelta::FromHours(1), DefaultSupportedQuicVersions()));
2298   alternative_service_info_vector.push_back(
2299       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
2300           AlternativeService(kProtoQUIC, "baz", 443),
2301           now + base::TimeDelta::FromHours(1), DefaultSupportedQuicVersions()));
2302 
2303   impl_.SetAlternativeServices(url::SchemeHostPort("https", "youtube.com", 443),
2304                                NetworkIsolationKey(),
2305                                alternative_service_info_vector);
2306 
2307   impl_.MarkAlternativeServiceBroken(AlternativeService(kProtoQUIC, "bar", 443),
2308                                      NetworkIsolationKey());
2309 
2310   impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
2311       AlternativeService(kProtoQUIC, "baz", 443), NetworkIsolationKey());
2312 
2313   alternative_service_info_vector.clear();
2314   alternative_service_info_vector.push_back(
2315       AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
2316           AlternativeService(kProtoHTTP2, "foo2", 443),
2317           now + base::TimeDelta::FromDays(1)));
2318   impl_.SetAlternativeServices(url::SchemeHostPort("http", "test.com", 80),
2319                                NetworkIsolationKey(),
2320                                alternative_service_info_vector);
2321 
2322   const char expected_json[] =
2323       "["
2324       "{"
2325       "\"alternative_service\":"
2326       "[\"h2 foo2:443, expires 2018-01-25 15:12:53\"],"
2327       "\"network_isolation_key\":\"null\","
2328       "\"server\":\"http://test.com\""
2329       "},"
2330       "{"
2331       "\"alternative_service\":"
2332       "[\"h2 foo:443, expires 2018-01-24 15:13:53\","
2333       "\"quic bar:443, expires 2018-01-24 16:12:53"
2334       " (broken until 2018-01-24 15:17:53)\","
2335       "\"quic baz:443, expires 2018-01-24 16:12:53"
2336       " (broken until 2018-01-24 15:17:53)\"],"
2337       "\"network_isolation_key\":\"null\","
2338       "\"server\":\"https://youtube.com\""
2339       "}"
2340       "]";
2341 
2342   base::Value alternative_service_info_value =
2343       impl_.GetAlternativeServiceInfoAsValue();
2344   std::string alternative_service_info_json;
2345   base::JSONWriter::Write(alternative_service_info_value,
2346                           &alternative_service_info_json);
2347   EXPECT_EQ(expected_json, alternative_service_info_json);
2348 }
2349 
TEST_F(HttpServerPropertiesTest,LoadLastLocalAddressWhenQuicWorked)2350 TEST_F(HttpServerPropertiesTest, LoadLastLocalAddressWhenQuicWorked) {
2351   const IPAddress kEmptyAddress;
2352   const IPAddress kValidAddress1 = IPAddress::IPv4Localhost();
2353   const IPAddress kValidAddress2 = IPAddress::IPv6Localhost();
2354 
2355   // Check by initializing empty address.
2356   impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kEmptyAddress);
2357   EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
2358   // Empty address should not be considered an address that was used when QUIC
2359   // worked.
2360   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2361   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2362   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2363 
2364   // Check by initializing with a valid address.
2365   impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kValidAddress1);
2366   EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
2367   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2368   EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2369   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2370 
2371   // Try another valid address.
2372   impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kValidAddress2);
2373   EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
2374   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2375   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2376   EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2377 
2378   // And loading an empty address clears the current one.
2379   // TODO(mmenke): This seems like a bug, since if we've learned the current
2380   // network supports QUIC, surely we want to save that to disk? Seems like a
2381   // pre-existing value should take precedence, if non-empty, since if the
2382   // current network is already known to support QUIC, the loaded value is no
2383   // longer relevant.
2384   impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kEmptyAddress);
2385   EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
2386   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2387   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2388   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2389 }
2390 
TEST_F(HttpServerPropertiesTest,SetLastLocalAddressWhenQuicWorked)2391 TEST_F(HttpServerPropertiesTest, SetLastLocalAddressWhenQuicWorked) {
2392   const IPAddress kEmptyAddress;
2393   const IPAddress kValidAddress1 = IPAddress::IPv4Localhost();
2394   const IPAddress kValidAddress2 = IPAddress::IPv6Localhost();
2395 
2396   EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
2397   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2398   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2399   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2400 
2401   // Set to a valid address.
2402   impl_.SetLastLocalAddressWhenQuicWorked(kValidAddress1);
2403   EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
2404   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2405   EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2406   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2407 
2408   // Clear only this value.
2409   impl_.ClearLastLocalAddressWhenQuicWorked();
2410   EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
2411   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2412   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2413   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2414 
2415   // Try another valid address.
2416   impl_.SetLastLocalAddressWhenQuicWorked(kValidAddress2);
2417   EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
2418   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2419   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2420   EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2421 
2422   // Clear all values.
2423   impl_.Clear(base::OnceClosure());
2424   EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
2425   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
2426   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
2427   EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
2428 }
2429 
TEST_F(HttpServerPropertiesTest,LoadServerNetworkStats)2430 TEST_F(HttpServerPropertiesTest, LoadServerNetworkStats) {
2431   url::SchemeHostPort google_server("https", "www.google.com", 443);
2432 
2433   // Check by initializing empty ServerNetworkStats.
2434   std::unique_ptr<HttpServerProperties::ServerInfoMap> load_server_info_map =
2435       std::make_unique<HttpServerProperties::ServerInfoMap>();
2436   impl_.OnServerInfoLoadedForTesting(std::move(load_server_info_map));
2437   const ServerNetworkStats* stats =
2438       impl_.GetServerNetworkStats(google_server, NetworkIsolationKey());
2439   EXPECT_EQ(nullptr, stats);
2440 
2441   // Check by initializing with www.google.com:443.
2442   ServerNetworkStats stats_google;
2443   stats_google.srtt = base::TimeDelta::FromMicroseconds(10);
2444   stats_google.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(100);
2445   load_server_info_map =
2446       std::make_unique<HttpServerProperties::ServerInfoMap>();
2447   load_server_info_map->GetOrPut(CreateSimpleKey(google_server))
2448       ->second.server_network_stats = stats_google;
2449   impl_.OnServerInfoLoadedForTesting(std::move(load_server_info_map));
2450 
2451   // Verify data for www.google.com:443.
2452   ASSERT_EQ(1u, impl_.server_info_map_for_testing().size());
2453   EXPECT_EQ(stats_google, *(impl_.GetServerNetworkStats(
2454                               google_server, NetworkIsolationKey())));
2455 
2456   // Test recency order and overwriting of data.
2457   //
2458   // |docs_server| has a ServerNetworkStats, which will be overwritten by
2459   // OnServerInfoLoadedForTesting(), because |server_network_stats_map| has an
2460   // entry for |docs_server|.
2461   url::SchemeHostPort docs_server("https", "docs.google.com", 443);
2462   ServerNetworkStats stats_docs;
2463   stats_docs.srtt = base::TimeDelta::FromMicroseconds(20);
2464   stats_docs.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(200);
2465   // Recency order will be |docs_server| and |google_server|.
2466   impl_.SetServerNetworkStats(docs_server, NetworkIsolationKey(), stats_docs);
2467 
2468   // Prepare |server_info_map| to be loaded by OnServerInfoLoadedForTesting().
2469   std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
2470       std::make_unique<HttpServerProperties::ServerInfoMap>();
2471 
2472   // Change the values for |docs_server|.
2473   ServerNetworkStats new_stats_docs;
2474   new_stats_docs.srtt = base::TimeDelta::FromMicroseconds(25);
2475   new_stats_docs.bandwidth_estimate =
2476       quic::QuicBandwidth::FromBitsPerSecond(250);
2477   server_info_map->GetOrPut(CreateSimpleKey(docs_server))
2478       ->second.server_network_stats = new_stats_docs;
2479   // Add data for mail.google.com:443.
2480   url::SchemeHostPort mail_server("https", "mail.google.com", 443);
2481   ServerNetworkStats stats_mail;
2482   stats_mail.srtt = base::TimeDelta::FromMicroseconds(30);
2483   stats_mail.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(300);
2484   server_info_map->GetOrPut(CreateSimpleKey(mail_server))
2485       ->second.server_network_stats = stats_mail;
2486 
2487   // Recency order will be |docs_server|, |google_server| and |mail_server|.
2488   impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));
2489 
2490   const HttpServerProperties::ServerInfoMap& map =
2491       impl_.server_info_map_for_testing();
2492   ASSERT_EQ(3u, map.size());
2493   auto map_it = map.begin();
2494 
2495   EXPECT_EQ(docs_server, map_it->first.server);
2496   EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
2497   ASSERT_TRUE(map_it->second.server_network_stats.has_value());
2498   EXPECT_EQ(new_stats_docs, *map_it->second.server_network_stats);
2499   ++map_it;
2500   EXPECT_EQ(google_server, map_it->first.server);
2501   EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
2502   ASSERT_TRUE(map_it->second.server_network_stats.has_value());
2503   EXPECT_EQ(stats_google, *map_it->second.server_network_stats);
2504   ++map_it;
2505   EXPECT_EQ(mail_server, map_it->first.server);
2506   EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
2507   ASSERT_TRUE(map_it->second.server_network_stats.has_value());
2508   EXPECT_EQ(stats_mail, *map_it->second.server_network_stats);
2509 }
2510 
TEST_F(HttpServerPropertiesTest,SetServerNetworkStats)2511 TEST_F(HttpServerPropertiesTest, SetServerNetworkStats) {
2512   url::SchemeHostPort foo_http_server("http", "foo", 443);
2513   url::SchemeHostPort foo_https_server("https", "foo", 443);
2514   EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_http_server,
2515                                                  NetworkIsolationKey()));
2516   EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
2517                                                  NetworkIsolationKey()));
2518 
2519   ServerNetworkStats stats1;
2520   stats1.srtt = base::TimeDelta::FromMicroseconds(10);
2521   stats1.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(100);
2522   impl_.SetServerNetworkStats(foo_http_server, NetworkIsolationKey(), stats1);
2523 
2524   const ServerNetworkStats* stats2 =
2525       impl_.GetServerNetworkStats(foo_http_server, NetworkIsolationKey());
2526   EXPECT_EQ(10, stats2->srtt.ToInternalValue());
2527   EXPECT_EQ(100, stats2->bandwidth_estimate.ToBitsPerSecond());
2528   // Https server should have nothing set for server network stats.
2529   EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
2530                                                  NetworkIsolationKey()));
2531 
2532   impl_.Clear(base::OnceClosure());
2533   EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_http_server,
2534                                                  NetworkIsolationKey()));
2535   EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
2536                                                  NetworkIsolationKey()));
2537 }
2538 
TEST_F(HttpServerPropertiesTest,ClearServerNetworkStats)2539 TEST_F(HttpServerPropertiesTest, ClearServerNetworkStats) {
2540   ServerNetworkStats stats;
2541   stats.srtt = base::TimeDelta::FromMicroseconds(10);
2542   stats.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(100);
2543   url::SchemeHostPort foo_https_server("https", "foo", 443);
2544   impl_.SetServerNetworkStats(foo_https_server, NetworkIsolationKey(), stats);
2545 
2546   impl_.ClearServerNetworkStats(foo_https_server, NetworkIsolationKey());
2547   EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
2548                                                  NetworkIsolationKey()));
2549 }
2550 
TEST_F(HttpServerPropertiesTest,OnQuicServerInfoMapLoaded)2551 TEST_F(HttpServerPropertiesTest, OnQuicServerInfoMapLoaded) {
2552   quic::QuicServerId google_quic_server_id("www.google.com", 443, true);
2553   HttpServerProperties::QuicServerInfoMapKey google_key(
2554       google_quic_server_id, NetworkIsolationKey(),
2555       false /* use_network_isolation_key */);
2556 
2557   const int kMaxQuicServerEntries = 10;
2558   impl_.SetMaxServerConfigsStoredInProperties(kMaxQuicServerEntries);
2559   EXPECT_EQ(10u, impl_.quic_server_info_map().max_size());
2560 
2561   // Check empty map.
2562   std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
2563       init_quic_server_info_map =
2564           std::make_unique<HttpServerProperties::QuicServerInfoMap>(
2565               kMaxQuicServerEntries);
2566   impl_.OnQuicServerInfoMapLoadedForTesting(
2567       std::move(init_quic_server_info_map));
2568   EXPECT_EQ(0u, impl_.quic_server_info_map().size());
2569 
2570   // Check by initializing with www.google.com:443.
2571   std::string google_server_info("google_quic_server_info");
2572   init_quic_server_info_map =
2573       std::make_unique<HttpServerProperties::QuicServerInfoMap>(
2574           kMaxQuicServerEntries);
2575   init_quic_server_info_map->Put(google_key, google_server_info);
2576   impl_.OnQuicServerInfoMapLoadedForTesting(
2577       std::move(init_quic_server_info_map));
2578 
2579   // Verify data for www.google.com:443.
2580   EXPECT_EQ(1u, impl_.quic_server_info_map().size());
2581   EXPECT_EQ(
2582       google_server_info,
2583       *impl_.GetQuicServerInfo(google_quic_server_id, NetworkIsolationKey()));
2584 
2585   // Test recency order and overwriting of data.
2586   //
2587   // |docs_server| has a QuicServerInfo, which will be overwritten by
2588   // SetQuicServerInfoMap(), because |quic_server_info_map| has an
2589   // entry for |docs_server|.
2590   quic::QuicServerId docs_quic_server_id("docs.google.com", 443, true);
2591   HttpServerProperties::QuicServerInfoMapKey docs_key(
2592       docs_quic_server_id, NetworkIsolationKey(),
2593       false /* use_network_isolation_key */);
2594   std::string docs_server_info("docs_quic_server_info");
2595   impl_.SetQuicServerInfo(docs_quic_server_id, NetworkIsolationKey(),
2596                           docs_server_info);
2597 
2598   // Recency order will be |docs_server| and |google_server|.
2599   const HttpServerProperties::QuicServerInfoMap& map =
2600       impl_.quic_server_info_map();
2601   ASSERT_EQ(2u, map.size());
2602   auto map_it = map.begin();
2603   EXPECT_EQ(map_it->first, docs_key);
2604   EXPECT_EQ(docs_server_info, map_it->second);
2605   ++map_it;
2606   EXPECT_EQ(map_it->first, google_key);
2607   EXPECT_EQ(google_server_info, map_it->second);
2608 
2609   // Prepare |quic_server_info_map| to be loaded by
2610   // SetQuicServerInfoMap().
2611   std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
2612       quic_server_info_map =
2613           std::make_unique<HttpServerProperties::QuicServerInfoMap>(
2614               kMaxQuicServerEntries);
2615   // Change the values for |docs_server|.
2616   std::string new_docs_server_info("new_docs_quic_server_info");
2617   quic_server_info_map->Put(docs_key, new_docs_server_info);
2618   // Add data for mail.google.com:443.
2619   quic::QuicServerId mail_quic_server_id("mail.google.com", 443, true);
2620   HttpServerProperties::QuicServerInfoMapKey mail_key(
2621       mail_quic_server_id, NetworkIsolationKey(),
2622       false /* use_network_isolation_key */);
2623   std::string mail_server_info("mail_quic_server_info");
2624   quic_server_info_map->Put(mail_key, mail_server_info);
2625   impl_.OnQuicServerInfoMapLoadedForTesting(std::move(quic_server_info_map));
2626 
2627   // Recency order will be |docs_server|, |google_server| and |mail_server|.
2628   const HttpServerProperties::QuicServerInfoMap& memory_map =
2629       impl_.quic_server_info_map();
2630   ASSERT_EQ(3u, memory_map.size());
2631   auto memory_map_it = memory_map.begin();
2632   EXPECT_EQ(memory_map_it->first, docs_key);
2633   EXPECT_EQ(new_docs_server_info, memory_map_it->second);
2634   ++memory_map_it;
2635   EXPECT_EQ(memory_map_it->first, google_key);
2636   EXPECT_EQ(google_server_info, memory_map_it->second);
2637   ++memory_map_it;
2638   EXPECT_EQ(memory_map_it->first, mail_key);
2639   EXPECT_EQ(mail_server_info, memory_map_it->second);
2640 
2641   // Shrink the size of |quic_server_info_map| and verify the MRU order is
2642   // maintained.
2643   impl_.SetMaxServerConfigsStoredInProperties(2);
2644   EXPECT_EQ(2u, impl_.quic_server_info_map().max_size());
2645 
2646   const HttpServerProperties::QuicServerInfoMap& memory_map1 =
2647       impl_.quic_server_info_map();
2648   ASSERT_EQ(2u, memory_map1.size());
2649   auto memory_map1_it = memory_map1.begin();
2650   EXPECT_EQ(memory_map1_it->first, docs_key);
2651   EXPECT_EQ(new_docs_server_info, memory_map1_it->second);
2652   ++memory_map1_it;
2653   EXPECT_EQ(memory_map1_it->first, google_key);
2654   EXPECT_EQ(google_server_info, memory_map1_it->second);
2655   // |QuicServerInfo| for |mail_quic_server_id| shouldn't be there.
2656   EXPECT_EQ(nullptr, impl_.GetQuicServerInfo(mail_quic_server_id,
2657                                              NetworkIsolationKey()));
2658 }
2659 
TEST_F(HttpServerPropertiesTest,SetQuicServerInfo)2660 TEST_F(HttpServerPropertiesTest, SetQuicServerInfo) {
2661   quic::QuicServerId server1("foo", 80, false /* privacy_mode_enabled */);
2662   quic::QuicServerId server2("foo", 80, true /* privacy_mode_enabled */);
2663 
2664   std::string quic_server_info1("quic_server_info1");
2665   std::string quic_server_info2("quic_server_info2");
2666   std::string quic_server_info3("quic_server_info3");
2667 
2668   // Without network isolation keys enabled for HttpServerProperties, passing in
2669   // a NetworkIsolationKey should have no effect on behavior.
2670   impl_.SetQuicServerInfo(server1, NetworkIsolationKey(), quic_server_info1);
2671   EXPECT_EQ(quic_server_info1,
2672             *(impl_.GetQuicServerInfo(server1, NetworkIsolationKey())));
2673   EXPECT_FALSE(impl_.GetQuicServerInfo(server2, NetworkIsolationKey()));
2674   EXPECT_EQ(quic_server_info1,
2675             *(impl_.GetQuicServerInfo(server1, network_isolation_key1_)));
2676   EXPECT_FALSE(impl_.GetQuicServerInfo(server2, network_isolation_key1_));
2677 
2678   impl_.SetQuicServerInfo(server2, network_isolation_key1_, quic_server_info2);
2679   EXPECT_EQ(quic_server_info1,
2680             *(impl_.GetQuicServerInfo(server1, NetworkIsolationKey())));
2681   EXPECT_EQ(quic_server_info2,
2682             *(impl_.GetQuicServerInfo(server2, NetworkIsolationKey())));
2683   EXPECT_EQ(quic_server_info1,
2684             *(impl_.GetQuicServerInfo(server1, network_isolation_key1_)));
2685   EXPECT_EQ(quic_server_info2,
2686             *(impl_.GetQuicServerInfo(server2, network_isolation_key1_)));
2687 
2688   impl_.SetQuicServerInfo(server1, network_isolation_key1_, quic_server_info3);
2689   EXPECT_EQ(quic_server_info3,
2690             *(impl_.GetQuicServerInfo(server1, NetworkIsolationKey())));
2691   EXPECT_EQ(quic_server_info2,
2692             *(impl_.GetQuicServerInfo(server2, NetworkIsolationKey())));
2693   EXPECT_EQ(quic_server_info3,
2694             *(impl_.GetQuicServerInfo(server1, network_isolation_key1_)));
2695   EXPECT_EQ(quic_server_info2,
2696             *(impl_.GetQuicServerInfo(server2, network_isolation_key1_)));
2697 
2698   impl_.Clear(base::OnceClosure());
2699   EXPECT_FALSE(impl_.GetQuicServerInfo(server1, NetworkIsolationKey()));
2700   EXPECT_FALSE(impl_.GetQuicServerInfo(server2, NetworkIsolationKey()));
2701   EXPECT_FALSE(impl_.GetQuicServerInfo(server1, network_isolation_key1_));
2702   EXPECT_FALSE(impl_.GetQuicServerInfo(server2, network_isolation_key1_));
2703 
2704   base::test::ScopedFeatureList feature_list;
2705   feature_list.InitAndEnableFeature(
2706       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
2707   // Since HttpServerProperties caches the feature value, have to create a new
2708   // one.
2709   HttpServerProperties properties(nullptr /* pref_delegate */,
2710                                   nullptr /* net_log */, test_tick_clock_,
2711                                   &test_clock_);
2712 
2713   properties.SetQuicServerInfo(server1, NetworkIsolationKey(),
2714                                quic_server_info1);
2715   EXPECT_EQ(quic_server_info1,
2716             *(properties.GetQuicServerInfo(server1, NetworkIsolationKey())));
2717   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2718   EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key1_));
2719   EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));
2720 
2721   properties.SetQuicServerInfo(server1, network_isolation_key1_,
2722                                quic_server_info2);
2723   EXPECT_EQ(quic_server_info1,
2724             *(properties.GetQuicServerInfo(server1, NetworkIsolationKey())));
2725   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2726   EXPECT_EQ(quic_server_info2,
2727             *(properties.GetQuicServerInfo(server1, network_isolation_key1_)));
2728   EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));
2729 
2730   properties.SetQuicServerInfo(server2, network_isolation_key1_,
2731                                quic_server_info3);
2732   EXPECT_EQ(quic_server_info1,
2733             *(properties.GetQuicServerInfo(server1, NetworkIsolationKey())));
2734   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2735   EXPECT_EQ(quic_server_info2,
2736             *(properties.GetQuicServerInfo(server1, network_isolation_key1_)));
2737   EXPECT_EQ(quic_server_info3,
2738             *(properties.GetQuicServerInfo(server2, network_isolation_key1_)));
2739 
2740   properties.Clear(base::OnceClosure());
2741   EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
2742   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2743   EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key1_));
2744   EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));
2745 }
2746 
2747 // Tests that GetQuicServerInfo() returns server info of a host
2748 // with the same canonical suffix when there is no exact host match.
TEST_F(HttpServerPropertiesTest,QuicServerInfoCanonicalSuffixMatch)2749 TEST_F(HttpServerPropertiesTest, QuicServerInfoCanonicalSuffixMatch) {
2750   // Set up HttpServerProperties.
2751   // Add a host with a canonical suffix.
2752   quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
2753   std::string foo_server_info("foo_server_info");
2754   impl_.SetQuicServerInfo(foo_server_id, NetworkIsolationKey(),
2755                           foo_server_info);
2756 
2757   // Add a host that has a different canonical suffix.
2758   quic::QuicServerId baz_server_id("baz.video.com", 443, false);
2759   std::string baz_server_info("baz_server_info");
2760   impl_.SetQuicServerInfo(baz_server_id, NetworkIsolationKey(),
2761                           baz_server_info);
2762 
2763   // Create SchemeHostPort with a host that has the initial canonical suffix.
2764   quic::QuicServerId bar_server_id("bar.googlevideo.com", 443, false);
2765 
2766   // Check the the server info associated with "foo" is returned for "bar".
2767   const std::string* bar_server_info =
2768       impl_.GetQuicServerInfo(bar_server_id, NetworkIsolationKey());
2769   ASSERT_TRUE(bar_server_info != nullptr);
2770   EXPECT_EQ(foo_server_info, *bar_server_info);
2771 }
2772 
2773 // Make sure that canonical suffices respect NetworkIsolationKeys when using
2774 // QuicServerInfo methods.
TEST_F(HttpServerPropertiesTest,QuicServerInfoCanonicalSuffixMatchWithNetworkIsolationKey)2775 TEST_F(HttpServerPropertiesTest,
2776        QuicServerInfoCanonicalSuffixMatchWithNetworkIsolationKey) {
2777   // Two servers with same canonical suffix.
2778   quic::QuicServerId server1("foo.googlevideo.com", 80,
2779                              false /* privacy_mode_enabled */);
2780   quic::QuicServerId server2("bar.googlevideo.com", 80,
2781                              false /* privacy_mode_enabled */);
2782 
2783   std::string server_info1("server_info1");
2784   std::string server_info2("server_info2");
2785 
2786   base::test::ScopedFeatureList feature_list;
2787   feature_list.InitAndEnableFeature(
2788       features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
2789   // Since HttpServerProperties caches the feature value, have to create a new
2790   // one.
2791   HttpServerProperties properties(nullptr /* pref_delegate */,
2792                                   nullptr /* net_log */, test_tick_clock_,
2793                                   &test_clock_);
2794 
2795   // Set QuicServerInfo for one canononical suffix and
2796   // |network_isolation_key1_|. It should be accessible via another
2797   // SchemeHostPort, but only when the NetworkIsolationKeys match.
2798   properties.SetQuicServerInfo(server1, network_isolation_key1_, server_info1);
2799   const std::string* fetched_server_info =
2800       properties.GetQuicServerInfo(server1, network_isolation_key1_);
2801   ASSERT_TRUE(fetched_server_info);
2802   EXPECT_EQ(server_info1, *fetched_server_info);
2803   fetched_server_info =
2804       properties.GetQuicServerInfo(server2, network_isolation_key1_);
2805   ASSERT_TRUE(fetched_server_info);
2806   EXPECT_EQ(server_info1, *fetched_server_info);
2807   EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key2_));
2808   EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key2_));
2809   EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
2810   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2811 
2812   // Set different QuicServerInfo for the same canononical suffix and
2813   // |network_isolation_key2_|. Both infos should be retriveable by using the
2814   // different NetworkIsolationKeys.
2815   properties.SetQuicServerInfo(server1, network_isolation_key2_, server_info2);
2816   fetched_server_info =
2817       properties.GetQuicServerInfo(server1, network_isolation_key1_);
2818   ASSERT_TRUE(fetched_server_info);
2819   EXPECT_EQ(server_info1, *fetched_server_info);
2820   fetched_server_info =
2821       properties.GetQuicServerInfo(server2, network_isolation_key1_);
2822   ASSERT_TRUE(fetched_server_info);
2823   EXPECT_EQ(server_info1, *fetched_server_info);
2824   fetched_server_info =
2825       properties.GetQuicServerInfo(server1, network_isolation_key2_);
2826   ASSERT_TRUE(fetched_server_info);
2827   EXPECT_EQ(server_info2, *fetched_server_info);
2828   fetched_server_info =
2829       properties.GetQuicServerInfo(server2, network_isolation_key2_);
2830   ASSERT_TRUE(fetched_server_info);
2831   EXPECT_EQ(server_info2, *fetched_server_info);
2832   EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
2833   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2834 
2835   // Clearing should destroy all information.
2836   properties.Clear(base::OnceClosure());
2837   EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key1_));
2838   EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));
2839   EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key2_));
2840   EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key2_));
2841   EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
2842   EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
2843 }
2844 
2845 // Verifies that GetQuicServerInfo() returns the MRU entry if multiple records
2846 // match a given canonical host.
TEST_F(HttpServerPropertiesTest,QuicServerInfoCanonicalSuffixMatchReturnsMruEntry)2847 TEST_F(HttpServerPropertiesTest,
2848        QuicServerInfoCanonicalSuffixMatchReturnsMruEntry) {
2849   // Set up HttpServerProperties by adding two hosts with the same canonical
2850   // suffixes.
2851   quic::QuicServerId h1_server_id("h1.googlevideo.com", 443, false);
2852   std::string h1_server_info("h1_server_info");
2853   impl_.SetQuicServerInfo(h1_server_id, NetworkIsolationKey(), h1_server_info);
2854 
2855   quic::QuicServerId h2_server_id("h2.googlevideo.com", 443, false);
2856   std::string h2_server_info("h2_server_info");
2857   impl_.SetQuicServerInfo(h2_server_id, NetworkIsolationKey(), h2_server_info);
2858 
2859   // Create quic::QuicServerId to use for the search.
2860   quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
2861 
2862   // Check that 'h2' info is returned since it is MRU.
2863   const std::string* server_info =
2864       impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
2865   ASSERT_TRUE(server_info != nullptr);
2866   EXPECT_EQ(h2_server_info, *server_info);
2867 
2868   // Access 'h1' info, so it becomes MRU.
2869   impl_.GetQuicServerInfo(h1_server_id, NetworkIsolationKey());
2870 
2871   // Check that 'h1' info is returned since it is MRU now.
2872   server_info = impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
2873   ASSERT_TRUE(server_info != nullptr);
2874   EXPECT_EQ(h1_server_info, *server_info);
2875 }
2876 
2877 // Verifies that |GetQuicServerInfo| doesn't change the MRU order of the server
2878 // info map when a record is matched based on a canonical name.
TEST_F(HttpServerPropertiesTest,QuicServerInfoCanonicalSuffixMatchDoesntChangeOrder)2879 TEST_F(HttpServerPropertiesTest,
2880        QuicServerInfoCanonicalSuffixMatchDoesntChangeOrder) {
2881   // Add a host with a matching canonical name.
2882   quic::QuicServerId h1_server_id("h1.googlevideo.com", 443, false);
2883   HttpServerProperties::QuicServerInfoMapKey h1_key(
2884       h1_server_id, NetworkIsolationKey(),
2885       false /* use_network_isolation_key */);
2886   std::string h1_server_info("h1_server_info");
2887   impl_.SetQuicServerInfo(h1_server_id, NetworkIsolationKey(), h1_server_info);
2888 
2889   // Add a host hosts with a non-matching canonical name.
2890   quic::QuicServerId h2_server_id("h2.video.com", 443, false);
2891   HttpServerProperties::QuicServerInfoMapKey h2_key(
2892       h2_server_id, NetworkIsolationKey(),
2893       false /* use_network_isolation_key */);
2894   std::string h2_server_info("h2_server_info");
2895   impl_.SetQuicServerInfo(h2_server_id, NetworkIsolationKey(), h2_server_info);
2896 
2897   // Check that "h2.video.com" is the MRU entry in the map.
2898   EXPECT_EQ(h2_key, impl_.quic_server_info_map().begin()->first);
2899 
2900   // Search for the entry that matches the canonical name
2901   // ("h1.googlevideo.com").
2902   quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
2903   const std::string* server_info =
2904       impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
2905   ASSERT_TRUE(server_info != nullptr);
2906 
2907   // Check that the search (although successful) hasn't changed the MRU order of
2908   // the map.
2909   EXPECT_EQ(h2_key, impl_.quic_server_info_map().begin()->first);
2910 
2911   // Search for "h1.googlevideo.com" directly, so it becomes MRU
2912   impl_.GetQuicServerInfo(h1_server_id, NetworkIsolationKey());
2913 
2914   // Check that "h1.googlevideo.com" is the MRU entry now.
2915   EXPECT_EQ(h1_key, impl_.quic_server_info_map().begin()->first);
2916 }
2917 
2918 // Tests that the canonical host matching works for hosts stored in memory cache
2919 // and the ones loaded from persistent storage, i.e. server info added
2920 // using SetQuicServerInfo() and SetQuicServerInfoMap() is taken into
2921 // cosideration when searching for server info for a host with the same
2922 // canonical suffix.
TEST_F(HttpServerPropertiesTest,QuicServerInfoCanonicalSuffixMatchSetInfoMap)2923 TEST_F(HttpServerPropertiesTest, QuicServerInfoCanonicalSuffixMatchSetInfoMap) {
2924   // Add a host info using SetQuicServerInfo(). That will simulate an info
2925   // entry stored in memory cache.
2926   quic::QuicServerId h1_server_id("h1.googlevideo.com", 443, false);
2927   std::string h1_server_info("h1_server_info_memory_cache");
2928   impl_.SetQuicServerInfo(h1_server_id, NetworkIsolationKey(), h1_server_info);
2929 
2930   // Prepare a map with host info and add it using SetQuicServerInfoMap(). That
2931   // will simulate info records read from the persistence storage.
2932   quic::QuicServerId h2_server_id("h2.googlevideo.com", 443, false);
2933   HttpServerProperties::QuicServerInfoMapKey h2_key(
2934       h2_server_id, NetworkIsolationKey(),
2935       false /* use_network_isolation_key */);
2936   std::string h2_server_info("h2_server_info_from_disk");
2937 
2938   quic::QuicServerId h3_server_id("h3.ggpht.com", 443, false);
2939   HttpServerProperties::QuicServerInfoMapKey h3_key(
2940       h3_server_id, NetworkIsolationKey(),
2941       false /* use_network_isolation_key */);
2942   std::string h3_server_info("h3_server_info_from_disk");
2943 
2944   const int kMaxQuicServerEntries = 10;
2945   impl_.SetMaxServerConfigsStoredInProperties(kMaxQuicServerEntries);
2946 
2947   std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
2948       quic_server_info_map =
2949           std::make_unique<HttpServerProperties::QuicServerInfoMap>(
2950               kMaxQuicServerEntries);
2951   quic_server_info_map->Put(h2_key, h2_server_info);
2952   quic_server_info_map->Put(h3_key, h3_server_info);
2953   impl_.OnQuicServerInfoMapLoadedForTesting(std::move(quic_server_info_map));
2954 
2955   // Check that the server info from the memory cache is returned since unique
2956   // entries from the memory cache are added after entries from the
2957   // persistence storage and, therefore, are most recently used.
2958   quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
2959   const std::string* server_info =
2960       impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
2961   ASSERT_TRUE(server_info != nullptr);
2962   EXPECT_EQ(h1_server_info, *server_info);
2963 
2964   // Check that server info that was added using SetQuicServerInfoMap() can be
2965   // found.
2966   foo_server_id = quic::QuicServerId("foo.ggpht.com", 443, false);
2967   server_info = impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
2968   ASSERT_TRUE(server_info != nullptr);
2969   EXPECT_EQ(h3_server_info, *server_info);
2970 }
2971 
2972 }  // namespace
2973 
2974 }  // namespace net
2975