Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / ssl / default_channel_id_store_unittest.cc
blobfce807f0f6c3c5c9a673641c9e25f792ceb9cabc
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"
7 #include <map>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "crypto/ec_private_key.h"
20 #include "net/base/net_errors.h"
21 #include "net/test/channel_id_test_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 namespace net {
26 namespace {
28 void CallCounter(int* counter) {
29 (*counter)++;
32 void GetChannelIDCallbackNotCalled(
33 int err,
34 const std::string& server_identifier,
35 scoped_ptr<crypto::ECPrivateKey> key_result) {
36 ADD_FAILURE() << "Unexpected callback execution.";
39 class AsyncGetChannelIDHelper {
40 public:
41 AsyncGetChannelIDHelper() : called_(false) {}
43 void Callback(int err,
44 const std::string& server_identifier,
45 scoped_ptr<crypto::ECPrivateKey> key_result) {
46 err_ = err;
47 server_identifier_ = server_identifier;
48 key_ = key_result.Pass();
49 called_ = true;
52 int err_;
53 std::string server_identifier_;
54 scoped_ptr<crypto::ECPrivateKey> key_;
55 bool called_;
58 void GetAllCallback(
59 ChannelIDStore::ChannelIDList* dest,
60 const ChannelIDStore::ChannelIDList& result) {
61 *dest = result;
64 class MockPersistentStore
65 : public DefaultChannelIDStore::PersistentStore {
66 public:
67 MockPersistentStore();
69 // DefaultChannelIDStore::PersistentStore implementation.
70 void Load(const LoadedCallback& loaded_callback) override;
71 void AddChannelID(
72 const DefaultChannelIDStore::ChannelID& channel_id) override;
73 void DeleteChannelID(
74 const DefaultChannelIDStore::ChannelID& channel_id) override;
75 void SetForceKeepSessionState() override;
77 protected:
78 ~MockPersistentStore() override;
80 private:
81 typedef std::map<std::string, DefaultChannelIDStore::ChannelID>
82 ChannelIDMap;
84 ChannelIDMap channel_ids_;
87 MockPersistentStore::MockPersistentStore() {}
89 void MockPersistentStore::Load(const LoadedCallback& loaded_callback) {
90 scoped_ptr<ScopedVector<DefaultChannelIDStore::ChannelID> >
91 channel_ids(new ScopedVector<DefaultChannelIDStore::ChannelID>());
92 ChannelIDMap::iterator it;
94 for (it = channel_ids_.begin(); it != channel_ids_.end(); ++it) {
95 channel_ids->push_back(
96 new DefaultChannelIDStore::ChannelID(it->second));
99 base::ThreadTaskRunnerHandle::Get()->PostTask(
100 FROM_HERE, base::Bind(loaded_callback, base::Passed(&channel_ids)));
103 void MockPersistentStore::AddChannelID(
104 const DefaultChannelIDStore::ChannelID& channel_id) {
105 channel_ids_[channel_id.server_identifier()] = channel_id;
108 void MockPersistentStore::DeleteChannelID(
109 const DefaultChannelIDStore::ChannelID& channel_id) {
110 channel_ids_.erase(channel_id.server_identifier());
113 void MockPersistentStore::SetForceKeepSessionState() {}
115 MockPersistentStore::~MockPersistentStore() {}
117 } // namespace
119 TEST(DefaultChannelIDStoreTest, TestLoading) {
120 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
122 persistent_store->AddChannelID(DefaultChannelIDStore::ChannelID(
123 "google.com", base::Time(),
124 make_scoped_ptr(crypto::ECPrivateKey::Create())));
125 persistent_store->AddChannelID(DefaultChannelIDStore::ChannelID(
126 "verisign.com", base::Time(),
127 make_scoped_ptr(crypto::ECPrivateKey::Create())));
129 // Make sure channel_ids load properly.
130 DefaultChannelIDStore store(persistent_store.get());
131 // Load has not occurred yet.
132 EXPECT_EQ(0, store.GetChannelIDCount());
133 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
134 "verisign.com", base::Time(),
135 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
136 // Wait for load & queued set task.
137 base::MessageLoop::current()->RunUntilIdle();
138 EXPECT_EQ(2, store.GetChannelIDCount());
139 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
140 "twitter.com", base::Time(),
141 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
142 // Set should be synchronous now that load is done.
143 EXPECT_EQ(3, store.GetChannelIDCount());
146 //TODO(mattm): add more tests of without a persistent store?
147 TEST(DefaultChannelIDStoreTest, TestSettingAndGetting) {
148 // No persistent store, all calls will be synchronous.
149 DefaultChannelIDStore store(NULL);
150 scoped_ptr<crypto::ECPrivateKey> expected_key(crypto::ECPrivateKey::Create());
152 scoped_ptr<crypto::ECPrivateKey> key;
153 EXPECT_EQ(0, store.GetChannelIDCount());
154 EXPECT_EQ(ERR_FILE_NOT_FOUND,
155 store.GetChannelID("verisign.com", &key,
156 base::Bind(&GetChannelIDCallbackNotCalled)));
157 EXPECT_FALSE(key);
158 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
159 "verisign.com", base::Time::FromInternalValue(123),
160 make_scoped_ptr(expected_key->Copy()))));
161 EXPECT_EQ(OK, store.GetChannelID("verisign.com", &key,
162 base::Bind(&GetChannelIDCallbackNotCalled)));
163 EXPECT_TRUE(KeysEqual(expected_key.get(), key.get()));
166 TEST(DefaultChannelIDStoreTest, TestDuplicateChannelIds) {
167 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
168 DefaultChannelIDStore store(persistent_store.get());
169 scoped_ptr<crypto::ECPrivateKey> expected_key(crypto::ECPrivateKey::Create());
171 scoped_ptr<crypto::ECPrivateKey> key;
172 EXPECT_EQ(0, store.GetChannelIDCount());
173 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
174 "verisign.com", base::Time::FromInternalValue(123),
175 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
176 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
177 "verisign.com", base::Time::FromInternalValue(456),
178 make_scoped_ptr(expected_key->Copy()))));
180 // Wait for load & queued set tasks.
181 base::MessageLoop::current()->RunUntilIdle();
182 EXPECT_EQ(1, store.GetChannelIDCount());
183 EXPECT_EQ(OK, store.GetChannelID("verisign.com", &key,
184 base::Bind(&GetChannelIDCallbackNotCalled)));
185 EXPECT_TRUE(KeysEqual(expected_key.get(), key.get()));
188 TEST(DefaultChannelIDStoreTest, TestAsyncGet) {
189 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
190 scoped_ptr<crypto::ECPrivateKey> expected_key(crypto::ECPrivateKey::Create());
191 persistent_store->AddChannelID(ChannelIDStore::ChannelID(
192 "verisign.com", base::Time::FromInternalValue(123),
193 make_scoped_ptr(expected_key->Copy())));
195 DefaultChannelIDStore store(persistent_store.get());
196 AsyncGetChannelIDHelper helper;
197 scoped_ptr<crypto::ECPrivateKey> key;
198 EXPECT_EQ(0, store.GetChannelIDCount());
199 EXPECT_EQ(ERR_IO_PENDING,
200 store.GetChannelID("verisign.com", &key,
201 base::Bind(&AsyncGetChannelIDHelper::Callback,
202 base::Unretained(&helper))));
204 // Wait for load & queued get tasks.
205 base::MessageLoop::current()->RunUntilIdle();
206 EXPECT_EQ(1, store.GetChannelIDCount());
207 EXPECT_FALSE(key);
208 EXPECT_TRUE(helper.called_);
209 EXPECT_EQ(OK, helper.err_);
210 EXPECT_EQ("verisign.com", helper.server_identifier_);
211 EXPECT_TRUE(KeysEqual(expected_key.get(), helper.key_.get()));
214 TEST(DefaultChannelIDStoreTest, TestDeleteAll) {
215 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
216 DefaultChannelIDStore store(persistent_store.get());
218 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
219 "verisign.com", base::Time(),
220 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
221 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
222 "google.com", base::Time(),
223 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
224 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
225 "harvard.com", base::Time(),
226 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
227 // Wait for load & queued set tasks.
228 base::MessageLoop::current()->RunUntilIdle();
230 EXPECT_EQ(3, store.GetChannelIDCount());
231 int delete_finished = 0;
232 store.DeleteAll(base::Bind(&CallCounter, &delete_finished));
233 ASSERT_EQ(1, delete_finished);
234 EXPECT_EQ(0, store.GetChannelIDCount());
237 TEST(DefaultChannelIDStoreTest, TestAsyncGetAndDeleteAll) {
238 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
239 persistent_store->AddChannelID(ChannelIDStore::ChannelID(
240 "verisign.com", base::Time(),
241 make_scoped_ptr(crypto::ECPrivateKey::Create())));
242 persistent_store->AddChannelID(ChannelIDStore::ChannelID(
243 "google.com", base::Time(),
244 make_scoped_ptr(crypto::ECPrivateKey::Create())));
246 ChannelIDStore::ChannelIDList pre_channel_ids;
247 ChannelIDStore::ChannelIDList post_channel_ids;
248 int delete_finished = 0;
249 DefaultChannelIDStore store(persistent_store.get());
251 store.GetAllChannelIDs(base::Bind(GetAllCallback, &pre_channel_ids));
252 store.DeleteAll(base::Bind(&CallCounter, &delete_finished));
253 store.GetAllChannelIDs(base::Bind(GetAllCallback, &post_channel_ids));
254 // Tasks have not run yet.
255 EXPECT_EQ(0u, pre_channel_ids.size());
256 // Wait for load & queued tasks.
257 base::MessageLoop::current()->RunUntilIdle();
258 EXPECT_EQ(0, store.GetChannelIDCount());
259 EXPECT_EQ(2u, pre_channel_ids.size());
260 EXPECT_EQ(0u, post_channel_ids.size());
263 TEST(DefaultChannelIDStoreTest, TestDelete) {
264 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
265 DefaultChannelIDStore store(persistent_store.get());
267 scoped_ptr<crypto::ECPrivateKey> key;
268 EXPECT_EQ(0, store.GetChannelIDCount());
269 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
270 "verisign.com", base::Time(),
271 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
272 // Wait for load & queued set task.
273 base::MessageLoop::current()->RunUntilIdle();
275 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
276 "google.com", base::Time(),
277 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
279 EXPECT_EQ(2, store.GetChannelIDCount());
280 int delete_finished = 0;
281 store.DeleteChannelID("verisign.com",
282 base::Bind(&CallCounter, &delete_finished));
283 ASSERT_EQ(1, delete_finished);
284 EXPECT_EQ(1, store.GetChannelIDCount());
285 EXPECT_EQ(ERR_FILE_NOT_FOUND,
286 store.GetChannelID("verisign.com", &key,
287 base::Bind(&GetChannelIDCallbackNotCalled)));
288 EXPECT_EQ(OK, store.GetChannelID("google.com", &key,
289 base::Bind(&GetChannelIDCallbackNotCalled)));
290 int delete2_finished = 0;
291 store.DeleteChannelID("google.com",
292 base::Bind(&CallCounter, &delete2_finished));
293 ASSERT_EQ(1, delete2_finished);
294 EXPECT_EQ(0, store.GetChannelIDCount());
295 EXPECT_EQ(ERR_FILE_NOT_FOUND,
296 store.GetChannelID("google.com", &key,
297 base::Bind(&GetChannelIDCallbackNotCalled)));
300 TEST(DefaultChannelIDStoreTest, TestAsyncDelete) {
301 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
302 scoped_ptr<crypto::ECPrivateKey> expected_key(crypto::ECPrivateKey::Create());
303 persistent_store->AddChannelID(ChannelIDStore::ChannelID(
304 "a.com", base::Time::FromInternalValue(1),
305 make_scoped_ptr(crypto::ECPrivateKey::Create())));
306 persistent_store->AddChannelID(
307 ChannelIDStore::ChannelID("b.com", base::Time::FromInternalValue(3),
308 make_scoped_ptr(expected_key->Copy())));
309 DefaultChannelIDStore store(persistent_store.get());
310 int delete_finished = 0;
311 store.DeleteChannelID("a.com",
312 base::Bind(&CallCounter, &delete_finished));
314 AsyncGetChannelIDHelper a_helper;
315 AsyncGetChannelIDHelper b_helper;
316 scoped_ptr<crypto::ECPrivateKey> key;
317 EXPECT_EQ(0, store.GetChannelIDCount());
318 EXPECT_EQ(ERR_IO_PENDING,
319 store.GetChannelID("a.com", &key,
320 base::Bind(&AsyncGetChannelIDHelper::Callback,
321 base::Unretained(&a_helper))));
322 EXPECT_EQ(ERR_IO_PENDING,
323 store.GetChannelID("b.com", &key,
324 base::Bind(&AsyncGetChannelIDHelper::Callback,
325 base::Unretained(&b_helper))));
327 EXPECT_EQ(0, delete_finished);
328 EXPECT_FALSE(a_helper.called_);
329 EXPECT_FALSE(b_helper.called_);
330 // Wait for load & queued tasks.
331 base::MessageLoop::current()->RunUntilIdle();
332 EXPECT_EQ(1, delete_finished);
333 EXPECT_EQ(1, store.GetChannelIDCount());
334 EXPECT_FALSE(key);
335 EXPECT_TRUE(a_helper.called_);
336 EXPECT_EQ(ERR_FILE_NOT_FOUND, a_helper.err_);
337 EXPECT_EQ("a.com", a_helper.server_identifier_);
338 EXPECT_FALSE(a_helper.key_);
339 EXPECT_TRUE(b_helper.called_);
340 EXPECT_EQ(OK, b_helper.err_);
341 EXPECT_EQ("b.com", b_helper.server_identifier_);
342 EXPECT_TRUE(KeysEqual(expected_key.get(), b_helper.key_.get()));
345 TEST(DefaultChannelIDStoreTest, TestGetAll) {
346 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
347 DefaultChannelIDStore store(persistent_store.get());
349 EXPECT_EQ(0, store.GetChannelIDCount());
350 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
351 "verisign.com", base::Time(),
352 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
353 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
354 "google.com", base::Time(),
355 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
356 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
357 "harvard.com", base::Time(),
358 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
359 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
360 "mit.com", base::Time(),
361 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
362 // Wait for load & queued set tasks.
363 base::MessageLoop::current()->RunUntilIdle();
365 EXPECT_EQ(4, store.GetChannelIDCount());
366 ChannelIDStore::ChannelIDList channel_ids;
367 store.GetAllChannelIDs(base::Bind(GetAllCallback, &channel_ids));
368 EXPECT_EQ(4u, channel_ids.size());
371 TEST(DefaultChannelIDStoreTest, TestInitializeFrom) {
372 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
373 DefaultChannelIDStore store(persistent_store.get());
374 scoped_ptr<crypto::ECPrivateKey> preexisting_key(
375 crypto::ECPrivateKey::Create());
376 scoped_ptr<crypto::ECPrivateKey> both_key(crypto::ECPrivateKey::Create());
377 scoped_ptr<crypto::ECPrivateKey> copied_key(crypto::ECPrivateKey::Create());
379 store.SetChannelID(make_scoped_ptr(
380 new ChannelIDStore::ChannelID("preexisting.com", base::Time(),
381 make_scoped_ptr(preexisting_key->Copy()))));
382 store.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
383 "both.com", base::Time(),
384 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
385 // Wait for load & queued set tasks.
386 base::MessageLoop::current()->RunUntilIdle();
387 EXPECT_EQ(2, store.GetChannelIDCount());
389 ChannelIDStore::ChannelIDList source_channel_ids;
390 source_channel_ids.push_back(ChannelIDStore::ChannelID(
391 "both.com", base::Time(),
392 // Key differs from above to test that existing entries are overwritten.
393 make_scoped_ptr(both_key->Copy())));
394 source_channel_ids.push_back(ChannelIDStore::ChannelID(
395 "copied.com", base::Time(), make_scoped_ptr(copied_key->Copy())));
396 store.InitializeFrom(source_channel_ids);
397 EXPECT_EQ(3, store.GetChannelIDCount());
399 ChannelIDStore::ChannelIDList channel_ids;
400 store.GetAllChannelIDs(base::Bind(GetAllCallback, &channel_ids));
401 ASSERT_EQ(3u, channel_ids.size());
403 ChannelIDStore::ChannelIDList::iterator channel_id = channel_ids.begin();
404 EXPECT_EQ("both.com", channel_id->server_identifier());
405 EXPECT_TRUE(KeysEqual(both_key.get(), channel_id->key()));
407 ++channel_id;
408 EXPECT_EQ("copied.com", channel_id->server_identifier());
409 EXPECT_TRUE(KeysEqual(copied_key.get(), channel_id->key()));
411 ++channel_id;
412 EXPECT_EQ("preexisting.com", channel_id->server_identifier());
413 EXPECT_TRUE(KeysEqual(preexisting_key.get(), channel_id->key()));
416 TEST(DefaultChannelIDStoreTest, TestAsyncInitializeFrom) {
417 scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
418 scoped_ptr<crypto::ECPrivateKey> preexisting_key(
419 crypto::ECPrivateKey::Create());
420 scoped_ptr<crypto::ECPrivateKey> both_key(crypto::ECPrivateKey::Create());
421 scoped_ptr<crypto::ECPrivateKey> copied_key(crypto::ECPrivateKey::Create());
423 persistent_store->AddChannelID(
424 ChannelIDStore::ChannelID("preexisting.com", base::Time(),
425 make_scoped_ptr(preexisting_key->Copy())));
426 persistent_store->AddChannelID(ChannelIDStore::ChannelID(
427 "both.com", base::Time(),
428 make_scoped_ptr(crypto::ECPrivateKey::Create())));
430 DefaultChannelIDStore store(persistent_store.get());
431 ChannelIDStore::ChannelIDList source_channel_ids;
432 source_channel_ids.push_back(ChannelIDStore::ChannelID(
433 "both.com", base::Time(),
434 // Key differs from above to test that existing entries are overwritten.
435 make_scoped_ptr(both_key->Copy())));
436 source_channel_ids.push_back(ChannelIDStore::ChannelID(
437 "copied.com", base::Time(), make_scoped_ptr(copied_key->Copy())));
438 store.InitializeFrom(source_channel_ids);
439 EXPECT_EQ(0, store.GetChannelIDCount());
440 // Wait for load & queued tasks.
441 base::MessageLoop::current()->RunUntilIdle();
442 EXPECT_EQ(3, store.GetChannelIDCount());
444 ChannelIDStore::ChannelIDList channel_ids;
445 store.GetAllChannelIDs(base::Bind(GetAllCallback, &channel_ids));
446 ASSERT_EQ(3u, channel_ids.size());
448 ChannelIDStore::ChannelIDList::iterator channel_id = channel_ids.begin();
449 EXPECT_EQ("both.com", channel_id->server_identifier());
450 EXPECT_TRUE(KeysEqual(both_key.get(), channel_id->key()));
452 ++channel_id;
453 EXPECT_EQ("copied.com", channel_id->server_identifier());
454 EXPECT_TRUE(KeysEqual(copied_key.get(), channel_id->key()));
456 ++channel_id;
457 EXPECT_EQ("preexisting.com", channel_id->server_identifier());
458 EXPECT_TRUE(KeysEqual(preexisting_key.get(), channel_id->key()));
461 } // namespace net