OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/ssl/ssl_client_session_cache.h" | 5 #include "net/ssl/ssl_client_session_cache.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/test/simple_test_clock.h" | 10 #include "base/test/simple_test_clock.h" |
| 11 #include "base/time/time.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "third_party/boringssl/src/include/openssl/ssl.h" | 13 #include "third_party/boringssl/src/include/openssl/ssl.h" |
13 | 14 |
14 namespace net { | 15 namespace net { |
15 | 16 |
| 17 namespace { |
| 18 |
| 19 std::unique_ptr<base::SimpleTestClock> MakeTestClock() { |
| 20 std::unique_ptr<base::SimpleTestClock> clock = |
| 21 base::MakeUnique<base::SimpleTestClock>(); |
| 22 // SimpleTestClock starts at the null base::Time which converts to and from |
| 23 // time_t confusingly. |
| 24 clock->SetNow(base::Time::FromTimeT(1000000000)); |
| 25 return clock; |
| 26 } |
| 27 |
| 28 bssl::UniquePtr<SSL_SESSION> MakeTestSession(base::Time now, |
| 29 base::TimeDelta timeout) { |
| 30 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); |
| 31 SSL_SESSION_set_time(session.get(), now.ToTimeT()); |
| 32 SSL_SESSION_set_timeout(session.get(), timeout.InSeconds()); |
| 33 return session; |
| 34 } |
| 35 |
| 36 } // namespace |
| 37 |
16 // Test basic insertion and lookup operations. | 38 // Test basic insertion and lookup operations. |
17 TEST(SSLClientSessionCacheTest, Basic) { | 39 TEST(SSLClientSessionCacheTest, Basic) { |
18 SSLClientSessionCache::Config config; | 40 SSLClientSessionCache::Config config; |
19 SSLClientSessionCache cache(config); | 41 SSLClientSessionCache cache(config); |
20 | 42 |
21 bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new()); | 43 bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new()); |
22 bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new()); | 44 bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new()); |
23 bssl::UniquePtr<SSL_SESSION> session3(SSL_SESSION_new()); | 45 bssl::UniquePtr<SSL_SESSION> session3(SSL_SESSION_new()); |
24 EXPECT_EQ(1u, session1->references); | 46 EXPECT_EQ(1u, session1->references); |
25 EXPECT_EQ(1u, session2->references); | 47 EXPECT_EQ(1u, session2->references); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 } | 158 } |
137 | 159 |
138 // Tests that session expiration works properly. | 160 // Tests that session expiration works properly. |
139 TEST(SSLClientSessionCacheTest, Expiration) { | 161 TEST(SSLClientSessionCacheTest, Expiration) { |
140 const size_t kNumEntries = 20; | 162 const size_t kNumEntries = 20; |
141 const size_t kExpirationCheckCount = 10; | 163 const size_t kExpirationCheckCount = 10; |
142 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | 164 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); |
143 | 165 |
144 SSLClientSessionCache::Config config; | 166 SSLClientSessionCache::Config config; |
145 config.expiration_check_count = kExpirationCheckCount; | 167 config.expiration_check_count = kExpirationCheckCount; |
146 config.timeout = kTimeout; | |
147 SSLClientSessionCache cache(config); | 168 SSLClientSessionCache cache(config); |
148 base::SimpleTestClock* clock = new base::SimpleTestClock; | 169 base::SimpleTestClock* clock = MakeTestClock().release(); |
149 cache.SetClockForTesting(base::WrapUnique(clock)); | 170 cache.SetClockForTesting(base::WrapUnique(clock)); |
150 | 171 |
151 // Add |kNumEntries - 1| entries. | 172 // Add |kNumEntries - 1| entries. |
152 for (size_t i = 0; i < kNumEntries - 1; i++) { | 173 for (size_t i = 0; i < kNumEntries - 1; i++) { |
153 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); | 174 bssl::UniquePtr<SSL_SESSION> session = |
| 175 MakeTestSession(clock->Now(), kTimeout); |
154 cache.Insert(base::SizeTToString(i), session.get()); | 176 cache.Insert(base::SizeTToString(i), session.get()); |
155 } | 177 } |
156 EXPECT_EQ(kNumEntries - 1, cache.size()); | 178 EXPECT_EQ(kNumEntries - 1, cache.size()); |
157 | 179 |
158 // Expire all the previous entries and insert one more entry. | 180 // Expire all the previous entries and insert one more entry. |
159 clock->Advance(kTimeout * 2); | 181 clock->Advance(kTimeout * 2); |
160 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); | 182 bssl::UniquePtr<SSL_SESSION> session = |
| 183 MakeTestSession(clock->Now(), kTimeout); |
161 cache.Insert("key", session.get()); | 184 cache.Insert("key", session.get()); |
162 | 185 |
163 // All entries are still in the cache. | 186 // All entries are still in the cache. |
164 EXPECT_EQ(kNumEntries, cache.size()); | 187 EXPECT_EQ(kNumEntries, cache.size()); |
165 | 188 |
166 // Perform one fewer lookup than needed to trigger the expiration check. This | 189 // Perform one fewer lookup than needed to trigger the expiration check. This |
167 // shall not expire any session. | 190 // shall not expire any session. |
168 for (size_t i = 0; i < kExpirationCheckCount - 1; i++) | 191 for (size_t i = 0; i < kExpirationCheckCount - 1; i++) |
169 cache.Lookup("key"); | 192 cache.Lookup("key"); |
170 | 193 |
(...skipping 13 matching lines...) Expand all Loading... |
184 // Tests that Lookup performs an expiration check before returning a cached | 207 // Tests that Lookup performs an expiration check before returning a cached |
185 // session. | 208 // session. |
186 TEST(SSLClientSessionCacheTest, LookupExpirationCheck) { | 209 TEST(SSLClientSessionCacheTest, LookupExpirationCheck) { |
187 // kExpirationCheckCount is set to a suitably large number so the automated | 210 // kExpirationCheckCount is set to a suitably large number so the automated |
188 // pruning never triggers. | 211 // pruning never triggers. |
189 const size_t kExpirationCheckCount = 1000; | 212 const size_t kExpirationCheckCount = 1000; |
190 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | 213 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); |
191 | 214 |
192 SSLClientSessionCache::Config config; | 215 SSLClientSessionCache::Config config; |
193 config.expiration_check_count = kExpirationCheckCount; | 216 config.expiration_check_count = kExpirationCheckCount; |
194 config.timeout = kTimeout; | |
195 SSLClientSessionCache cache(config); | 217 SSLClientSessionCache cache(config); |
196 base::SimpleTestClock* clock = new base::SimpleTestClock; | 218 base::SimpleTestClock* clock = MakeTestClock().release(); |
197 cache.SetClockForTesting(base::WrapUnique(clock)); | 219 cache.SetClockForTesting(base::WrapUnique(clock)); |
198 | 220 |
199 // Insert an entry into the session cache. | 221 // Insert an entry into the session cache. |
200 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); | 222 bssl::UniquePtr<SSL_SESSION> session = |
| 223 MakeTestSession(clock->Now(), kTimeout); |
201 cache.Insert("key", session.get()); | 224 cache.Insert("key", session.get()); |
202 EXPECT_EQ(session.get(), cache.Lookup("key").get()); | 225 EXPECT_EQ(session.get(), cache.Lookup("key").get()); |
203 EXPECT_EQ(1u, cache.size()); | 226 EXPECT_EQ(1u, cache.size()); |
204 | 227 |
205 // Expire the session. | 228 // Expire the session. |
206 clock->Advance(kTimeout * 2); | 229 clock->Advance(kTimeout * 2); |
207 | 230 |
208 // The entry has not been removed yet. | 231 // The entry has not been removed yet. |
209 EXPECT_EQ(1u, cache.size()); | 232 EXPECT_EQ(1u, cache.size()); |
210 | 233 |
211 // But it will not be returned on lookup and gets pruned at that point. | 234 // But it will not be returned on lookup and gets pruned at that point. |
212 EXPECT_EQ(nullptr, cache.Lookup("key").get()); | 235 EXPECT_EQ(nullptr, cache.Lookup("key").get()); |
213 EXPECT_EQ(0u, cache.size()); | 236 EXPECT_EQ(0u, cache.size()); |
214 | 237 |
215 // Sessions also are treated as expired if the clock rewinds. | 238 // Re-inserting a session does not refresh the lifetime. The expiration |
| 239 // information in the session is used. |
| 240 cache.Insert("key", session.get()); |
| 241 EXPECT_EQ(nullptr, cache.Lookup("key").get()); |
| 242 EXPECT_EQ(0u, cache.size()); |
| 243 |
| 244 // Re-insert a fresh copy of the session. |
| 245 session = MakeTestSession(clock->Now(), kTimeout); |
216 cache.Insert("key", session.get()); | 246 cache.Insert("key", session.get()); |
217 EXPECT_EQ(session.get(), cache.Lookup("key").get()); | 247 EXPECT_EQ(session.get(), cache.Lookup("key").get()); |
218 EXPECT_EQ(1u, cache.size()); | 248 EXPECT_EQ(1u, cache.size()); |
219 | 249 |
220 clock->Advance(-kTimeout * 2); | 250 // Sessions also are treated as expired if the clock rewinds. |
221 | 251 clock->Advance(base::TimeDelta::FromSeconds(-1)); |
222 EXPECT_EQ(nullptr, cache.Lookup("key").get()); | 252 EXPECT_EQ(nullptr, cache.Lookup("key").get()); |
223 EXPECT_EQ(0u, cache.size()); | 253 EXPECT_EQ(0u, cache.size()); |
224 } | 254 } |
225 | 255 |
226 // Test that SSL cache is flushed on low memory notifications | 256 // Test that SSL cache is flushed on low memory notifications |
227 TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) { | 257 TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) { |
228 // kExpirationCheckCount is set to a suitably large number so the automated | 258 // kExpirationCheckCount is set to a suitably large number so the automated |
229 // pruning never triggers. | 259 // pruning never triggers. |
230 const size_t kExpirationCheckCount = 1000; | 260 const size_t kExpirationCheckCount = 1000; |
231 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | 261 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); |
232 | 262 |
233 SSLClientSessionCache::Config config; | 263 SSLClientSessionCache::Config config; |
234 config.expiration_check_count = kExpirationCheckCount; | 264 config.expiration_check_count = kExpirationCheckCount; |
235 config.timeout = kTimeout; | |
236 SSLClientSessionCache cache(config); | 265 SSLClientSessionCache cache(config); |
237 base::SimpleTestClock* clock = new base::SimpleTestClock; | 266 base::SimpleTestClock* clock = MakeTestClock().release(); |
238 cache.SetClockForTesting(base::WrapUnique(clock)); | 267 cache.SetClockForTesting(base::WrapUnique(clock)); |
239 | 268 |
240 // Insert an entry into the session cache. | 269 // Insert an entry into the session cache. |
241 bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new()); | 270 bssl::UniquePtr<SSL_SESSION> session1 = |
| 271 MakeTestSession(clock->Now(), kTimeout); |
242 cache.Insert("key1", session1.get()); | 272 cache.Insert("key1", session1.get()); |
243 EXPECT_EQ(session1.get(), cache.Lookup("key1").get()); | 273 EXPECT_EQ(session1.get(), cache.Lookup("key1").get()); |
244 EXPECT_EQ(1u, cache.size()); | 274 EXPECT_EQ(1u, cache.size()); |
245 | 275 |
246 // Expire the session. | 276 // Expire the session. |
247 clock->Advance(kTimeout * 2); | 277 clock->Advance(kTimeout * 2); |
248 // Add one more session. | 278 // Add one more session. |
249 bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new()); | 279 bssl::UniquePtr<SSL_SESSION> session2 = |
| 280 MakeTestSession(clock->Now(), kTimeout); |
250 cache.Insert("key2", session2.get()); | 281 cache.Insert("key2", session2.get()); |
251 EXPECT_EQ(2u, cache.size()); | 282 EXPECT_EQ(2u, cache.size()); |
252 | 283 |
253 // Fire a notification that will flush expired sessions. | 284 // Fire a notification that will flush expired sessions. |
254 base::MemoryPressureListener::NotifyMemoryPressure( | 285 base::MemoryPressureListener::NotifyMemoryPressure( |
255 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); | 286 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); |
256 base::RunLoop().RunUntilIdle(); | 287 base::RunLoop().RunUntilIdle(); |
257 | 288 |
258 // Expired session's cache should be flushed. | 289 // Expired session's cache should be flushed. |
259 // Lookup returns nullptr, when cache entry not found. | 290 // Lookup returns nullptr, when cache entry not found. |
260 EXPECT_FALSE(cache.Lookup("key1")); | 291 EXPECT_FALSE(cache.Lookup("key1")); |
261 EXPECT_TRUE(cache.Lookup("key2")); | 292 EXPECT_TRUE(cache.Lookup("key2")); |
262 EXPECT_EQ(1u, cache.size()); | 293 EXPECT_EQ(1u, cache.size()); |
263 | 294 |
264 // Fire notification that will flush everything. | 295 // Fire notification that will flush everything. |
265 base::MemoryPressureListener::NotifyMemoryPressure( | 296 base::MemoryPressureListener::NotifyMemoryPressure( |
266 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); | 297 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); |
267 base::RunLoop().RunUntilIdle(); | 298 base::RunLoop().RunUntilIdle(); |
268 EXPECT_EQ(0u, cache.size()); | 299 EXPECT_EQ(0u, cache.size()); |
269 } | 300 } |
270 | 301 |
271 } // namespace net | 302 } // namespace net |
OLD | NEW |