OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "base/prefs/leveldb_pref_store.h" | |
6 | |
7 #include "base/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 "testing/gmock/include/gmock/gmock.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 namespace base { | |
18 namespace { | |
19 | |
20 class MockPrefStoreObserver : public PrefStore::Observer { | |
21 public: | |
22 MOCK_METHOD1(OnPrefValueChanged, void(const std::string&)); | |
23 MOCK_METHOD1(OnInitializationCompleted, void(bool)); | |
24 }; | |
25 | |
26 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate { | |
27 public: | |
28 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError)); | |
29 }; | |
30 | |
31 } // namespace | |
32 | |
33 class LevelDBPrefStoreTest : public testing::Test { | |
34 protected: | |
35 virtual void SetUp() OVERRIDE { | |
36 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
37 | |
38 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_)); | |
39 data_dir_ = data_dir_.AppendASCII("prefs"); | |
40 ASSERT_TRUE(PathExists(data_dir_)); | |
41 } | |
42 | |
43 void Open() { | |
44 pref_store_ = new LevelDBPrefStore( | |
45 temp_dir_.path(), message_loop_.message_loop_proxy().get()); | |
46 EXPECT_EQ(LevelDBPrefStore::PREF_READ_ERROR_NONE, pref_store_->ReadPrefs()); | |
47 } | |
48 | |
49 void Close() { | |
50 pref_store_ = NULL; | |
51 RunLoop().RunUntilIdle(); | |
52 } | |
53 | |
54 void CloseAndReopen() { | |
55 Close(); | |
56 Open(); | |
57 } | |
58 | |
59 // The path to temporary directory used to contain the test operations. | |
60 base::ScopedTempDir temp_dir_; | |
61 // The path to the directory where the test data is stored in the source tree. | |
62 base::FilePath data_dir_; | |
63 // A message loop that we can use as the file thread message loop. | |
64 MessageLoop message_loop_; | |
65 | |
66 scoped_refptr<LevelDBPrefStore> pref_store_; | |
67 }; | |
68 | |
69 TEST_F(LevelDBPrefStoreTest, PutAndGet) { | |
70 Open(); | |
71 const std::string key = "some.key"; | |
72 pref_store_->SetValue(key, new FundamentalValue(5)); | |
73 FundamentalValue orig_value(5); | |
74 const base::Value* actual_value; | |
75 EXPECT_TRUE(pref_store_->GetValue(key, &actual_value)); | |
76 EXPECT_TRUE(orig_value.Equals(actual_value)); | |
77 } | |
78 | |
79 TEST_F(LevelDBPrefStoreTest, PutAndGetPersistent) { | |
80 Open(); | |
81 const std::string key = "some.key"; | |
82 pref_store_->SetValue(key, new FundamentalValue(5)); | |
83 | |
84 CloseAndReopen(); | |
85 const base::Value* actual_value = NULL; | |
86 FundamentalValue orig_value(5); | |
87 EXPECT_TRUE(pref_store_->GetValue(key, &actual_value)); | |
88 EXPECT_TRUE(orig_value.Equals(actual_value)); | |
89 } | |
90 | |
91 TEST_F(LevelDBPrefStoreTest, BasicObserver) { | |
92 scoped_refptr<LevelDBPrefStore> pref_store = new LevelDBPrefStore( | |
93 temp_dir_.path(), message_loop_.message_loop_proxy().get()); | |
94 MockPrefStoreObserver mock_observer; | |
95 pref_store->AddObserver(&mock_observer); | |
96 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
97 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
98 testing::Mock::VerifyAndClearExpectations(&mock_observer); | |
99 | |
100 const std::string key = "some.key"; | |
101 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(1); | |
102 pref_store->SetValue(key, new FundamentalValue(5)); | |
103 | |
104 pref_store->RemoveObserver(&mock_observer); | |
105 } | |
106 | |
107 TEST_F(LevelDBPrefStoreTest, SetValueSilently) { | |
108 Open(); | |
109 | |
110 MockPrefStoreObserver mock_observer; | |
111 pref_store_->AddObserver(&mock_observer); | |
112 const std::string key = "some.key"; | |
113 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(0); | |
114 pref_store_->SetValueSilently(key, new FundamentalValue(30)); | |
115 pref_store_->RemoveObserver(&mock_observer); | |
116 | |
117 CloseAndReopen(); | |
118 FundamentalValue value(30); | |
119 const base::Value* actual_value = NULL; | |
120 EXPECT_TRUE(pref_store_->GetValue(key, &actual_value)); | |
121 EXPECT_TRUE(base::Value::Equals(&value, actual_value)); | |
122 } | |
123 | |
124 TEST_F(LevelDBPrefStoreTest, GetMutableValue) { | |
125 Open(); | |
126 | |
127 const std::string key = "some.key"; | |
128 base::DictionaryValue* orig_value = new DictionaryValue; | |
129 orig_value->SetInteger("key2", 25); | |
130 pref_store_->SetValue(key, orig_value); | |
131 | |
132 base::Value* actual_value; | |
133 EXPECT_TRUE(pref_store_->GetMutableValue(key, &actual_value)); | |
134 EXPECT_TRUE(orig_value->Equals(actual_value)); | |
135 base::DictionaryValue* dict_value = | |
136 static_cast<base::DictionaryValue*>(actual_value); | |
Mattias Nissler (ping if slow)
2014/04/30 09:58:21
This is usually written as ASSERT_TRUE(actual_valu
dgrogan
2014/05/01 09:00:15
Done.
| |
137 dict_value->SetInteger("key2", 30); | |
138 pref_store_->ReportValueChanged(key); | |
139 | |
140 // Ensure the new value is stored in memory. | |
141 const base::Value* retrieved_value; | |
142 EXPECT_TRUE(pref_store_->GetValue(key, &retrieved_value)); | |
143 scoped_ptr<base::DictionaryValue> golden_value(new DictionaryValue); | |
144 golden_value->SetInteger("key2", 30); | |
145 EXPECT_TRUE(Value::Equals(golden_value.get(), retrieved_value)); | |
146 | |
147 // Ensure the new value is persisted to disk. | |
148 CloseAndReopen(); | |
149 EXPECT_TRUE(pref_store_->GetValue(key, &retrieved_value)); | |
150 EXPECT_TRUE(Value::Equals(golden_value.get(), retrieved_value)); | |
151 } | |
152 | |
153 TEST_F(LevelDBPrefStoreTest, RemoveFromMemory) { | |
154 Open(); | |
155 const std::string key = "some.key"; | |
156 pref_store_->SetValue(key, new FundamentalValue(5)); | |
157 | |
158 MockPrefStoreObserver mock_observer; | |
159 pref_store_->AddObserver(&mock_observer); | |
160 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(1); | |
161 pref_store_->RemoveValue(key); | |
162 pref_store_->RemoveObserver(&mock_observer); | |
163 | |
164 const base::Value* retrieved_value; | |
165 EXPECT_FALSE(pref_store_->GetValue(key, &retrieved_value)); | |
166 } | |
167 | |
168 TEST_F(LevelDBPrefStoreTest, RemoveFromDisk) { | |
169 Open(); | |
170 const std::string key = "some.key"; | |
171 pref_store_->SetValue(key, new FundamentalValue(5)); | |
172 | |
173 CloseAndReopen(); | |
174 | |
175 pref_store_->RemoveValue(key); | |
176 | |
177 CloseAndReopen(); | |
178 | |
179 const base::Value* retrieved_value; | |
180 EXPECT_FALSE(pref_store_->GetValue(key, &retrieved_value)); | |
181 } | |
182 | |
183 TEST_F(LevelDBPrefStoreTest, OpenAsync) { | |
184 // First set a key/value with a synchronous connection. | |
185 Open(); | |
186 const std::string key = "some.key"; | |
187 pref_store_->SetValue(key, new FundamentalValue(5)); | |
188 Close(); | |
189 | |
190 scoped_refptr<LevelDBPrefStore> pref_store(new LevelDBPrefStore( | |
191 temp_dir_.path(), message_loop_.message_loop_proxy().get())); | |
192 MockReadErrorDelegate* delegate = new MockReadErrorDelegate; | |
193 pref_store->ReadPrefsAsync(delegate); | |
194 | |
195 MockPrefStoreObserver mock_observer; | |
196 pref_store->AddObserver(&mock_observer); | |
197 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
198 RunLoop().RunUntilIdle(); | |
199 pref_store->RemoveObserver(&mock_observer); | |
200 | |
201 const base::Value* result; | |
202 EXPECT_TRUE(pref_store->GetValue("some.key", &result)); | |
203 int int_value; | |
204 EXPECT_TRUE(result->GetAsInteger(&int_value)); | |
205 EXPECT_EQ(5, int_value); | |
206 | |
207 pref_store = NULL; | |
208 } | |
209 | |
210 TEST_F(LevelDBPrefStoreTest, OpenAsyncError) { | |
211 // Open a connection that will lock the database. | |
212 Open(); | |
213 | |
214 // Try to open an async connection to the same database. | |
215 scoped_refptr<LevelDBPrefStore> pref_store(new LevelDBPrefStore( | |
216 temp_dir_.path(), message_loop_.message_loop_proxy().get())); | |
217 MockReadErrorDelegate* delegate = new MockReadErrorDelegate; | |
218 pref_store->ReadPrefsAsync(delegate); | |
219 | |
220 MockPrefStoreObserver mock_observer; | |
221 pref_store->AddObserver(&mock_observer); | |
222 EXPECT_CALL(*delegate, | |
223 OnError(PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO)) | |
224 .Times(1); | |
225 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
226 RunLoop().RunUntilIdle(); | |
227 pref_store->RemoveObserver(&mock_observer); | |
228 | |
229 EXPECT_TRUE(pref_store->ReadOnly()); | |
230 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO, | |
231 pref_store->GetReadError()); | |
232 | |
233 // Sync connection to the database will be closed by the destructor. | |
234 } | |
235 | |
236 TEST_F(LevelDBPrefStoreTest, RepairCorrupt) { | |
237 // Open a database where CURRENT has no newline. Ensure that repair is called | |
238 // and there is no error reading the database. | |
239 FilePath corrupted_dir = data_dir_.AppendASCII("corrupted_leveldb"); | |
240 base::FilePath dest = temp_dir_.path().AppendASCII("corrupted_leveldb"); | |
241 const bool kRecursive = true; | |
242 ASSERT_TRUE(CopyDirectory(corrupted_dir, dest, kRecursive)); | |
243 pref_store_ = | |
244 new LevelDBPrefStore(dest, message_loop_.message_loop_proxy().get()); | |
245 EXPECT_EQ(LevelDBPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION, | |
246 pref_store_->ReadPrefs()); | |
247 } | |
248 | |
249 TEST_F(LevelDBPrefStoreTest, Values) { | |
250 Open(); | |
251 pref_store_->SetValue("boolean", new FundamentalValue(false)); | |
252 pref_store_->SetValue("integer", new FundamentalValue(10)); | |
253 pref_store_->SetValue("double", new FundamentalValue(10.3)); | |
254 pref_store_->SetValue("string", new StringValue("some string")); | |
255 | |
256 DictionaryValue* dict_value = new DictionaryValue; | |
257 dict_value->Set("boolean", new FundamentalValue(true)); | |
258 scoped_ptr<DictionaryValue> golden_dict_value(dict_value->DeepCopy()); | |
259 pref_store_->SetValue("dictionary", dict_value); | |
260 | |
261 ListValue* list_value = new ListValue; | |
262 list_value->Set(2, new StringValue("string in list")); | |
263 scoped_ptr<ListValue> golden_list_value(list_value->DeepCopy()); | |
264 pref_store_->SetValue("list", list_value); | |
265 | |
266 // Do something nontrivial as well. | |
267 DictionaryValue* compound_value = new DictionaryValue; | |
268 ListValue* outer_list = new ListValue; | |
269 ListValue* inner_list = new ListValue; | |
270 inner_list->Set(0, new FundamentalValue(5)); | |
271 outer_list->Set(1, inner_list); | |
272 compound_value->Set("compound_lists", outer_list); | |
273 scoped_ptr<DictionaryValue> golden_compound_value(compound_value->DeepCopy()); | |
274 pref_store_->SetValue("compound_value", compound_value); | |
275 | |
276 CloseAndReopen(); | |
277 | |
278 const Value* value; | |
279 EXPECT_TRUE(pref_store_->GetValue("boolean", &value)); | |
280 EXPECT_TRUE(FundamentalValue(false).Equals(value)); | |
281 | |
282 EXPECT_TRUE(pref_store_->GetValue("integer", &value)); | |
283 EXPECT_TRUE(FundamentalValue(10).Equals(value)); | |
284 | |
285 EXPECT_TRUE(pref_store_->GetValue("double", &value)); | |
286 EXPECT_TRUE(FundamentalValue(10.3).Equals(value)); | |
287 | |
288 EXPECT_TRUE(pref_store_->GetValue("string", &value)); | |
289 EXPECT_TRUE(StringValue("some string").Equals(value)); | |
290 | |
291 EXPECT_TRUE(pref_store_->GetValue("dictionary", &value)); | |
292 EXPECT_TRUE(Value::Equals(golden_dict_value.get(), value)); | |
293 | |
294 EXPECT_TRUE(pref_store_->GetValue("list", &value)); | |
295 EXPECT_TRUE(Value::Equals(golden_list_value.get(), value)); | |
296 | |
297 EXPECT_TRUE(pref_store_->GetValue("compound_value", &value)); | |
298 EXPECT_TRUE(Value::Equals(golden_compound_value.get(), value)); | |
299 } | |
300 | |
301 } // namespace base | |
OLD | NEW |