Blink roll 173193:173208
[chromium-blink-merge.git] / net / ssl / default_server_bound_cert_store_unittest.cc
bloba742e0c3f1cf4a697ed1e2d805fd6516273b965d
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.
5 #include "net/ssl/default_server_bound_cert_store.h"
7 #include <map>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "net/base/net_errors.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace net {
21 namespace {
23 void CallCounter(int* counter) {
24 (*counter)++;
27 void GetCertCallbackNotCalled(int err,
28 const std::string& server_identifier,
29 base::Time expiration_time,
30 const std::string& private_key_result,
31 const std::string& cert_result) {
32 ADD_FAILURE() << "Unexpected callback execution.";
35 class AsyncGetCertHelper {
36 public:
37 AsyncGetCertHelper() : called_(false) {}
39 void Callback(int err,
40 const std::string& server_identifier,
41 base::Time expiration_time,
42 const std::string& private_key_result,
43 const std::string& cert_result) {
44 err_ = err;
45 server_identifier_ = server_identifier;
46 expiration_time_ = expiration_time;
47 private_key_ = private_key_result;
48 cert_ = cert_result;
49 called_ = true;
52 int err_;
53 std::string server_identifier_;
54 base::Time expiration_time_;
55 std::string private_key_;
56 std::string cert_;
57 bool called_;
60 void GetAllCallback(
61 ServerBoundCertStore::ServerBoundCertList* dest,
62 const ServerBoundCertStore::ServerBoundCertList& result) {
63 *dest = result;
66 class MockPersistentStore
67 : public DefaultServerBoundCertStore::PersistentStore {
68 public:
69 MockPersistentStore();
71 // DefaultServerBoundCertStore::PersistentStore implementation.
72 virtual void Load(const LoadedCallback& loaded_callback) OVERRIDE;
73 virtual void AddServerBoundCert(
74 const DefaultServerBoundCertStore::ServerBoundCert& cert) OVERRIDE;
75 virtual void DeleteServerBoundCert(
76 const DefaultServerBoundCertStore::ServerBoundCert& cert) OVERRIDE;
77 virtual void SetForceKeepSessionState() OVERRIDE;
79 protected:
80 virtual ~MockPersistentStore();
82 private:
83 typedef std::map<std::string, DefaultServerBoundCertStore::ServerBoundCert>
84 ServerBoundCertMap;
86 ServerBoundCertMap origin_certs_;
89 MockPersistentStore::MockPersistentStore() {}
91 void MockPersistentStore::Load(const LoadedCallback& loaded_callback) {
92 scoped_ptr<ScopedVector<DefaultServerBoundCertStore::ServerBoundCert> >
93 certs(new ScopedVector<DefaultServerBoundCertStore::ServerBoundCert>());
94 ServerBoundCertMap::iterator it;
96 for (it = origin_certs_.begin(); it != origin_certs_.end(); ++it) {
97 certs->push_back(
98 new DefaultServerBoundCertStore::ServerBoundCert(it->second));
101 base::MessageLoop::current()->PostTask(
102 FROM_HERE, base::Bind(loaded_callback, base::Passed(&certs)));
105 void MockPersistentStore::AddServerBoundCert(
106 const DefaultServerBoundCertStore::ServerBoundCert& cert) {
107 origin_certs_[cert.server_identifier()] = cert;
110 void MockPersistentStore::DeleteServerBoundCert(
111 const DefaultServerBoundCertStore::ServerBoundCert& cert) {
112 origin_certs_.erase(cert.server_identifier());
115 void MockPersistentStore::SetForceKeepSessionState() {}
117 MockPersistentStore::~MockPersistentStore() {}
119 } // namespace
121 TEST(DefaultServerBoundCertStoreTest, TestLoading) {
122 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
124 persistent_store->AddServerBoundCert(
125 DefaultServerBoundCertStore::ServerBoundCert(
126 "google.com",
127 base::Time(),
128 base::Time(),
129 "a", "b"));
130 persistent_store->AddServerBoundCert(
131 DefaultServerBoundCertStore::ServerBoundCert(
132 "verisign.com",
133 base::Time(),
134 base::Time(),
135 "c", "d"));
137 // Make sure certs load properly.
138 DefaultServerBoundCertStore store(persistent_store.get());
139 // Load has not occurred yet.
140 EXPECT_EQ(0, store.GetCertCount());
141 store.SetServerBoundCert(
142 "verisign.com",
143 base::Time(),
144 base::Time(),
145 "e", "f");
146 // Wait for load & queued set task.
147 base::MessageLoop::current()->RunUntilIdle();
148 EXPECT_EQ(2, store.GetCertCount());
149 store.SetServerBoundCert(
150 "twitter.com",
151 base::Time(),
152 base::Time(),
153 "g", "h");
154 // Set should be synchronous now that load is done.
155 EXPECT_EQ(3, store.GetCertCount());
158 //TODO(mattm): add more tests of without a persistent store?
159 TEST(DefaultServerBoundCertStoreTest, TestSettingAndGetting) {
160 // No persistent store, all calls will be synchronous.
161 DefaultServerBoundCertStore store(NULL);
162 base::Time expiration_time;
163 std::string private_key, cert;
164 EXPECT_EQ(0, store.GetCertCount());
165 EXPECT_EQ(ERR_FILE_NOT_FOUND,
166 store.GetServerBoundCert("verisign.com",
167 &expiration_time,
168 &private_key,
169 &cert,
170 base::Bind(&GetCertCallbackNotCalled)));
171 EXPECT_TRUE(private_key.empty());
172 EXPECT_TRUE(cert.empty());
173 store.SetServerBoundCert(
174 "verisign.com",
175 base::Time::FromInternalValue(123),
176 base::Time::FromInternalValue(456),
177 "i", "j");
178 EXPECT_EQ(OK,
179 store.GetServerBoundCert("verisign.com",
180 &expiration_time,
181 &private_key,
182 &cert,
183 base::Bind(&GetCertCallbackNotCalled)));
184 EXPECT_EQ(456, expiration_time.ToInternalValue());
185 EXPECT_EQ("i", private_key);
186 EXPECT_EQ("j", cert);
189 TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) {
190 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
191 DefaultServerBoundCertStore store(persistent_store.get());
193 base::Time expiration_time;
194 std::string private_key, cert;
195 EXPECT_EQ(0, store.GetCertCount());
196 store.SetServerBoundCert(
197 "verisign.com",
198 base::Time::FromInternalValue(123),
199 base::Time::FromInternalValue(1234),
200 "a", "b");
201 store.SetServerBoundCert(
202 "verisign.com",
203 base::Time::FromInternalValue(456),
204 base::Time::FromInternalValue(4567),
205 "c", "d");
207 // Wait for load & queued set tasks.
208 base::MessageLoop::current()->RunUntilIdle();
209 EXPECT_EQ(1, store.GetCertCount());
210 EXPECT_EQ(OK,
211 store.GetServerBoundCert("verisign.com",
212 &expiration_time,
213 &private_key,
214 &cert,
215 base::Bind(&GetCertCallbackNotCalled)));
216 EXPECT_EQ(4567, expiration_time.ToInternalValue());
217 EXPECT_EQ("c", private_key);
218 EXPECT_EQ("d", cert);
221 TEST(DefaultServerBoundCertStoreTest, TestAsyncGet) {
222 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
223 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
224 "verisign.com",
225 base::Time::FromInternalValue(123),
226 base::Time::FromInternalValue(1234),
227 "a", "b"));
229 DefaultServerBoundCertStore store(persistent_store.get());
230 AsyncGetCertHelper helper;
231 base::Time expiration_time;
232 std::string private_key;
233 std::string cert = "not set";
234 EXPECT_EQ(0, store.GetCertCount());
235 EXPECT_EQ(ERR_IO_PENDING,
236 store.GetServerBoundCert("verisign.com",
237 &expiration_time,
238 &private_key,
239 &cert,
240 base::Bind(&AsyncGetCertHelper::Callback,
241 base::Unretained(&helper))));
243 // Wait for load & queued get tasks.
244 base::MessageLoop::current()->RunUntilIdle();
245 EXPECT_EQ(1, store.GetCertCount());
246 EXPECT_EQ("not set", cert);
247 EXPECT_TRUE(helper.called_);
248 EXPECT_EQ(OK, helper.err_);
249 EXPECT_EQ("verisign.com", helper.server_identifier_);
250 EXPECT_EQ(1234, helper.expiration_time_.ToInternalValue());
251 EXPECT_EQ("a", helper.private_key_);
252 EXPECT_EQ("b", helper.cert_);
255 TEST(DefaultServerBoundCertStoreTest, TestDeleteAll) {
256 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
257 DefaultServerBoundCertStore store(persistent_store.get());
259 store.SetServerBoundCert(
260 "verisign.com",
261 base::Time(),
262 base::Time(),
263 "a", "b");
264 store.SetServerBoundCert(
265 "google.com",
266 base::Time(),
267 base::Time(),
268 "c", "d");
269 store.SetServerBoundCert(
270 "harvard.com",
271 base::Time(),
272 base::Time(),
273 "e", "f");
274 // Wait for load & queued set tasks.
275 base::MessageLoop::current()->RunUntilIdle();
277 EXPECT_EQ(3, store.GetCertCount());
278 int delete_finished = 0;
279 store.DeleteAll(base::Bind(&CallCounter, &delete_finished));
280 ASSERT_EQ(1, delete_finished);
281 EXPECT_EQ(0, store.GetCertCount());
284 TEST(DefaultServerBoundCertStoreTest, TestAsyncGetAndDeleteAll) {
285 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
286 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
287 "verisign.com",
288 base::Time(),
289 base::Time(),
290 "a", "b"));
291 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
292 "google.com",
293 base::Time(),
294 base::Time(),
295 "c", "d"));
297 ServerBoundCertStore::ServerBoundCertList pre_certs;
298 ServerBoundCertStore::ServerBoundCertList post_certs;
299 int delete_finished = 0;
300 DefaultServerBoundCertStore store(persistent_store.get());
302 store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &pre_certs));
303 store.DeleteAll(base::Bind(&CallCounter, &delete_finished));
304 store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &post_certs));
305 // Tasks have not run yet.
306 EXPECT_EQ(0u, pre_certs.size());
307 // Wait for load & queued tasks.
308 base::MessageLoop::current()->RunUntilIdle();
309 EXPECT_EQ(0, store.GetCertCount());
310 EXPECT_EQ(2u, pre_certs.size());
311 EXPECT_EQ(0u, post_certs.size());
314 TEST(DefaultServerBoundCertStoreTest, TestDelete) {
315 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
316 DefaultServerBoundCertStore store(persistent_store.get());
318 base::Time expiration_time;
319 std::string private_key, cert;
320 EXPECT_EQ(0, store.GetCertCount());
321 store.SetServerBoundCert(
322 "verisign.com",
323 base::Time(),
324 base::Time(),
325 "a", "b");
326 // Wait for load & queued set task.
327 base::MessageLoop::current()->RunUntilIdle();
329 store.SetServerBoundCert(
330 "google.com",
331 base::Time(),
332 base::Time(),
333 "c", "d");
335 EXPECT_EQ(2, store.GetCertCount());
336 int delete_finished = 0;
337 store.DeleteServerBoundCert("verisign.com",
338 base::Bind(&CallCounter, &delete_finished));
339 ASSERT_EQ(1, delete_finished);
340 EXPECT_EQ(1, store.GetCertCount());
341 EXPECT_EQ(ERR_FILE_NOT_FOUND,
342 store.GetServerBoundCert("verisign.com",
343 &expiration_time,
344 &private_key,
345 &cert,
346 base::Bind(&GetCertCallbackNotCalled)));
347 EXPECT_EQ(OK,
348 store.GetServerBoundCert("google.com",
349 &expiration_time,
350 &private_key,
351 &cert,
352 base::Bind(&GetCertCallbackNotCalled)));
353 int delete2_finished = 0;
354 store.DeleteServerBoundCert("google.com",
355 base::Bind(&CallCounter, &delete2_finished));
356 ASSERT_EQ(1, delete2_finished);
357 EXPECT_EQ(0, store.GetCertCount());
358 EXPECT_EQ(ERR_FILE_NOT_FOUND,
359 store.GetServerBoundCert("google.com",
360 &expiration_time,
361 &private_key,
362 &cert,
363 base::Bind(&GetCertCallbackNotCalled)));
366 TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) {
367 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
368 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
369 "a.com",
370 base::Time::FromInternalValue(1),
371 base::Time::FromInternalValue(2),
372 "a", "b"));
373 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
374 "b.com",
375 base::Time::FromInternalValue(3),
376 base::Time::FromInternalValue(4),
377 "c", "d"));
378 DefaultServerBoundCertStore store(persistent_store.get());
379 int delete_finished = 0;
380 store.DeleteServerBoundCert("a.com",
381 base::Bind(&CallCounter, &delete_finished));
383 AsyncGetCertHelper a_helper;
384 AsyncGetCertHelper b_helper;
385 base::Time expiration_time;
386 std::string private_key;
387 std::string cert = "not set";
388 EXPECT_EQ(0, store.GetCertCount());
389 EXPECT_EQ(ERR_IO_PENDING,
390 store.GetServerBoundCert(
391 "a.com", &expiration_time, &private_key, &cert,
392 base::Bind(&AsyncGetCertHelper::Callback,
393 base::Unretained(&a_helper))));
394 EXPECT_EQ(ERR_IO_PENDING,
395 store.GetServerBoundCert(
396 "b.com", &expiration_time, &private_key, &cert,
397 base::Bind(&AsyncGetCertHelper::Callback,
398 base::Unretained(&b_helper))));
400 EXPECT_EQ(0, delete_finished);
401 EXPECT_FALSE(a_helper.called_);
402 EXPECT_FALSE(b_helper.called_);
403 // Wait for load & queued tasks.
404 base::MessageLoop::current()->RunUntilIdle();
405 EXPECT_EQ(1, delete_finished);
406 EXPECT_EQ(1, store.GetCertCount());
407 EXPECT_EQ("not set", cert);
408 EXPECT_TRUE(a_helper.called_);
409 EXPECT_EQ(ERR_FILE_NOT_FOUND, a_helper.err_);
410 EXPECT_EQ("a.com", a_helper.server_identifier_);
411 EXPECT_EQ(0, a_helper.expiration_time_.ToInternalValue());
412 EXPECT_EQ("", a_helper.private_key_);
413 EXPECT_EQ("", a_helper.cert_);
414 EXPECT_TRUE(b_helper.called_);
415 EXPECT_EQ(OK, b_helper.err_);
416 EXPECT_EQ("b.com", b_helper.server_identifier_);
417 EXPECT_EQ(4, b_helper.expiration_time_.ToInternalValue());
418 EXPECT_EQ("c", b_helper.private_key_);
419 EXPECT_EQ("d", b_helper.cert_);
422 TEST(DefaultServerBoundCertStoreTest, TestGetAll) {
423 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
424 DefaultServerBoundCertStore store(persistent_store.get());
426 EXPECT_EQ(0, store.GetCertCount());
427 store.SetServerBoundCert(
428 "verisign.com",
429 base::Time(),
430 base::Time(),
431 "a", "b");
432 store.SetServerBoundCert(
433 "google.com",
434 base::Time(),
435 base::Time(),
436 "c", "d");
437 store.SetServerBoundCert(
438 "harvard.com",
439 base::Time(),
440 base::Time(),
441 "e", "f");
442 store.SetServerBoundCert(
443 "mit.com",
444 base::Time(),
445 base::Time(),
446 "g", "h");
447 // Wait for load & queued set tasks.
448 base::MessageLoop::current()->RunUntilIdle();
450 EXPECT_EQ(4, store.GetCertCount());
451 ServerBoundCertStore::ServerBoundCertList certs;
452 store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &certs));
453 EXPECT_EQ(4u, certs.size());
456 TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) {
457 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
458 DefaultServerBoundCertStore store(persistent_store.get());
460 store.SetServerBoundCert(
461 "preexisting.com",
462 base::Time(),
463 base::Time(),
464 "a", "b");
465 store.SetServerBoundCert(
466 "both.com",
467 base::Time(),
468 base::Time(),
469 "c", "d");
470 // Wait for load & queued set tasks.
471 base::MessageLoop::current()->RunUntilIdle();
472 EXPECT_EQ(2, store.GetCertCount());
474 ServerBoundCertStore::ServerBoundCertList source_certs;
475 source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
476 "both.com",
477 base::Time(),
478 base::Time(),
479 // Key differs from above to test that existing entries are overwritten.
480 "e", "f"));
481 source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
482 "copied.com",
483 base::Time(),
484 base::Time(),
485 "g", "h"));
486 store.InitializeFrom(source_certs);
487 EXPECT_EQ(3, store.GetCertCount());
489 ServerBoundCertStore::ServerBoundCertList certs;
490 store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &certs));
491 ASSERT_EQ(3u, certs.size());
493 ServerBoundCertStore::ServerBoundCertList::iterator cert = certs.begin();
494 EXPECT_EQ("both.com", cert->server_identifier());
495 EXPECT_EQ("e", cert->private_key());
497 ++cert;
498 EXPECT_EQ("copied.com", cert->server_identifier());
499 EXPECT_EQ("g", cert->private_key());
501 ++cert;
502 EXPECT_EQ("preexisting.com", cert->server_identifier());
503 EXPECT_EQ("a", cert->private_key());
506 TEST(DefaultServerBoundCertStoreTest, TestAsyncInitializeFrom) {
507 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
508 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
509 "preexisting.com",
510 base::Time(),
511 base::Time(),
512 "a", "b"));
513 persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
514 "both.com",
515 base::Time(),
516 base::Time(),
517 "c", "d"));
519 DefaultServerBoundCertStore store(persistent_store.get());
520 ServerBoundCertStore::ServerBoundCertList source_certs;
521 source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
522 "both.com",
523 base::Time(),
524 base::Time(),
525 // Key differs from above to test that existing entries are overwritten.
526 "e", "f"));
527 source_certs.push_back(ServerBoundCertStore::ServerBoundCert(
528 "copied.com",
529 base::Time(),
530 base::Time(),
531 "g", "h"));
532 store.InitializeFrom(source_certs);
533 EXPECT_EQ(0, store.GetCertCount());
534 // Wait for load & queued tasks.
535 base::MessageLoop::current()->RunUntilIdle();
536 EXPECT_EQ(3, store.GetCertCount());
538 ServerBoundCertStore::ServerBoundCertList certs;
539 store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &certs));
540 ASSERT_EQ(3u, certs.size());
542 ServerBoundCertStore::ServerBoundCertList::iterator cert = certs.begin();
543 EXPECT_EQ("both.com", cert->server_identifier());
544 EXPECT_EQ("e", cert->private_key());
546 ++cert;
547 EXPECT_EQ("copied.com", cert->server_identifier());
548 EXPECT_EQ("g", cert->private_key());
550 ++cert;
551 EXPECT_EQ("preexisting.com", cert->server_identifier());
552 EXPECT_EQ("a", cert->private_key());
555 } // namespace net