1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/ssl/ssl_client_session_cache.h"
6
7 #include "base/run_loop.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/test/simple_test_clock.h"
10 #include "base/test/task_environment.h"
11 #include "base/time/time.h"
12 #include "base/trace_event/memory_allocator_dump.h"
13 #include "base/trace_event/process_memory_dump.h"
14 #include "net/base/network_anonymization_key.h"
15 #include "net/base/schemeful_site.h"
16 #include "net/base/tracing.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/boringssl/src/include/openssl/ssl.h"
20 #include "url/gurl.h"
21
22 using testing::ByRef;
23 using testing::Contains;
24 using testing::Eq;
25 using testing::Field;
26
27 namespace net {
28
29 namespace {
30
MakeTestClock()31 std::unique_ptr<base::SimpleTestClock> MakeTestClock() {
32 std::unique_ptr<base::SimpleTestClock> clock =
33 std::make_unique<base::SimpleTestClock>();
34 // SimpleTestClock starts at the null base::Time which converts to and from
35 // time_t confusingly.
36 clock->SetNow(base::Time::FromTimeT(1000000000));
37 return clock;
38 }
39
MakeTestKey(const std::string & str)40 SSLClientSessionCache::Key MakeTestKey(const std::string& str) {
41 SSLClientSessionCache::Key key;
42 key.server = HostPortPair(str, 443);
43 return key;
44 }
45
46 class SSLClientSessionCacheTest : public testing::Test {
47 public:
SSLClientSessionCacheTest()48 SSLClientSessionCacheTest() : ssl_ctx_(SSL_CTX_new(TLS_method())) {}
49
50 protected:
NewSSLSession(uint16_t version=TLS1_2_VERSION)51 bssl::UniquePtr<SSL_SESSION> NewSSLSession(
52 uint16_t version = TLS1_2_VERSION) {
53 SSL_SESSION* session = SSL_SESSION_new(ssl_ctx_.get());
54 if (!SSL_SESSION_set_protocol_version(session, version))
55 return nullptr;
56 return bssl::UniquePtr<SSL_SESSION>(session);
57 }
58
MakeTestSession(base::Time now,base::TimeDelta timeout)59 bssl::UniquePtr<SSL_SESSION> MakeTestSession(base::Time now,
60 base::TimeDelta timeout) {
61 bssl::UniquePtr<SSL_SESSION> session = NewSSLSession();
62 SSL_SESSION_set_time(session.get(), now.ToTimeT());
63 SSL_SESSION_set_timeout(session.get(), timeout.InSeconds());
64 return session;
65 }
66
67 private:
68 bssl::UniquePtr<SSL_CTX> ssl_ctx_;
69 };
70
71 } // namespace
72
73 // These tests rely on memory corruption detectors to verify that
74 // SSL_SESSION reference counts were correctly managed and no sessions
75 // leaked or were accessed after free.
76
77 // Test basic insertion and lookup operations.
TEST_F(SSLClientSessionCacheTest,Basic)78 TEST_F(SSLClientSessionCacheTest, Basic) {
79 SSLClientSessionCache::Config config;
80 SSLClientSessionCache cache(config);
81
82 bssl::UniquePtr<SSL_SESSION> session1 = NewSSLSession();
83 bssl::UniquePtr<SSL_SESSION> session2 = NewSSLSession();
84 bssl::UniquePtr<SSL_SESSION> session3 = NewSSLSession();
85
86 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
87 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
88 EXPECT_EQ(0u, cache.size());
89
90 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
91 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
92 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
93 EXPECT_EQ(1u, cache.size());
94
95 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session2));
96 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
97 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
98 EXPECT_EQ(2u, cache.size());
99
100 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session3));
101 EXPECT_EQ(session3.get(), cache.Lookup(MakeTestKey("key1")).get());
102 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
103 EXPECT_EQ(2u, cache.size());
104
105 cache.Flush();
106 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
107 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
108 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key3")).get());
109 EXPECT_EQ(0u, cache.size());
110 }
111
112 // Test basic insertion and lookup operations with single-use sessions.
TEST_F(SSLClientSessionCacheTest,BasicSingleUse)113 TEST_F(SSLClientSessionCacheTest, BasicSingleUse) {
114 SSLClientSessionCache::Config config;
115 SSLClientSessionCache cache(config);
116
117 bssl::UniquePtr<SSL_SESSION> session1 = NewSSLSession(TLS1_3_VERSION);
118 bssl::UniquePtr<SSL_SESSION> session2 = NewSSLSession(TLS1_3_VERSION);
119 bssl::UniquePtr<SSL_SESSION> session3 = NewSSLSession(TLS1_3_VERSION);
120
121 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
122 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
123 EXPECT_EQ(0u, cache.size());
124
125 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
126 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
127 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
128 EXPECT_EQ(0u, cache.size());
129
130 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
131
132 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
133 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
134 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session2));
135
136 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
137 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
138 EXPECT_EQ(1u, cache.size());
139
140 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
141 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
142
143 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
144 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session3));
145 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session2));
146 EXPECT_EQ(session3.get(), cache.Lookup(MakeTestKey("key1")).get());
147 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
148 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
149 EXPECT_EQ(0u, cache.size());
150
151 cache.Flush();
152 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
153 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
154 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key3")).get());
155 EXPECT_EQ(0u, cache.size());
156
157 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
158 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session2));
159 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session3));
160 EXPECT_EQ(session3.get(), cache.Lookup(MakeTestKey("key1")).get());
161 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key1")).get());
162 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
163 }
164
165 // Test insertion and lookup operations with both single-use and reusable
166 // sessions.
TEST_F(SSLClientSessionCacheTest,MixedUse)167 TEST_F(SSLClientSessionCacheTest, MixedUse) {
168 SSLClientSessionCache::Config config;
169 SSLClientSessionCache cache(config);
170
171 bssl::UniquePtr<SSL_SESSION> session_single = NewSSLSession(TLS1_3_VERSION);
172 bssl::UniquePtr<SSL_SESSION> session_reuse = NewSSLSession(TLS1_2_VERSION);
173
174 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
175 EXPECT_EQ(0u, cache.size());
176
177 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session_reuse));
178 EXPECT_EQ(session_reuse.get(), cache.Lookup(MakeTestKey("key1")).get());
179 EXPECT_EQ(1u, cache.size());
180
181 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session_single));
182 EXPECT_EQ(session_single.get(), cache.Lookup(MakeTestKey("key1")).get());
183 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
184 EXPECT_EQ(0u, cache.size());
185
186 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
187 EXPECT_EQ(0u, cache.size());
188
189 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session_single));
190 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session_single));
191 EXPECT_EQ(1u, cache.size());
192
193 EXPECT_EQ(session_single.get(), cache.Lookup(MakeTestKey("key2")).get());
194 EXPECT_EQ(session_single.get(), cache.Lookup(MakeTestKey("key2")).get());
195 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
196 EXPECT_EQ(0u, cache.size());
197
198 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session_single));
199 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session_reuse));
200 EXPECT_EQ(session_reuse.get(), cache.Lookup(MakeTestKey("key2")).get());
201 EXPECT_EQ(session_reuse.get(), cache.Lookup(MakeTestKey("key2")).get());
202 EXPECT_EQ(1u, cache.size());
203 }
204
205 // Test that a session may be inserted at two different keys. This should never
206 // be necessary, but the API doesn't prohibit it.
TEST_F(SSLClientSessionCacheTest,DoubleInsert)207 TEST_F(SSLClientSessionCacheTest, DoubleInsert) {
208 SSLClientSessionCache::Config config;
209 SSLClientSessionCache cache(config);
210
211 bssl::UniquePtr<SSL_SESSION> session = NewSSLSession();
212
213 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
214 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
215 EXPECT_EQ(0u, cache.size());
216
217 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session));
218 EXPECT_EQ(session.get(), cache.Lookup(MakeTestKey("key1")).get());
219 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
220 EXPECT_EQ(1u, cache.size());
221
222 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session));
223 EXPECT_EQ(session.get(), cache.Lookup(MakeTestKey("key1")).get());
224 EXPECT_EQ(session.get(), cache.Lookup(MakeTestKey("key2")).get());
225 EXPECT_EQ(2u, cache.size());
226
227 cache.Flush();
228 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
229 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key2")).get());
230 EXPECT_EQ(0u, cache.size());
231 }
232
233 // Tests that the session cache's size is correctly bounded.
TEST_F(SSLClientSessionCacheTest,MaxEntries)234 TEST_F(SSLClientSessionCacheTest, MaxEntries) {
235 SSLClientSessionCache::Config config;
236 config.max_entries = 3;
237 SSLClientSessionCache cache(config);
238
239 bssl::UniquePtr<SSL_SESSION> session1 = NewSSLSession();
240 bssl::UniquePtr<SSL_SESSION> session2 = NewSSLSession();
241 bssl::UniquePtr<SSL_SESSION> session3 = NewSSLSession();
242 bssl::UniquePtr<SSL_SESSION> session4 = NewSSLSession();
243
244 // Insert three entries.
245 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
246 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session2));
247 cache.Insert(MakeTestKey("key3"), bssl::UpRef(session3));
248 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
249 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
250 EXPECT_EQ(session3.get(), cache.Lookup(MakeTestKey("key3")).get());
251 EXPECT_EQ(3u, cache.size());
252
253 // On insertion of a fourth, the first is removed.
254 cache.Insert(MakeTestKey("key4"), bssl::UpRef(session4));
255 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key1")).get());
256 EXPECT_EQ(session4.get(), cache.Lookup(MakeTestKey("key4")).get());
257 EXPECT_EQ(session3.get(), cache.Lookup(MakeTestKey("key3")).get());
258 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
259 EXPECT_EQ(3u, cache.size());
260
261 // Despite being newest, the next to be removed is session4 as it was accessed
262 // least. recently.
263 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
264 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
265 EXPECT_EQ(session2.get(), cache.Lookup(MakeTestKey("key2")).get());
266 EXPECT_EQ(session3.get(), cache.Lookup(MakeTestKey("key3")).get());
267 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key4")).get());
268 EXPECT_EQ(3u, cache.size());
269 }
270
271 // Tests that session expiration works properly.
TEST_F(SSLClientSessionCacheTest,Expiration)272 TEST_F(SSLClientSessionCacheTest, Expiration) {
273 const size_t kNumEntries = 20;
274 const size_t kExpirationCheckCount = 10;
275 const base::TimeDelta kTimeout = base::Seconds(1000);
276
277 SSLClientSessionCache::Config config;
278 config.expiration_check_count = kExpirationCheckCount;
279 std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock();
280 SSLClientSessionCache cache(config);
281 cache.SetClockForTesting(clock.get());
282
283 // Add |kNumEntries - 1| entries.
284 for (size_t i = 0; i < kNumEntries - 1; i++) {
285 bssl::UniquePtr<SSL_SESSION> session =
286 MakeTestSession(clock->Now(), kTimeout);
287 cache.Insert(MakeTestKey(base::NumberToString(i)), bssl::UpRef(session));
288 }
289 EXPECT_EQ(kNumEntries - 1, cache.size());
290
291 // Expire all the previous entries and insert one more entry.
292 clock->Advance(kTimeout * 2);
293 bssl::UniquePtr<SSL_SESSION> session =
294 MakeTestSession(clock->Now(), kTimeout);
295 cache.Insert(MakeTestKey("key"), bssl::UpRef(session));
296
297 // All entries are still in the cache.
298 EXPECT_EQ(kNumEntries, cache.size());
299
300 // Perform one fewer lookup than needed to trigger the expiration check. This
301 // shall not expire any session.
302 for (size_t i = 0; i < kExpirationCheckCount - 1; i++)
303 cache.Lookup(MakeTestKey("key"));
304
305 // All entries are still in the cache.
306 EXPECT_EQ(kNumEntries, cache.size());
307
308 // Perform one more lookup. This will expire all sessions but the last one.
309 cache.Lookup(MakeTestKey("key"));
310 EXPECT_EQ(1u, cache.size());
311 EXPECT_EQ(session.get(), cache.Lookup(MakeTestKey("key")).get());
312 for (size_t i = 0; i < kNumEntries - 1; i++) {
313 SCOPED_TRACE(i);
314 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey(base::NumberToString(i))));
315 }
316 }
317
318 // Tests that Lookup performs an expiration check before returning a cached
319 // session.
TEST_F(SSLClientSessionCacheTest,LookupExpirationCheck)320 TEST_F(SSLClientSessionCacheTest, LookupExpirationCheck) {
321 // kExpirationCheckCount is set to a suitably large number so the automated
322 // pruning never triggers.
323 const size_t kExpirationCheckCount = 1000;
324 const base::TimeDelta kTimeout = base::Seconds(1000);
325
326 SSLClientSessionCache::Config config;
327 config.expiration_check_count = kExpirationCheckCount;
328 std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock();
329 SSLClientSessionCache cache(config);
330 cache.SetClockForTesting(clock.get());
331
332 // Insert an entry into the session cache.
333 bssl::UniquePtr<SSL_SESSION> session =
334 MakeTestSession(clock->Now(), kTimeout);
335 cache.Insert(MakeTestKey("key"), bssl::UpRef(session));
336 EXPECT_EQ(session.get(), cache.Lookup(MakeTestKey("key")).get());
337 EXPECT_EQ(1u, cache.size());
338
339 // Expire the session.
340 clock->Advance(kTimeout * 2);
341
342 // The entry has not been removed yet.
343 EXPECT_EQ(1u, cache.size());
344
345 // But it will not be returned on lookup and gets pruned at that point.
346 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key")).get());
347 EXPECT_EQ(0u, cache.size());
348
349 // Re-inserting a session does not refresh the lifetime. The expiration
350 // information in the session is used.
351 cache.Insert(MakeTestKey("key"), bssl::UpRef(session));
352 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key")).get());
353 EXPECT_EQ(0u, cache.size());
354
355 // Re-insert a fresh copy of the session.
356 session = MakeTestSession(clock->Now(), kTimeout);
357 cache.Insert(MakeTestKey("key"), bssl::UpRef(session));
358 EXPECT_EQ(session.get(), cache.Lookup(MakeTestKey("key")).get());
359 EXPECT_EQ(1u, cache.size());
360
361 // Sessions also are treated as expired if the clock rewinds.
362 clock->Advance(base::Seconds(-2));
363 EXPECT_EQ(nullptr, cache.Lookup(MakeTestKey("key")).get());
364 EXPECT_EQ(0u, cache.size());
365 }
366
367 // Test that SSL cache is flushed on low memory notifications
TEST_F(SSLClientSessionCacheTest,TestFlushOnMemoryNotifications)368 TEST_F(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) {
369 base::test::TaskEnvironment task_environment;
370
371 // kExpirationCheckCount is set to a suitably large number so the automated
372 // pruning never triggers.
373 const size_t kExpirationCheckCount = 1000;
374 const base::TimeDelta kTimeout = base::Seconds(1000);
375
376 SSLClientSessionCache::Config config;
377 config.expiration_check_count = kExpirationCheckCount;
378 std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock();
379 SSLClientSessionCache cache(config);
380 cache.SetClockForTesting(clock.get());
381
382 // Insert an entry into the session cache.
383 bssl::UniquePtr<SSL_SESSION> session1 =
384 MakeTestSession(clock->Now(), kTimeout);
385 cache.Insert(MakeTestKey("key1"), bssl::UpRef(session1));
386 EXPECT_EQ(session1.get(), cache.Lookup(MakeTestKey("key1")).get());
387 EXPECT_EQ(1u, cache.size());
388
389 // Expire the session.
390 clock->Advance(kTimeout * 2);
391 // Add one more session.
392 bssl::UniquePtr<SSL_SESSION> session2 =
393 MakeTestSession(clock->Now(), kTimeout);
394 cache.Insert(MakeTestKey("key2"), bssl::UpRef(session2));
395 EXPECT_EQ(2u, cache.size());
396
397 // Fire a notification that will flush expired sessions.
398 base::MemoryPressureListener::NotifyMemoryPressure(
399 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
400 base::RunLoop().RunUntilIdle();
401
402 // Expired session's cache should be flushed.
403 // Lookup returns nullptr, when cache entry not found.
404 EXPECT_FALSE(cache.Lookup(MakeTestKey("key1")));
405 EXPECT_TRUE(cache.Lookup(MakeTestKey("key2")));
406 EXPECT_EQ(1u, cache.size());
407
408 // Fire notification that will flush everything.
409 base::MemoryPressureListener::NotifyMemoryPressure(
410 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
411 base::RunLoop().RunUntilIdle();
412 EXPECT_EQ(0u, cache.size());
413 }
414
TEST_F(SSLClientSessionCacheTest,FlushForServer)415 TEST_F(SSLClientSessionCacheTest, FlushForServer) {
416 SSLClientSessionCache::Config config;
417 SSLClientSessionCache cache(config);
418
419 const SchemefulSite kSiteA(GURL("https://a.test"));
420 const SchemefulSite kSiteB(GURL("https://b.test"));
421
422 // Insert a number of cache entries.
423 SSLClientSessionCache::Key key1;
424 key1.server = HostPortPair("a.test", 443);
425 auto session1 = NewSSLSession();
426 cache.Insert(key1, bssl::UpRef(session1));
427
428 SSLClientSessionCache::Key key2;
429 key2.server = HostPortPair("a.test", 443);
430 key2.dest_ip_addr = IPAddress::IPv4Localhost();
431 key2.network_anonymization_key =
432 NetworkAnonymizationKey::CreateSameSite(kSiteB);
433 key2.privacy_mode = PRIVACY_MODE_ENABLED;
434 auto session2 = NewSSLSession();
435 cache.Insert(key2, bssl::UpRef(session2));
436
437 SSLClientSessionCache::Key key3;
438 key3.server = HostPortPair("a.test", 444);
439 auto session3 = NewSSLSession();
440 cache.Insert(key3, bssl::UpRef(session3));
441
442 SSLClientSessionCache::Key key4;
443 key4.server = HostPortPair("b.test", 443);
444 auto session4 = NewSSLSession();
445 cache.Insert(key4, bssl::UpRef(session4));
446
447 SSLClientSessionCache::Key key5;
448 key5.server = HostPortPair("b.test", 443);
449 key5.network_anonymization_key =
450 NetworkAnonymizationKey::CreateSameSite(kSiteA);
451 auto session5 = NewSSLSession();
452 cache.Insert(key5, bssl::UpRef(session5));
453
454 // Flush an unrelated server. The cache should be unaffected.
455 cache.FlushForServers({HostPortPair("c.test", 443)});
456 EXPECT_EQ(5u, cache.size());
457 EXPECT_EQ(session1.get(), cache.Lookup(key1).get());
458 EXPECT_EQ(session2.get(), cache.Lookup(key2).get());
459 EXPECT_EQ(session3.get(), cache.Lookup(key3).get());
460 EXPECT_EQ(session4.get(), cache.Lookup(key4).get());
461 EXPECT_EQ(session5.get(), cache.Lookup(key5).get());
462
463 // Flush a.test:443. |key1| and |key2| should match, but not the others.
464 cache.FlushForServers({HostPortPair("a.test", 443)});
465 EXPECT_EQ(3u, cache.size());
466 EXPECT_EQ(nullptr, cache.Lookup(key1).get());
467 EXPECT_EQ(nullptr, cache.Lookup(key2).get());
468 EXPECT_EQ(session3.get(), cache.Lookup(key3).get());
469 EXPECT_EQ(session4.get(), cache.Lookup(key4).get());
470 EXPECT_EQ(session5.get(), cache.Lookup(key5).get());
471
472 // Flush b.test:443. |key4| and |key5| match, but not |key3|.
473 cache.FlushForServers({HostPortPair("b.test", 443)});
474 EXPECT_EQ(1u, cache.size());
475 EXPECT_EQ(nullptr, cache.Lookup(key1).get());
476 EXPECT_EQ(nullptr, cache.Lookup(key2).get());
477 EXPECT_EQ(session3.get(), cache.Lookup(key3).get());
478 EXPECT_EQ(nullptr, cache.Lookup(key4).get());
479 EXPECT_EQ(nullptr, cache.Lookup(key5).get());
480
481 // Flush the last host, a.test:444.
482 cache.FlushForServers({HostPortPair("a.test", 444)});
483 EXPECT_EQ(0u, cache.size());
484 EXPECT_EQ(nullptr, cache.Lookup(key1).get());
485 EXPECT_EQ(nullptr, cache.Lookup(key2).get());
486 EXPECT_EQ(nullptr, cache.Lookup(key3).get());
487 EXPECT_EQ(nullptr, cache.Lookup(key4).get());
488 EXPECT_EQ(nullptr, cache.Lookup(key5).get());
489 }
490
TEST_F(SSLClientSessionCacheTest,FlushForServers)491 TEST_F(SSLClientSessionCacheTest, FlushForServers) {
492 SSLClientSessionCache::Config config;
493 SSLClientSessionCache cache(config);
494
495 const SchemefulSite kSiteA(GURL("https://a.test"));
496 const SchemefulSite kSiteB(GURL("https://b.test"));
497
498 // Insert a number of cache entries.
499 SSLClientSessionCache::Key key1;
500 key1.server = HostPortPair("a.test", 443);
501 auto session1 = NewSSLSession();
502 cache.Insert(key1, bssl::UpRef(session1));
503
504 SSLClientSessionCache::Key key2;
505 key2.server = HostPortPair("a.test", 443);
506 key2.dest_ip_addr = IPAddress::IPv4Localhost();
507 key2.network_anonymization_key =
508 NetworkAnonymizationKey::CreateSameSite(kSiteB);
509 key2.privacy_mode = PRIVACY_MODE_ENABLED;
510 auto session2 = NewSSLSession();
511 cache.Insert(key2, bssl::UpRef(session2));
512
513 SSLClientSessionCache::Key key3;
514 key3.server = HostPortPair("a.test", 444);
515 auto session3 = NewSSLSession();
516 cache.Insert(key3, bssl::UpRef(session3));
517
518 SSLClientSessionCache::Key key4;
519 key4.server = HostPortPair("b.test", 443);
520 auto session4 = NewSSLSession();
521 cache.Insert(key4, bssl::UpRef(session4));
522
523 SSLClientSessionCache::Key key5;
524 key5.server = HostPortPair("b.test", 443);
525 key5.network_anonymization_key =
526 NetworkAnonymizationKey::CreateSameSite(kSiteA);
527 auto session5 = NewSSLSession();
528 cache.Insert(key5, bssl::UpRef(session5));
529
530 cache.FlushForServers({
531 // Unrelated server. Should have no effect.
532 HostPortPair("c.test", 443),
533 // Flush a.test:443. |key1| and |key2| should match, but not the others.
534 HostPortPair("a.test", 443),
535 // Flush b.test:443. |key4| and |key5| match, but not |key3|.
536 HostPortPair("b.test", 443),
537 });
538 EXPECT_EQ(1u, cache.size());
539 EXPECT_EQ(nullptr, cache.Lookup(key1).get());
540 EXPECT_EQ(nullptr, cache.Lookup(key2).get());
541 EXPECT_EQ(session3.get(), cache.Lookup(key3).get());
542 EXPECT_EQ(nullptr, cache.Lookup(key4).get());
543 EXPECT_EQ(nullptr, cache.Lookup(key5).get());
544 }
545
546 } // namespace net
547