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/prefs/pref_filter.h" | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
used?
dgrogan
2014/04/12 00:32:45
Removed.
| |
13 #include "base/run_loop.h" | |
14 #include "base/values.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 namespace base { | |
19 namespace { | |
20 | |
21 class MockPrefStoreObserver : public PrefStore::Observer { | |
22 public: | |
23 MOCK_METHOD1(OnPrefValueChanged, void(const std::string&)); | |
24 MOCK_METHOD1(OnInitializationCompleted, void(bool)); | |
25 }; | |
26 | |
27 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate { | |
28 public: | |
29 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError)); | |
30 }; | |
31 | |
32 } // namespace | |
33 | |
34 class LevelDBPrefStoreTest : public testing::Test { | |
35 protected: | |
36 virtual void SetUp() OVERRIDE { | |
37 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
38 | |
39 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_)); | |
40 data_dir_ = data_dir_.AppendASCII("prefs"); | |
41 ASSERT_TRUE(PathExists(data_dir_)); | |
42 } | |
43 | |
44 void Open() { | |
45 pref_store_ = new LevelDBPrefStore( | |
46 temp_dir_.path(), message_loop_.message_loop_proxy().get()); | |
47 EXPECT_EQ(LevelDBPrefStore::PREF_READ_ERROR_NONE, pref_store_->ReadPrefs()); | |
48 } | |
49 | |
50 void Close() { | |
51 pref_store_ = NULL; | |
52 RunLoop().RunUntilIdle(); | |
53 } | |
54 | |
55 void CloseAndReopen() { | |
56 Close(); | |
57 Open(); | |
58 } | |
59 | |
60 // The path to temporary directory used to contain the test operations. | |
61 base::ScopedTempDir temp_dir_; | |
62 // The path to the directory where the test data is stored in the source tree. | |
63 base::FilePath data_dir_; | |
64 // A message loop that we can use as the file thread message loop. | |
65 MessageLoop message_loop_; | |
66 | |
67 scoped_refptr<LevelDBPrefStore> pref_store_; | |
68 }; | |
69 | |
70 TEST_F(LevelDBPrefStoreTest, PutAndGet) { | |
71 Open(); | |
72 const std::string key = "some.key"; | |
73 pref_store_->SetValue(key, new FundamentalValue(5)); | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
Might want to put a GetValue check here before run
dgrogan
2014/04/12 00:32:45
Removed the RunUntilIdle completely, it wasn't ser
| |
74 RunLoop().RunUntilIdle(); | |
75 FundamentalValue orig_value(5); | |
76 const base::Value* actual_value; | |
77 EXPECT_TRUE(pref_store_->GetValue(key, &actual_value)); | |
78 EXPECT_TRUE(orig_value.Equals(actual_value)); | |
79 } | |
80 | |
81 TEST_F(LevelDBPrefStoreTest, PutAndGetPersistent) { | |
82 Open(); | |
83 const std::string key = "some.key"; | |
84 pref_store_->SetValue(key, new FundamentalValue(5)); | |
85 RunLoop().RunUntilIdle(); | |
86 | |
87 CloseAndReopen(); | |
88 const base::Value* actual_value = NULL; | |
89 FundamentalValue orig_value(5); | |
90 EXPECT_TRUE(pref_store_->GetValue(key, &actual_value)); | |
91 EXPECT_TRUE(orig_value.Equals(actual_value)); | |
92 } | |
93 | |
94 TEST_F(LevelDBPrefStoreTest, BasicObserver) { | |
95 scoped_refptr<LevelDBPrefStore> pref_store = new LevelDBPrefStore( | |
96 temp_dir_.path(), message_loop_.message_loop_proxy().get()); | |
97 MockPrefStoreObserver mock_observer; | |
98 pref_store->AddObserver(&mock_observer); | |
99 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
100 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
101 testing::Mock::VerifyAndClearExpectations(&mock_observer); | |
102 | |
103 const std::string key = "some.key"; | |
104 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(1); | |
105 pref_store->SetValue(key, new FundamentalValue(5)); | |
106 | |
107 pref_store->RemoveObserver(&mock_observer); | |
108 } | |
109 | |
110 TEST_F(LevelDBPrefStoreTest, SetValueSilently) { | |
111 Open(); | |
112 | |
113 MockPrefStoreObserver mock_observer; | |
114 pref_store_->AddObserver(&mock_observer); | |
115 const std::string key = "some.key"; | |
116 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(0); | |
117 pref_store_->SetValueSilently(key, new FundamentalValue(30)); | |
118 RunLoop().RunUntilIdle(); | |
119 pref_store_->RemoveObserver(&mock_observer); | |
120 | |
121 CloseAndReopen(); | |
122 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)); | |
126 } | |
127 | |
128 TEST_F(LevelDBPrefStoreTest, GetMutableValue) { | |
129 Open(); | |
130 | |
131 const std::string key = "some.key"; | |
132 base::DictionaryValue* orig_value = new DictionaryValue; | |
133 orig_value->SetInteger("key2", 25); | |
134 pref_store_->SetValue(key, orig_value); | |
135 base::Value* actual_value; | |
136 | |
137 EXPECT_TRUE(pref_store_->GetMutableValue(key, &actual_value)); | |
138 EXPECT_TRUE(orig_value->Equals(actual_value)); | |
139 base::DictionaryValue* dict_value = | |
140 static_cast<base::DictionaryValue*>(actual_value); | |
141 dict_value->SetInteger("key2", 30); | |
142 pref_store_->ReportValueChanged(key); | |
143 RunLoop().RunUntilIdle(); | |
144 | |
145 // Ensure the new value is stored in memory. | |
146 const base::Value* retrieved_value; | |
147 EXPECT_TRUE(pref_store_->GetValue(key, &retrieved_value)); | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
Suggestion: Instead of decoding the dictionary by
dgrogan
2014/04/12 00:32:45
Done.
| |
148 const base::DictionaryValue* dictionary; | |
149 EXPECT_TRUE(retrieved_value->GetAsDictionary(&dictionary)); | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
This should be ASSERT_TRUE() (here and below), the
dgrogan
2014/04/12 00:32:45
Obviated by your suggestion above.
| |
150 const base::Value* inner_value; | |
151 EXPECT_TRUE(dictionary->Get("key2", &inner_value)); | |
152 int inner_integer; | |
153 EXPECT_TRUE(inner_value->GetAsInteger(&inner_integer)); | |
154 EXPECT_EQ(30, inner_integer); | |
155 | |
156 // Ensure the new value is persisted to disk. | |
157 CloseAndReopen(); | |
158 EXPECT_TRUE(pref_store_->GetValue(key, &retrieved_value)); | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
... and you could reuse that expected dictionary h
dgrogan
2014/04/12 00:32:45
Done.
| |
159 EXPECT_TRUE(retrieved_value->GetAsDictionary(&dictionary)); | |
160 EXPECT_TRUE(dictionary->Get("key2", &inner_value)); | |
161 EXPECT_TRUE(inner_value->GetAsInteger(&inner_integer)); | |
162 EXPECT_EQ(30, inner_integer); | |
163 } | |
164 | |
165 TEST_F(LevelDBPrefStoreTest, RemoveFromMemory) { | |
166 Open(); | |
167 const std::string key = "some.key"; | |
168 pref_store_->SetValue(key, new FundamentalValue(5)); | |
169 | |
170 MockPrefStoreObserver mock_observer; | |
171 pref_store_->AddObserver(&mock_observer); | |
172 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(1); | |
173 pref_store_->RemoveValue(key); | |
174 pref_store_->RemoveObserver(&mock_observer); | |
175 RunLoop().RunUntilIdle(); | |
176 const base::Value* retrieved_value; | |
177 EXPECT_FALSE(pref_store_->GetValue(key, &retrieved_value)); | |
178 | |
179 CloseAndReopen(); | |
180 | |
181 EXPECT_FALSE(pref_store_->GetValue(key, &retrieved_value)); | |
182 } | |
183 | |
184 TEST_F(LevelDBPrefStoreTest, RemoveFromDisk) { | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
Isn't this mostly identical with RemoveFromMemory
dgrogan
2014/04/12 00:32:45
The second was written because the first didn't ca
| |
185 Open(); | |
186 const std::string key = "some.key"; | |
187 pref_store_->SetValue(key, new FundamentalValue(5)); | |
188 | |
189 CloseAndReopen(); | |
190 | |
191 MockPrefStoreObserver mock_observer; | |
192 pref_store_->AddObserver(&mock_observer); | |
193 EXPECT_CALL(mock_observer, OnPrefValueChanged(key)).Times(1); | |
194 pref_store_->RemoveValue(key); | |
195 pref_store_->RemoveObserver(&mock_observer); | |
196 RunLoop().RunUntilIdle(); | |
197 | |
198 CloseAndReopen(); | |
199 | |
200 const base::Value* retrieved_value; | |
201 EXPECT_FALSE(pref_store_->GetValue(key, &retrieved_value)); | |
202 } | |
203 | |
204 TEST_F(LevelDBPrefStoreTest, OpenAsync) { | |
205 // First set a key/value with a synchronous connection. | |
206 Open(); | |
207 const std::string key = "some.key"; | |
208 pref_store_->SetValue(key, new FundamentalValue(5)); | |
209 Close(); | |
210 | |
211 scoped_refptr<LevelDBPrefStore> pref_store(new LevelDBPrefStore( | |
212 temp_dir_.path(), message_loop_.message_loop_proxy().get())); | |
213 MockReadErrorDelegate* delegate = new MockReadErrorDelegate; | |
214 pref_store->ReadPrefsAsync(delegate); | |
215 | |
216 MockPrefStoreObserver mock_observer; | |
217 pref_store->AddObserver(&mock_observer); | |
218 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
219 RunLoop().RunUntilIdle(); | |
220 pref_store->RemoveObserver(&mock_observer); | |
221 | |
222 const base::Value* result; | |
223 EXPECT_TRUE(pref_store->GetValue("some.key", &result)); | |
224 int int_value; | |
225 EXPECT_TRUE(result->GetAsInteger(&int_value)); | |
226 EXPECT_EQ(5, int_value); | |
227 | |
228 pref_store = NULL; | |
229 } | |
230 | |
231 TEST_F(LevelDBPrefStoreTest, OpenAsyncError) { | |
232 // Open a connection that will lock the database. | |
233 Open(); | |
234 | |
235 // Try to open an async connection to the same database. | |
236 scoped_refptr<LevelDBPrefStore> pref_store(new LevelDBPrefStore( | |
237 temp_dir_.path(), message_loop_.message_loop_proxy().get())); | |
238 MockReadErrorDelegate* delegate = new MockReadErrorDelegate; | |
239 pref_store->ReadPrefsAsync(delegate); | |
240 | |
241 MockPrefStoreObserver mock_observer; | |
242 pref_store->AddObserver(&mock_observer); | |
243 EXPECT_CALL(*delegate, | |
244 OnError(PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO_ERROR)) | |
245 .Times(1); | |
246 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
247 RunLoop().RunUntilIdle(); | |
248 pref_store->RemoveObserver(&mock_observer); | |
249 | |
250 EXPECT_TRUE(pref_store->ReadOnly()); | |
251 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO_ERROR, | |
252 pref_store->GetReadError()); | |
253 | |
254 // Sync connection to the database will be closed by the destructor. | |
255 } | |
256 | |
257 TEST_F(LevelDBPrefStoreTest, RepairCorrupt) { | |
258 // Open a database where CURRENT has no newline. Ensure that repair is called | |
259 // and there is no error reading the database. | |
260 FilePath corrupted_dir = data_dir_.AppendASCII("corrupted_leveldb"); | |
261 base::FilePath dest = temp_dir_.path().AppendASCII("corrupted_leveldb"); | |
262 const bool kRecursive = true; | |
263 ASSERT_TRUE(CopyDirectory(corrupted_dir, dest, kRecursive)); | |
264 pref_store_ = | |
265 new LevelDBPrefStore(dest, message_loop_.message_loop_proxy().get()); | |
266 EXPECT_EQ(LevelDBPrefStore::PREF_READ_ERROR_NONE, pref_store_->ReadPrefs()); | |
267 } | |
268 | |
269 TEST_F(LevelDBPrefStoreTest, Values) { | |
270 Open(); | |
271 pref_store_->SetValue("boolean", new FundamentalValue(false)); | |
272 pref_store_->SetValue("integer", new FundamentalValue(10)); | |
273 pref_store_->SetValue("double", new FundamentalValue(10.3)); | |
274 pref_store_->SetValue("string", new StringValue("some string")); | |
275 | |
276 // Extra block so that variable names can be reused below. | |
277 { | |
278 DictionaryValue* dict_value = new DictionaryValue; | |
Mattias Nissler (ping if slow)
2014/03/20 09:32:25
Again, I suggest keeping copies of these objects s
dgrogan
2014/04/12 00:32:45
Done.
| |
279 dict_value->Set("boolean", new FundamentalValue(true)); | |
280 pref_store_->SetValue("dictionary", dict_value); | |
281 | |
282 ListValue* list_value = new ListValue; | |
283 list_value->Set(2, new StringValue("string in list")); | |
284 pref_store_->SetValue("list", list_value); | |
285 | |
286 // Do something nontrivial as well. | |
287 DictionaryValue* compound_value = new DictionaryValue; | |
288 ListValue* outer_list = new ListValue; | |
289 ListValue* inner_list = new ListValue; | |
290 inner_list->Set(0, new FundamentalValue(5)); | |
291 outer_list->Set(1, inner_list); | |
292 compound_value->Set("compound_lists", outer_list); | |
293 pref_store_->SetValue("compound_value", compound_value); | |
294 } | |
295 | |
296 CloseAndReopen(); | |
297 | |
298 const Value* value; | |
299 EXPECT_TRUE(pref_store_->GetValue("boolean", &value)); | |
300 bool boolean_value; | |
301 EXPECT_TRUE(value->GetAsBoolean(&boolean_value)); | |
302 EXPECT_EQ(false, boolean_value); | |
303 | |
304 EXPECT_TRUE(pref_store_->GetValue("integer", &value)); | |
305 int integer_value; | |
306 EXPECT_TRUE(value->GetAsInteger(&integer_value)); | |
307 EXPECT_EQ(10, integer_value); | |
308 | |
309 EXPECT_TRUE(pref_store_->GetValue("double", &value)); | |
310 double double_value; | |
311 EXPECT_TRUE(value->GetAsDouble(&double_value)); | |
312 EXPECT_LT(10.29, double_value); | |
313 EXPECT_GT(10.31, double_value); | |
314 | |
315 EXPECT_TRUE(pref_store_->GetValue("string", &value)); | |
316 std::string string_value; | |
317 EXPECT_TRUE(value->GetAsString(&string_value)); | |
318 EXPECT_EQ("some string", string_value); | |
319 | |
320 EXPECT_TRUE(pref_store_->GetValue("dictionary", &value)); | |
321 const DictionaryValue* dict_value; | |
322 EXPECT_TRUE(value->GetAsDictionary(&dict_value)); | |
323 EXPECT_TRUE(dict_value->GetBoolean("boolean", &boolean_value)); | |
324 EXPECT_EQ(true, boolean_value); | |
325 | |
326 EXPECT_TRUE(pref_store_->GetValue("list", &value)); | |
327 const ListValue* list_value; | |
328 EXPECT_TRUE(value->GetAsList(&list_value)); | |
329 EXPECT_TRUE(list_value->GetString(2, &string_value)); | |
330 EXPECT_EQ("string in list", string_value); | |
331 | |
332 EXPECT_TRUE(pref_store_->GetValue("compound_value", &value)); | |
333 EXPECT_TRUE(value->GetAsDictionary(&dict_value)); | |
334 const ListValue* outer_list; | |
335 const ListValue* inner_list; | |
336 EXPECT_TRUE(dict_value->GetList("compound_lists", &outer_list)); | |
337 EXPECT_TRUE(outer_list->GetList(1, &inner_list)); | |
338 EXPECT_TRUE(inner_list->GetInteger(0, &integer_value)); | |
339 EXPECT_EQ(5, integer_value); | |
340 } | |
341 | |
342 } // namespace base | |
OLD | NEW |