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 "chrome/browser/prefs/leveldb_pref_store.h"
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/path_service.h"
12 #include "base/run_loop.h"
13 #include "base/values.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
20 class MockPrefStoreObserver
: public PrefStore::Observer
{
22 MOCK_METHOD1(OnPrefValueChanged
, void(const std::string
&));
23 MOCK_METHOD1(OnInitializationCompleted
, void(bool));
26 class MockReadErrorDelegate
: public PersistentPrefStore::ReadErrorDelegate
{
28 MOCK_METHOD1(OnError
, void(PersistentPrefStore::PrefReadError
));
33 class LevelDBPrefStoreTest
: public testing::Test
{
35 virtual void SetUp() OVERRIDE
{
36 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
38 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &data_dir_
));
39 data_dir_
= data_dir_
.AppendASCII("prefs");
40 ASSERT_TRUE(PathExists(data_dir_
));
43 virtual void TearDown() OVERRIDE
{
48 pref_store_
= new LevelDBPrefStore(
49 temp_dir_
.path(), message_loop_
.message_loop_proxy().get());
50 EXPECT_EQ(LevelDBPrefStore::PREF_READ_ERROR_NONE
, pref_store_
->ReadPrefs());
55 base::RunLoop().RunUntilIdle();
58 void CloseAndReopen() {
63 // The path to temporary directory used to contain the test operations.
64 base::ScopedTempDir temp_dir_
;
65 // The path to the directory where the test data is stored in the source tree.
66 base::FilePath data_dir_
;
67 // A message loop that we can use as the file thread message loop.
68 base::MessageLoop message_loop_
;
70 scoped_refptr
<LevelDBPrefStore
> pref_store_
;
73 TEST_F(LevelDBPrefStoreTest
, PutAndGet
) {
75 const std::string key
= "some.key";
76 pref_store_
->SetValue(key
, new base::FundamentalValue(5));
77 base::FundamentalValue
orig_value(5);
78 const base::Value
* actual_value
;
79 EXPECT_TRUE(pref_store_
->GetValue(key
, &actual_value
));
80 EXPECT_TRUE(orig_value
.Equals(actual_value
));
83 TEST_F(LevelDBPrefStoreTest
, PutAndGetPersistent
) {
85 const std::string key
= "some.key";
86 pref_store_
->SetValue(key
, new base::FundamentalValue(5));
89 const base::Value
* actual_value
= NULL
;
90 base::FundamentalValue
orig_value(5);
91 EXPECT_TRUE(pref_store_
->GetValue(key
, &actual_value
));
92 EXPECT_TRUE(orig_value
.Equals(actual_value
));
95 TEST_F(LevelDBPrefStoreTest
, BasicObserver
) {
96 scoped_refptr
<LevelDBPrefStore
> pref_store
= new LevelDBPrefStore(
97 temp_dir_
.path(), message_loop_
.message_loop_proxy().get());
98 MockPrefStoreObserver mock_observer
;
99 pref_store
->AddObserver(&mock_observer
);
100 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
101 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE
, pref_store
->ReadPrefs());
102 testing::Mock::VerifyAndClearExpectations(&mock_observer
);
104 const std::string key
= "some.key";
105 EXPECT_CALL(mock_observer
, OnPrefValueChanged(key
)).Times(1);
106 pref_store
->SetValue(key
, new base::FundamentalValue(5));
108 pref_store
->RemoveObserver(&mock_observer
);
111 TEST_F(LevelDBPrefStoreTest
, SetValueSilently
) {
114 MockPrefStoreObserver mock_observer
;
115 pref_store_
->AddObserver(&mock_observer
);
116 const std::string key
= "some.key";
117 EXPECT_CALL(mock_observer
, OnPrefValueChanged(key
)).Times(0);
118 pref_store_
->SetValueSilently(key
, new base::FundamentalValue(30));
119 pref_store_
->RemoveObserver(&mock_observer
);
122 base::FundamentalValue
value(30);
123 const base::Value
* actual_value
= NULL
;
124 EXPECT_TRUE(pref_store_
->GetValue(key
, &actual_value
));
125 EXPECT_TRUE(base::Value::Equals(&value
, actual_value
));
128 TEST_F(LevelDBPrefStoreTest
, GetMutableValue
) {
131 const std::string key
= "some.key";
132 base::DictionaryValue
* orig_value
= new base::DictionaryValue
;
133 orig_value
->SetInteger("key2", 25);
134 pref_store_
->SetValue(key
, orig_value
);
136 base::Value
* actual_value
;
137 EXPECT_TRUE(pref_store_
->GetMutableValue(key
, &actual_value
));
138 EXPECT_TRUE(orig_value
->Equals(actual_value
));
139 base::DictionaryValue
* dict_value
;
140 ASSERT_TRUE(actual_value
->GetAsDictionary(&dict_value
));
141 dict_value
->SetInteger("key2", 30);
142 pref_store_
->ReportValueChanged(key
);
144 // Ensure the new value is stored in memory.
145 const base::Value
* retrieved_value
;
146 EXPECT_TRUE(pref_store_
->GetValue(key
, &retrieved_value
));
147 scoped_ptr
<base::DictionaryValue
> golden_value(new base::DictionaryValue
);
148 golden_value
->SetInteger("key2", 30);
149 EXPECT_TRUE(base::Value::Equals(golden_value
.get(), retrieved_value
));
151 // Ensure the new value is persisted to disk.
153 EXPECT_TRUE(pref_store_
->GetValue(key
, &retrieved_value
));
154 EXPECT_TRUE(base::Value::Equals(golden_value
.get(), retrieved_value
));
157 TEST_F(LevelDBPrefStoreTest
, RemoveFromMemory
) {
159 const std::string key
= "some.key";
160 pref_store_
->SetValue(key
, new base::FundamentalValue(5));
162 MockPrefStoreObserver mock_observer
;
163 pref_store_
->AddObserver(&mock_observer
);
164 EXPECT_CALL(mock_observer
, OnPrefValueChanged(key
)).Times(1);
165 pref_store_
->RemoveValue(key
);
166 pref_store_
->RemoveObserver(&mock_observer
);
168 const base::Value
* retrieved_value
;
169 EXPECT_FALSE(pref_store_
->GetValue(key
, &retrieved_value
));
172 TEST_F(LevelDBPrefStoreTest
, RemoveFromDisk
) {
174 const std::string key
= "some.key";
175 pref_store_
->SetValue(key
, new base::FundamentalValue(5));
179 pref_store_
->RemoveValue(key
);
183 const base::Value
* retrieved_value
;
184 EXPECT_FALSE(pref_store_
->GetValue(key
, &retrieved_value
));
187 TEST_F(LevelDBPrefStoreTest
, OpenAsync
) {
188 // First set a key/value with a synchronous connection.
190 const std::string key
= "some.key";
191 pref_store_
->SetValue(key
, new base::FundamentalValue(5));
194 scoped_refptr
<LevelDBPrefStore
> pref_store(new LevelDBPrefStore(
195 temp_dir_
.path(), message_loop_
.message_loop_proxy().get()));
196 MockReadErrorDelegate
* delegate
= new MockReadErrorDelegate
;
197 pref_store
->ReadPrefsAsync(delegate
);
199 MockPrefStoreObserver mock_observer
;
200 pref_store
->AddObserver(&mock_observer
);
201 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
202 base::RunLoop().RunUntilIdle();
203 pref_store
->RemoveObserver(&mock_observer
);
205 const base::Value
* result
;
206 EXPECT_TRUE(pref_store
->GetValue("some.key", &result
));
208 EXPECT_TRUE(result
->GetAsInteger(&int_value
));
209 EXPECT_EQ(5, int_value
);
214 TEST_F(LevelDBPrefStoreTest
, OpenAsyncError
) {
215 // Open a connection that will lock the database.
218 // Try to open an async connection to the same database.
219 scoped_refptr
<LevelDBPrefStore
> pref_store(new LevelDBPrefStore(
220 temp_dir_
.path(), message_loop_
.message_loop_proxy().get()));
221 MockReadErrorDelegate
* delegate
= new MockReadErrorDelegate
;
222 pref_store
->ReadPrefsAsync(delegate
);
224 MockPrefStoreObserver mock_observer
;
225 pref_store
->AddObserver(&mock_observer
);
226 EXPECT_CALL(*delegate
,
227 OnError(PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO
))
229 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
230 base::RunLoop().RunUntilIdle();
231 pref_store
->RemoveObserver(&mock_observer
);
233 EXPECT_TRUE(pref_store
->ReadOnly());
234 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO
,
235 pref_store
->GetReadError());
237 // Sync connection to the database will be closed by the destructor.
240 TEST_F(LevelDBPrefStoreTest
, RepairCorrupt
) {
241 // Open a database where CURRENT has no newline. Ensure that repair is called
242 // and there is no error reading the database.
243 base::FilePath corrupted_dir
= data_dir_
.AppendASCII("corrupted_leveldb");
244 base::FilePath dest
= temp_dir_
.path().AppendASCII("corrupted_leveldb");
245 const bool kRecursive
= true;
246 ASSERT_TRUE(CopyDirectory(corrupted_dir
, dest
, kRecursive
));
248 new LevelDBPrefStore(dest
, message_loop_
.message_loop_proxy().get());
249 EXPECT_EQ(LevelDBPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION
,
250 pref_store_
->ReadPrefs());
253 TEST_F(LevelDBPrefStoreTest
, Values
) {
255 pref_store_
->SetValue("boolean", new base::FundamentalValue(false));
256 pref_store_
->SetValue("integer", new base::FundamentalValue(10));
257 pref_store_
->SetValue("double", new base::FundamentalValue(10.3));
258 pref_store_
->SetValue("string", new base::StringValue("some string"));
260 base::DictionaryValue
* dict_value
= new base::DictionaryValue
;
261 dict_value
->Set("boolean", new base::FundamentalValue(true));
262 scoped_ptr
<base::DictionaryValue
> golden_dict_value(dict_value
->DeepCopy());
263 pref_store_
->SetValue("dictionary", dict_value
);
265 base::ListValue
* list_value
= new base::ListValue
;
266 list_value
->Set(2, new base::StringValue("string in list"));
267 scoped_ptr
<base::ListValue
> golden_list_value(list_value
->DeepCopy());
268 pref_store_
->SetValue("list", list_value
);
270 // Do something nontrivial as well.
271 base::DictionaryValue
* compound_value
= new base::DictionaryValue
;
272 base::ListValue
* outer_list
= new base::ListValue
;
273 base::ListValue
* inner_list
= new base::ListValue
;
274 inner_list
->Set(0, new base::FundamentalValue(5));
275 outer_list
->Set(1, inner_list
);
276 compound_value
->Set("compound_lists", outer_list
);
277 scoped_ptr
<base::DictionaryValue
> golden_compound_value(
278 compound_value
->DeepCopy());
279 pref_store_
->SetValue("compound_value", compound_value
);
283 const base::Value
* value
;
284 EXPECT_TRUE(pref_store_
->GetValue("boolean", &value
));
285 EXPECT_TRUE(base::FundamentalValue(false).Equals(value
));
287 EXPECT_TRUE(pref_store_
->GetValue("integer", &value
));
288 EXPECT_TRUE(base::FundamentalValue(10).Equals(value
));
290 EXPECT_TRUE(pref_store_
->GetValue("double", &value
));
291 EXPECT_TRUE(base::FundamentalValue(10.3).Equals(value
));
293 EXPECT_TRUE(pref_store_
->GetValue("string", &value
));
294 EXPECT_TRUE(base::StringValue("some string").Equals(value
));
296 EXPECT_TRUE(pref_store_
->GetValue("dictionary", &value
));
297 EXPECT_TRUE(base::Value::Equals(golden_dict_value
.get(), value
));
299 EXPECT_TRUE(pref_store_
->GetValue("list", &value
));
300 EXPECT_TRUE(base::Value::Equals(golden_list_value
.get(), value
));
302 EXPECT_TRUE(pref_store_
->GetValue("compound_value", &value
));
303 EXPECT_TRUE(base::Value::Equals(golden_compound_value
.get(), value
));