OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/ssl/ssl_client_session_cache_openssl.h" | |
6 | |
7 #include <openssl/ssl.h> | |
8 | |
9 #include "base/strings/string_number_conversions.h" | |
10 #include "base/test/simple_test_clock.h" | |
11 #include "net/ssl/scoped_openssl_types.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 namespace net { | |
15 | |
16 // Test basic insertion and lookup operations. | |
17 TEST(SSLClientSessionCacheOpenSSLTest, Basic) { | |
18 SSLClientSessionCacheOpenSSL::Config config; | |
19 SSLClientSessionCacheOpenSSL cache(config); | |
20 | |
21 ScopedSSL_SESSION session1(SSL_SESSION_new()); | |
22 ScopedSSL_SESSION session2(SSL_SESSION_new()); | |
23 ScopedSSL_SESSION session3(SSL_SESSION_new()); | |
24 EXPECT_EQ(1, session1->references); | |
25 EXPECT_EQ(1, session2->references); | |
26 EXPECT_EQ(1, session3->references); | |
27 | |
28 EXPECT_EQ(nullptr, cache.Lookup("key1")); | |
29 EXPECT_EQ(nullptr, cache.Lookup("key2")); | |
30 EXPECT_EQ(0u, cache.size()); | |
31 | |
32 cache.Insert("key1", session1.get()); | |
33 EXPECT_EQ(session1.get(), cache.Lookup("key1")); | |
34 EXPECT_EQ(nullptr, cache.Lookup("key2")); | |
35 EXPECT_EQ(1u, cache.size()); | |
36 | |
37 cache.Insert("key2", session2.get()); | |
38 EXPECT_EQ(session1.get(), cache.Lookup("key1")); | |
39 EXPECT_EQ(session2.get(), cache.Lookup("key2")); | |
40 EXPECT_EQ(2u, cache.size()); | |
41 | |
42 EXPECT_EQ(2, session1->references); | |
43 EXPECT_EQ(2, session2->references); | |
44 | |
45 cache.Insert("key1", session3.get()); | |
46 EXPECT_EQ(session3.get(), cache.Lookup("key1")); | |
Ryan Sleevi
2015/04/02 20:00:14
EXPECT_NEQ(session3.get(), session1.get()) ?
davidben
2015/04/03 00:37:11
Er. That's just asserting that SSL_SESSION_new ret
Ryan Sleevi
2015/04/03 00:59:02
Well, and that no one accidentally stores a pointe
davidben
2015/04/07 18:35:36
But that can be determined trivially by inspection
| |
47 EXPECT_EQ(session2.get(), cache.Lookup("key2")); | |
48 EXPECT_EQ(2u, cache.size()); | |
49 | |
50 EXPECT_EQ(1, session1->references); | |
51 EXPECT_EQ(2, session2->references); | |
52 EXPECT_EQ(2, session3->references); | |
53 | |
54 cache.Flush(); | |
55 EXPECT_EQ(nullptr, cache.Lookup("key1")); | |
56 EXPECT_EQ(nullptr, cache.Lookup("key2")); | |
57 EXPECT_EQ(nullptr, cache.Lookup("key3")); | |
58 EXPECT_EQ(0u, cache.size()); | |
59 | |
60 EXPECT_EQ(1, session1->references); | |
61 EXPECT_EQ(1, session2->references); | |
62 EXPECT_EQ(1, session3->references); | |
63 } | |
64 | |
65 // Test that a session may be inserted at two different keys. This should never | |
66 // be necessary, but the API doesn't prohibit it. | |
67 TEST(SSLClientSessionCacheOpenSSLTest, DoubleInsert) { | |
68 SSLClientSessionCacheOpenSSL::Config config; | |
69 SSLClientSessionCacheOpenSSL cache(config); | |
70 | |
71 ScopedSSL_SESSION session(SSL_SESSION_new()); | |
72 EXPECT_EQ(1, session->references); | |
73 | |
74 EXPECT_EQ(nullptr, cache.Lookup("key1")); | |
75 EXPECT_EQ(nullptr, cache.Lookup("key2")); | |
76 EXPECT_EQ(0u, cache.size()); | |
77 | |
78 cache.Insert("key1", session.get()); | |
79 EXPECT_EQ(session.get(), cache.Lookup("key1")); | |
80 EXPECT_EQ(nullptr, cache.Lookup("key2")); | |
81 EXPECT_EQ(1u, cache.size()); | |
82 | |
83 EXPECT_EQ(2, session->references); | |
84 | |
85 cache.Insert("key2", session.get()); | |
86 EXPECT_EQ(session.get(), cache.Lookup("key1")); | |
87 EXPECT_EQ(session.get(), cache.Lookup("key2")); | |
88 EXPECT_EQ(2u, cache.size()); | |
89 | |
90 EXPECT_EQ(3, session->references); | |
91 | |
92 cache.Flush(); | |
93 EXPECT_EQ(nullptr, cache.Lookup("key1")); | |
94 EXPECT_EQ(nullptr, cache.Lookup("key2")); | |
95 EXPECT_EQ(0u, cache.size()); | |
96 | |
97 EXPECT_EQ(1, session->references); | |
98 } | |
99 | |
100 // Tests that the session cache's size is correctly bounded. | |
101 TEST(SSLClientSessionCacheOpenSSLTest, MaxEntries) { | |
102 SSLClientSessionCacheOpenSSL::Config config; | |
103 config.max_entries = 3; | |
104 SSLClientSessionCacheOpenSSL cache(config); | |
105 base::SimpleTestClock* clock = new base::SimpleTestClock; | |
Ryan Sleevi
2015/04/02 20:00:14
Why store the naked pointer? It's unused.
davidben
2015/04/03 00:37:11
Copy-pasta. Removed.
| |
106 cache.SetClockForTesting(make_scoped_ptr(clock)); | |
107 | |
108 ScopedSSL_SESSION session1(SSL_SESSION_new()); | |
109 ScopedSSL_SESSION session2(SSL_SESSION_new()); | |
110 ScopedSSL_SESSION session3(SSL_SESSION_new()); | |
111 ScopedSSL_SESSION session4(SSL_SESSION_new()); | |
112 | |
113 // Insert three entries. | |
114 cache.Insert("key1", session1.get()); | |
115 cache.Insert("key2", session2.get()); | |
116 cache.Insert("key3", session3.get()); | |
117 EXPECT_EQ(session1.get(), cache.Lookup("key1")); | |
118 EXPECT_EQ(session2.get(), cache.Lookup("key2")); | |
119 EXPECT_EQ(session3.get(), cache.Lookup("key3")); | |
120 EXPECT_EQ(3u, cache.size()); | |
121 | |
122 // On insertion of a fourth, the first is removed. | |
123 cache.Insert("key4", session4.get()); | |
124 EXPECT_EQ(nullptr, cache.Lookup("key1")); | |
125 EXPECT_EQ(session4.get(), cache.Lookup("key4")); | |
126 EXPECT_EQ(session3.get(), cache.Lookup("key3")); | |
127 EXPECT_EQ(session2.get(), cache.Lookup("key2")); | |
128 EXPECT_EQ(3u, cache.size()); | |
129 | |
130 // Despite being newest, the next to be removed is session4 as it was accessed | |
131 // least. recently. | |
132 cache.Insert("key1", session1.get()); | |
133 EXPECT_EQ(session1.get(), cache.Lookup("key1")); | |
134 EXPECT_EQ(session2.get(), cache.Lookup("key2")); | |
135 EXPECT_EQ(session3.get(), cache.Lookup("key3")); | |
136 EXPECT_EQ(nullptr, cache.Lookup("key4")); | |
137 EXPECT_EQ(3u, cache.size()); | |
138 } | |
139 | |
140 // Tests that session expiration works properly. | |
141 TEST(SSLClientSessionCacheOpenSSLTest, Expiration) { | |
142 const size_t kNumEntries = 20; | |
143 const size_t kExpirationCheckCount = 10; | |
144 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | |
145 | |
146 SSLClientSessionCacheOpenSSL::Config config; | |
147 config.expiration_check_count = kExpirationCheckCount; | |
148 config.timeout = kTimeout; | |
149 SSLClientSessionCacheOpenSSL cache(config); | |
150 base::SimpleTestClock* clock = new base::SimpleTestClock; | |
151 cache.SetClockForTesting(make_scoped_ptr(clock)); | |
152 | |
153 // Add |kNumEntries - 1| entries. | |
154 for (size_t i = 0; i < kNumEntries - 1; i++) { | |
155 ScopedSSL_SESSION session(SSL_SESSION_new()); | |
156 cache.Insert(base::SizeTToString(i), session.get()); | |
157 } | |
158 EXPECT_EQ(kNumEntries - 1, cache.size()); | |
159 | |
160 // Expire all the previous entries and insert one more entry. | |
161 clock->Advance(kTimeout * 2); | |
162 ScopedSSL_SESSION session(SSL_SESSION_new()); | |
163 cache.Insert("key", session.get()); | |
164 | |
165 // All entries are still in the cache. | |
166 EXPECT_EQ(kNumEntries, cache.size()); | |
167 | |
168 // Perform one fewer lookup than needed to trigger the expiration check. This | |
169 // shall not expire any session. | |
170 for (size_t i = 0; i < kExpirationCheckCount - 1; i++) | |
171 cache.Lookup("key"); | |
172 | |
173 // All entries are still in the cache. | |
174 EXPECT_EQ(kNumEntries, cache.size()); | |
175 | |
176 // Perform one more lookup. This will expire all sessions but the last one. | |
177 cache.Lookup("key"); | |
178 EXPECT_EQ(1u, cache.size()); | |
179 EXPECT_EQ(session.get(), cache.Lookup("key")); | |
180 for (size_t i = 0; i < kNumEntries - 1; i++) { | |
181 SCOPED_TRACE(i); | |
182 EXPECT_EQ(nullptr, cache.Lookup(base::SizeTToString(i))); | |
183 } | |
184 } | |
185 | |
186 // Tests that Lookup performs an expiration check before returning a cached | |
187 // session. | |
188 TEST(SSLClientSessionCacheOpenSSLTest, LookupExpirationCheck) { | |
189 // kExpirationCheckCount is set to a suitably large number so the automated | |
190 // pruning never triggers. | |
191 const size_t kExpirationCheckCount = 1000; | |
192 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | |
193 | |
194 SSLClientSessionCacheOpenSSL::Config config; | |
195 config.expiration_check_count = kExpirationCheckCount; | |
196 config.timeout = kTimeout; | |
197 SSLClientSessionCacheOpenSSL cache(config); | |
198 base::SimpleTestClock* clock = new base::SimpleTestClock; | |
199 cache.SetClockForTesting(make_scoped_ptr(clock)); | |
200 | |
201 // Insert an entry into the session cache. | |
202 ScopedSSL_SESSION session(SSL_SESSION_new()); | |
203 cache.Insert("key", session.get()); | |
204 EXPECT_EQ(session.get(), cache.Lookup("key")); | |
205 EXPECT_EQ(1u, cache.size()); | |
206 | |
207 // Expire the session. | |
208 clock->Advance(kTimeout * 2); | |
209 | |
210 // The entry has not been removed yet. | |
211 EXPECT_EQ(1u, cache.size()); | |
212 | |
213 // But it will not be returned on lookup and gets pruned at that point. | |
214 EXPECT_EQ(nullptr, cache.Lookup("key")); | |
215 EXPECT_EQ(0u, cache.size()); | |
216 | |
217 // Sessions also are treated as expired if the clock rewinds. | |
218 cache.Insert("key", session.get()); | |
219 EXPECT_EQ(session.get(), cache.Lookup("key")); | |
220 EXPECT_EQ(1u, cache.size()); | |
221 | |
222 clock->Advance(-kTimeout * 2); | |
223 | |
224 EXPECT_EQ(nullptr, cache.Lookup("key")); | |
225 EXPECT_EQ(0u, cache.size()); | |
226 } | |
227 | |
228 } // namespace net | |
OLD | NEW |