1 // Copyright 2014 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_channel_id_store.h"
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"
23 void CallCounter(int* counter
) {
27 void GetChannelIDCallbackNotCalled(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 AsyncGetChannelIDHelper
{
37 AsyncGetChannelIDHelper() : 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
) {
45 server_identifier_
= server_identifier
;
46 expiration_time_
= expiration_time
;
47 private_key_
= private_key_result
;
53 std::string server_identifier_
;
54 base::Time expiration_time_
;
55 std::string private_key_
;
61 ChannelIDStore::ChannelIDList
* dest
,
62 const ChannelIDStore::ChannelIDList
& result
) {
66 class MockPersistentStore
67 : public DefaultChannelIDStore::PersistentStore
{
69 MockPersistentStore();
71 // DefaultChannelIDStore::PersistentStore implementation.
72 void Load(const LoadedCallback
& loaded_callback
) override
;
74 const DefaultChannelIDStore::ChannelID
& channel_id
) override
;
76 const DefaultChannelIDStore::ChannelID
& channel_id
) override
;
77 void SetForceKeepSessionState() override
;
80 ~MockPersistentStore() override
;
83 typedef std::map
<std::string
, DefaultChannelIDStore::ChannelID
>
86 ChannelIDMap channel_ids_
;
89 MockPersistentStore::MockPersistentStore() {}
91 void MockPersistentStore::Load(const LoadedCallback
& loaded_callback
) {
92 scoped_ptr
<ScopedVector
<DefaultChannelIDStore::ChannelID
> >
93 channel_ids(new ScopedVector
<DefaultChannelIDStore::ChannelID
>());
94 ChannelIDMap::iterator it
;
96 for (it
= channel_ids_
.begin(); it
!= channel_ids_
.end(); ++it
) {
97 channel_ids
->push_back(
98 new DefaultChannelIDStore::ChannelID(it
->second
));
101 base::MessageLoop::current()->PostTask(
102 FROM_HERE
, base::Bind(loaded_callback
, base::Passed(&channel_ids
)));
105 void MockPersistentStore::AddChannelID(
106 const DefaultChannelIDStore::ChannelID
& channel_id
) {
107 channel_ids_
[channel_id
.server_identifier()] = channel_id
;
110 void MockPersistentStore::DeleteChannelID(
111 const DefaultChannelIDStore::ChannelID
& channel_id
) {
112 channel_ids_
.erase(channel_id
.server_identifier());
115 void MockPersistentStore::SetForceKeepSessionState() {}
117 MockPersistentStore::~MockPersistentStore() {}
121 TEST(DefaultChannelIDStoreTest
, TestLoading
) {
122 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
124 persistent_store
->AddChannelID(
125 DefaultChannelIDStore::ChannelID(
130 persistent_store
->AddChannelID(
131 DefaultChannelIDStore::ChannelID(
137 // Make sure channel_ids load properly.
138 DefaultChannelIDStore
store(persistent_store
.get());
139 // Load has not occurred yet.
140 EXPECT_EQ(0, store
.GetChannelIDCount());
146 // Wait for load & queued set task.
147 base::MessageLoop::current()->RunUntilIdle();
148 EXPECT_EQ(2, store
.GetChannelIDCount());
154 // Set should be synchronous now that load is done.
155 EXPECT_EQ(3, store
.GetChannelIDCount());
158 //TODO(mattm): add more tests of without a persistent store?
159 TEST(DefaultChannelIDStoreTest
, TestSettingAndGetting
) {
160 // No persistent store, all calls will be synchronous.
161 DefaultChannelIDStore
store(NULL
);
162 base::Time expiration_time
;
163 std::string private_key
, cert
;
164 EXPECT_EQ(0, store
.GetChannelIDCount());
165 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
166 store
.GetChannelID("verisign.com",
170 base::Bind(&GetChannelIDCallbackNotCalled
)));
171 EXPECT_TRUE(private_key
.empty());
172 EXPECT_TRUE(cert
.empty());
175 base::Time::FromInternalValue(123),
176 base::Time::FromInternalValue(456),
179 store
.GetChannelID("verisign.com",
183 base::Bind(&GetChannelIDCallbackNotCalled
)));
184 EXPECT_EQ(456, expiration_time
.ToInternalValue());
185 EXPECT_EQ("i", private_key
);
186 EXPECT_EQ("j", cert
);
189 TEST(DefaultChannelIDStoreTest
, TestDuplicateChannelIds
) {
190 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
191 DefaultChannelIDStore
store(persistent_store
.get());
193 base::Time expiration_time
;
194 std::string private_key
, cert
;
195 EXPECT_EQ(0, store
.GetChannelIDCount());
198 base::Time::FromInternalValue(123),
199 base::Time::FromInternalValue(1234),
203 base::Time::FromInternalValue(456),
204 base::Time::FromInternalValue(4567),
207 // Wait for load & queued set tasks.
208 base::MessageLoop::current()->RunUntilIdle();
209 EXPECT_EQ(1, store
.GetChannelIDCount());
211 store
.GetChannelID("verisign.com",
215 base::Bind(&GetChannelIDCallbackNotCalled
)));
216 EXPECT_EQ(4567, expiration_time
.ToInternalValue());
217 EXPECT_EQ("c", private_key
);
218 EXPECT_EQ("d", cert
);
221 TEST(DefaultChannelIDStoreTest
, TestAsyncGet
) {
222 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
223 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
225 base::Time::FromInternalValue(123),
226 base::Time::FromInternalValue(1234),
229 DefaultChannelIDStore
store(persistent_store
.get());
230 AsyncGetChannelIDHelper helper
;
231 base::Time expiration_time
;
232 std::string private_key
;
233 std::string cert
= "not set";
234 EXPECT_EQ(0, store
.GetChannelIDCount());
235 EXPECT_EQ(ERR_IO_PENDING
,
236 store
.GetChannelID("verisign.com",
240 base::Bind(&AsyncGetChannelIDHelper::Callback
,
241 base::Unretained(&helper
))));
243 // Wait for load & queued get tasks.
244 base::MessageLoop::current()->RunUntilIdle();
245 EXPECT_EQ(1, store
.GetChannelIDCount());
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(DefaultChannelIDStoreTest
, TestDeleteAll
) {
256 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
257 DefaultChannelIDStore
store(persistent_store
.get());
274 // Wait for load & queued set tasks.
275 base::MessageLoop::current()->RunUntilIdle();
277 EXPECT_EQ(3, store
.GetChannelIDCount());
278 int delete_finished
= 0;
279 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
280 ASSERT_EQ(1, delete_finished
);
281 EXPECT_EQ(0, store
.GetChannelIDCount());
284 TEST(DefaultChannelIDStoreTest
, TestAsyncGetAndDeleteAll
) {
285 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
286 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
291 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
297 ChannelIDStore::ChannelIDList pre_channel_ids
;
298 ChannelIDStore::ChannelIDList post_channel_ids
;
299 int delete_finished
= 0;
300 DefaultChannelIDStore
store(persistent_store
.get());
302 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &pre_channel_ids
));
303 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
304 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &post_channel_ids
));
305 // Tasks have not run yet.
306 EXPECT_EQ(0u, pre_channel_ids
.size());
307 // Wait for load & queued tasks.
308 base::MessageLoop::current()->RunUntilIdle();
309 EXPECT_EQ(0, store
.GetChannelIDCount());
310 EXPECT_EQ(2u, pre_channel_ids
.size());
311 EXPECT_EQ(0u, post_channel_ids
.size());
314 TEST(DefaultChannelIDStoreTest
, TestDelete
) {
315 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
316 DefaultChannelIDStore
store(persistent_store
.get());
318 base::Time expiration_time
;
319 std::string private_key
, cert
;
320 EXPECT_EQ(0, store
.GetChannelIDCount());
326 // Wait for load & queued set task.
327 base::MessageLoop::current()->RunUntilIdle();
335 EXPECT_EQ(2, store
.GetChannelIDCount());
336 int delete_finished
= 0;
337 store
.DeleteChannelID("verisign.com",
338 base::Bind(&CallCounter
, &delete_finished
));
339 ASSERT_EQ(1, delete_finished
);
340 EXPECT_EQ(1, store
.GetChannelIDCount());
341 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
342 store
.GetChannelID("verisign.com",
346 base::Bind(&GetChannelIDCallbackNotCalled
)));
348 store
.GetChannelID("google.com",
352 base::Bind(&GetChannelIDCallbackNotCalled
)));
353 int delete2_finished
= 0;
354 store
.DeleteChannelID("google.com",
355 base::Bind(&CallCounter
, &delete2_finished
));
356 ASSERT_EQ(1, delete2_finished
);
357 EXPECT_EQ(0, store
.GetChannelIDCount());
358 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
359 store
.GetChannelID("google.com",
363 base::Bind(&GetChannelIDCallbackNotCalled
)));
366 TEST(DefaultChannelIDStoreTest
, TestAsyncDelete
) {
367 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
368 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
370 base::Time::FromInternalValue(1),
371 base::Time::FromInternalValue(2),
373 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
375 base::Time::FromInternalValue(3),
376 base::Time::FromInternalValue(4),
378 DefaultChannelIDStore
store(persistent_store
.get());
379 int delete_finished
= 0;
380 store
.DeleteChannelID("a.com",
381 base::Bind(&CallCounter
, &delete_finished
));
383 AsyncGetChannelIDHelper a_helper
;
384 AsyncGetChannelIDHelper b_helper
;
385 base::Time expiration_time
;
386 std::string private_key
;
387 std::string cert
= "not set";
388 EXPECT_EQ(0, store
.GetChannelIDCount());
389 EXPECT_EQ(ERR_IO_PENDING
,
391 "a.com", &expiration_time
, &private_key
, &cert
,
392 base::Bind(&AsyncGetChannelIDHelper::Callback
,
393 base::Unretained(&a_helper
))));
394 EXPECT_EQ(ERR_IO_PENDING
,
396 "b.com", &expiration_time
, &private_key
, &cert
,
397 base::Bind(&AsyncGetChannelIDHelper::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
.GetChannelIDCount());
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(DefaultChannelIDStoreTest
, TestGetAll
) {
423 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
424 DefaultChannelIDStore
store(persistent_store
.get());
426 EXPECT_EQ(0, store
.GetChannelIDCount());
447 // Wait for load & queued set tasks.
448 base::MessageLoop::current()->RunUntilIdle();
450 EXPECT_EQ(4, store
.GetChannelIDCount());
451 ChannelIDStore::ChannelIDList channel_ids
;
452 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &channel_ids
));
453 EXPECT_EQ(4u, channel_ids
.size());
456 TEST(DefaultChannelIDStoreTest
, TestInitializeFrom
) {
457 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
458 DefaultChannelIDStore
store(persistent_store
.get());
470 // Wait for load & queued set tasks.
471 base::MessageLoop::current()->RunUntilIdle();
472 EXPECT_EQ(2, store
.GetChannelIDCount());
474 ChannelIDStore::ChannelIDList source_channel_ids
;
475 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
479 // Key differs from above to test that existing entries are overwritten.
481 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
486 store
.InitializeFrom(source_channel_ids
);
487 EXPECT_EQ(3, store
.GetChannelIDCount());
489 ChannelIDStore::ChannelIDList channel_ids
;
490 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &channel_ids
));
491 ASSERT_EQ(3u, channel_ids
.size());
493 ChannelIDStore::ChannelIDList::iterator channel_id
= channel_ids
.begin();
494 EXPECT_EQ("both.com", channel_id
->server_identifier());
495 EXPECT_EQ("e", channel_id
->private_key());
498 EXPECT_EQ("copied.com", channel_id
->server_identifier());
499 EXPECT_EQ("g", channel_id
->private_key());
502 EXPECT_EQ("preexisting.com", channel_id
->server_identifier());
503 EXPECT_EQ("a", channel_id
->private_key());
506 TEST(DefaultChannelIDStoreTest
, TestAsyncInitializeFrom
) {
507 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
508 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
513 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
519 DefaultChannelIDStore
store(persistent_store
.get());
520 ChannelIDStore::ChannelIDList source_channel_ids
;
521 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
525 // Key differs from above to test that existing entries are overwritten.
527 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
532 store
.InitializeFrom(source_channel_ids
);
533 EXPECT_EQ(0, store
.GetChannelIDCount());
534 // Wait for load & queued tasks.
535 base::MessageLoop::current()->RunUntilIdle();
536 EXPECT_EQ(3, store
.GetChannelIDCount());
538 ChannelIDStore::ChannelIDList channel_ids
;
539 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &channel_ids
));
540 ASSERT_EQ(3u, channel_ids
.size());
542 ChannelIDStore::ChannelIDList::iterator channel_id
= channel_ids
.begin();
543 EXPECT_EQ("both.com", channel_id
->server_identifier());
544 EXPECT_EQ("e", channel_id
->private_key());
547 EXPECT_EQ("copied.com", channel_id
->server_identifier());
548 EXPECT_EQ("g", channel_id
->private_key());
551 EXPECT_EQ("preexisting.com", channel_id
->server_identifier());
552 EXPECT_EQ("a", channel_id
->private_key());