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.
5 #include "components/gcm_driver/crypto/gcm_key_store.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "crypto/curve25519.h"
13 #include "testing/gtest/include/gtest/gtest.h"
19 const char kFakeAppId
[] = "my_app_id";
20 const char kSecondFakeAppId
[] = "my_other_app_id";
22 class GCMKeyStoreTest
: public ::testing::Test
{
25 ~GCMKeyStoreTest() override
{}
27 void SetUp() override
{
28 ASSERT_TRUE(scoped_temp_dir_
.CreateUniqueTempDir());
32 void TearDown() override
{
33 gcm_key_store_
.reset();
35 // |gcm_key_store_| owns a ProtoDatabaseImpl whose destructor deletes the
36 // underlying LevelDB database on the task runner.
37 base::RunLoop().RunUntilIdle();
40 // Creates the GCM Key Store instance. May be called from within a test's body
41 // to re-create the key store, causing the database to re-open.
42 void CreateKeyStore() {
44 new GCMKeyStore(scoped_temp_dir_
.path(), message_loop_
.task_runner()));
47 // Callback to use with GCMKeyStore::{GetKeys, CreateKeys} calls.
48 void GotKeys(KeyPair
* pair_out
, const KeyPair
& pair
) {
54 // Callback to use with GCMKeyStore::DeleteKeys calls.
55 void DeletedKeys(bool* success_out
, bool success
) {
58 *success_out
= success
;
62 GCMKeyStore
* gcm_key_store() { return gcm_key_store_
.get(); }
65 base::MessageLoop message_loop_
;
66 base::ScopedTempDir scoped_temp_dir_
;
68 scoped_ptr
<GCMKeyStore
> gcm_key_store_
;
71 TEST_F(GCMKeyStoreTest
, CreatedByDefault
) {
73 gcm_key_store()->GetKeys(kFakeAppId
,
74 base::Bind(&GCMKeyStoreTest::GotKeys
,
75 base::Unretained(this), &pair
));
77 base::RunLoop().RunUntilIdle();
79 ASSERT_FALSE(pair
.IsInitialized());
80 EXPECT_FALSE(pair
.has_type());
83 TEST_F(GCMKeyStoreTest
, CreateAndGetKeys
) {
85 gcm_key_store()->CreateKeys(kFakeAppId
,
86 base::Bind(&GCMKeyStoreTest::GotKeys
,
87 base::Unretained(this), &pair
));
89 base::RunLoop().RunUntilIdle();
91 ASSERT_TRUE(pair
.IsInitialized());
93 ASSERT_TRUE(pair
.has_private_key());
94 EXPECT_EQ(crypto::curve25519::kScalarBytes
, pair
.private_key().size());
96 ASSERT_TRUE(pair
.has_public_key());
97 EXPECT_EQ(crypto::curve25519::kBytes
, pair
.public_key().size());
100 gcm_key_store()->GetKeys(kFakeAppId
,
101 base::Bind(&GCMKeyStoreTest::GotKeys
,
102 base::Unretained(this), &read_pair
));
104 base::RunLoop().RunUntilIdle();
106 ASSERT_TRUE(read_pair
.IsInitialized());
108 EXPECT_EQ(pair
.type(), read_pair
.type());
109 EXPECT_EQ(pair
.private_key(), read_pair
.private_key());
110 EXPECT_EQ(pair
.public_key(), read_pair
.public_key());
113 TEST_F(GCMKeyStoreTest
, KeysPersistenceBetweenInstances
) {
115 gcm_key_store()->CreateKeys(kFakeAppId
,
116 base::Bind(&GCMKeyStoreTest::GotKeys
,
117 base::Unretained(this), &pair
));
119 base::RunLoop().RunUntilIdle();
121 ASSERT_TRUE(pair
.IsInitialized());
123 // Create a new GCM Key Store instance.
127 gcm_key_store()->GetKeys(kFakeAppId
,
128 base::Bind(&GCMKeyStoreTest::GotKeys
,
129 base::Unretained(this), &read_pair
));
131 base::RunLoop().RunUntilIdle();
133 ASSERT_TRUE(read_pair
.IsInitialized());
134 EXPECT_TRUE(read_pair
.has_type());
137 TEST_F(GCMKeyStoreTest
, CreateAndDeleteKeys
) {
139 gcm_key_store()->CreateKeys(kFakeAppId
,
140 base::Bind(&GCMKeyStoreTest::GotKeys
,
141 base::Unretained(this), &pair
));
143 base::RunLoop().RunUntilIdle();
145 ASSERT_TRUE(pair
.IsInitialized());
148 gcm_key_store()->GetKeys(kFakeAppId
,
149 base::Bind(&GCMKeyStoreTest::GotKeys
,
150 base::Unretained(this), &read_pair
));
152 base::RunLoop().RunUntilIdle();
154 ASSERT_TRUE(read_pair
.IsInitialized());
155 EXPECT_TRUE(read_pair
.has_type());
157 bool success
= false;
158 gcm_key_store()->DeleteKeys(kFakeAppId
,
159 base::Bind(&GCMKeyStoreTest::DeletedKeys
,
160 base::Unretained(this), &success
));
162 base::RunLoop().RunUntilIdle();
164 ASSERT_TRUE(success
);
166 gcm_key_store()->GetKeys(kFakeAppId
,
167 base::Bind(&GCMKeyStoreTest::GotKeys
,
168 base::Unretained(this), &read_pair
));
170 base::RunLoop().RunUntilIdle();
172 ASSERT_FALSE(read_pair
.IsInitialized());
175 TEST_F(GCMKeyStoreTest
, GetKeysMultipleAppIds
) {
177 gcm_key_store()->CreateKeys(kFakeAppId
,
178 base::Bind(&GCMKeyStoreTest::GotKeys
,
179 base::Unretained(this), &pair
));
181 base::RunLoop().RunUntilIdle();
183 ASSERT_TRUE(pair
.IsInitialized());
185 gcm_key_store()->CreateKeys(kSecondFakeAppId
,
186 base::Bind(&GCMKeyStoreTest::GotKeys
,
187 base::Unretained(this), &pair
));
189 base::RunLoop().RunUntilIdle();
191 ASSERT_TRUE(pair
.IsInitialized());
194 gcm_key_store()->GetKeys(kFakeAppId
,
195 base::Bind(&GCMKeyStoreTest::GotKeys
,
196 base::Unretained(this), &read_pair
));
198 base::RunLoop().RunUntilIdle();
200 ASSERT_TRUE(read_pair
.IsInitialized());
201 EXPECT_TRUE(read_pair
.has_type());
204 TEST_F(GCMKeyStoreTest
, SuccessiveCallsBeforeInitialization
) {
206 gcm_key_store()->CreateKeys(kFakeAppId
,
207 base::Bind(&GCMKeyStoreTest::GotKeys
,
208 base::Unretained(this), &pair
));
210 // Deliberately do not run the message loop, so that the callback has not
211 // been resolved yet. The following EXPECT() ensures this.
212 EXPECT_FALSE(pair
.IsInitialized());
215 gcm_key_store()->GetKeys(kFakeAppId
,
216 base::Bind(&GCMKeyStoreTest::GotKeys
,
217 base::Unretained(this), &read_pair
));
219 EXPECT_FALSE(read_pair
.IsInitialized());
221 // Now run the message loop. Both tasks should have finished executing. Due
222 // to the asynchronous nature of operations, however, we can't rely on the
223 // write to have finished before the read begins.
224 base::RunLoop().RunUntilIdle();
226 EXPECT_TRUE(pair
.IsInitialized());