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