Clean-ups in the GCMKeyStore class.
[chromium-blink-merge.git] / components / gcm_driver / crypto / gcm_key_store_unittest.cc
blob56aae8713bf600c7c7a8e5bbce3c55c4f3c31075
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"
7 #include "base/bind.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"
15 namespace gcm {
17 namespace {
19 const char kFakeAppId[] = "my_app_id";
20 const char kSecondFakeAppId[] = "my_other_app_id";
22 class GCMKeyStoreTest : public ::testing::Test {
23 public:
24 GCMKeyStoreTest() {}
25 ~GCMKeyStoreTest() override {}
27 void SetUp() override {
28 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
29 CreateKeyStore();
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() {
43 gcm_key_store_.reset(
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) {
49 DCHECK(pair_out);
51 *pair_out = pair;
54 // Callback to use with GCMKeyStore::DeleteKeys calls.
55 void DeletedKeys(bool* success_out, bool success) {
56 DCHECK(success_out);
58 *success_out = success;
61 protected:
62 GCMKeyStore* gcm_key_store() { return gcm_key_store_.get(); }
64 private:
65 base::MessageLoop message_loop_;
66 base::ScopedTempDir scoped_temp_dir_;
68 scoped_ptr<GCMKeyStore> gcm_key_store_;
71 TEST_F(GCMKeyStoreTest, CreatedByDefault) {
72 KeyPair pair;
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) {
84 KeyPair pair;
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());
99 KeyPair read_pair;
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) {
114 KeyPair pair;
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.
124 CreateKeyStore();
126 KeyPair read_pair;
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) {
138 KeyPair pair;
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());
147 KeyPair read_pair;
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) {
176 KeyPair pair;
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());
193 KeyPair read_pair;
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) {
205 KeyPair pair;
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());
214 KeyPair read_pair;
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());
229 } // namespace
231 } // namespace gcm