xref: /aosp_15_r20/external/cronet/net/ssl/ssl_client_session_cache_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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