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/json_pref_store.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <utility> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/files/file_util.h" | |
13 #include "base/files/scoped_temp_dir.h" | |
14 #include "base/location.h" | |
15 #include "base/macros.h" | |
16 #include "base/memory/ref_counted.h" | |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/message_loop/message_loop.h" | |
19 #include "base/metrics/histogram_samples.h" | |
20 #include "base/path_service.h" | |
21 #include "base/prefs/pref_filter.h" | |
22 #include "base/run_loop.h" | |
23 #include "base/single_thread_task_runner.h" | |
24 #include "base/strings/string_number_conversions.h" | |
25 #include "base/strings/string_util.h" | |
26 #include "base/strings/utf_string_conversions.h" | |
27 #include "base/test/histogram_tester.h" | |
28 #include "base/test/simple_test_clock.h" | |
29 #include "base/threading/sequenced_worker_pool.h" | |
30 #include "base/threading/thread.h" | |
31 #include "base/values.h" | |
32 #include "testing/gmock/include/gmock/gmock.h" | |
33 #include "testing/gtest/include/gtest/gtest.h" | |
34 | |
35 namespace base { | |
36 namespace { | |
37 | |
38 const char kHomePage[] = "homepage"; | |
39 | |
40 const char kReadJson[] = | |
41 "{\n" | |
42 " \"homepage\": \"http://www.cnn.com\",\n" | |
43 " \"some_directory\": \"/usr/local/\",\n" | |
44 " \"tabs\": {\n" | |
45 " \"new_windows_in_tabs\": true,\n" | |
46 " \"max_tabs\": 20\n" | |
47 " }\n" | |
48 "}"; | |
49 | |
50 const char kInvalidJson[] = "!@#$%^&"; | |
51 | |
52 // Expected output for tests using RunBasicJsonPrefStoreTest(). | |
53 const char kWriteGolden[] = | |
54 "{\"homepage\":\"http://www.cnn.com\"," | |
55 "\"long_int\":{\"pref\":\"214748364842\"}," | |
56 "\"some_directory\":\"/usr/sbin/\"," | |
57 "\"tabs\":{\"max_tabs\":10,\"new_windows_in_tabs\":false}}"; | |
58 | |
59 // Set the time on the given SimpleTestClock to the given time in minutes. | |
60 void SetCurrentTimeInMinutes(double minutes, base::SimpleTestClock* clock) { | |
61 const int32_t kBaseTimeMins = 100; | |
62 clock->SetNow(base::Time::FromDoubleT((kBaseTimeMins + minutes) * 60)); | |
63 } | |
64 | |
65 // A PrefFilter that will intercept all calls to FilterOnLoad() and hold on | |
66 // to the |prefs| until explicitly asked to release them. | |
67 class InterceptingPrefFilter : public PrefFilter { | |
68 public: | |
69 InterceptingPrefFilter(); | |
70 ~InterceptingPrefFilter() override; | |
71 | |
72 // PrefFilter implementation: | |
73 void FilterOnLoad( | |
74 const PostFilterOnLoadCallback& post_filter_on_load_callback, | |
75 scoped_ptr<base::DictionaryValue> pref_store_contents) override; | |
76 void FilterUpdate(const std::string& path) override {} | |
77 void FilterSerializeData( | |
78 base::DictionaryValue* pref_store_contents) override {} | |
79 | |
80 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; } | |
81 | |
82 // Finalize an intercepted read, handing |intercepted_prefs_| back to its | |
83 // JsonPrefStore. | |
84 void ReleasePrefs(); | |
85 | |
86 private: | |
87 PostFilterOnLoadCallback post_filter_on_load_callback_; | |
88 scoped_ptr<base::DictionaryValue> intercepted_prefs_; | |
89 | |
90 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter); | |
91 }; | |
92 | |
93 InterceptingPrefFilter::InterceptingPrefFilter() {} | |
94 InterceptingPrefFilter::~InterceptingPrefFilter() {} | |
95 | |
96 void InterceptingPrefFilter::FilterOnLoad( | |
97 const PostFilterOnLoadCallback& post_filter_on_load_callback, | |
98 scoped_ptr<base::DictionaryValue> pref_store_contents) { | |
99 post_filter_on_load_callback_ = post_filter_on_load_callback; | |
100 intercepted_prefs_ = std::move(pref_store_contents); | |
101 } | |
102 | |
103 void InterceptingPrefFilter::ReleasePrefs() { | |
104 EXPECT_FALSE(post_filter_on_load_callback_.is_null()); | |
105 post_filter_on_load_callback_.Run(std::move(intercepted_prefs_), false); | |
106 post_filter_on_load_callback_.Reset(); | |
107 } | |
108 | |
109 class MockPrefStoreObserver : public PrefStore::Observer { | |
110 public: | |
111 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&)); | |
112 MOCK_METHOD1(OnInitializationCompleted, void (bool)); | |
113 }; | |
114 | |
115 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate { | |
116 public: | |
117 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError)); | |
118 }; | |
119 | |
120 } // namespace | |
121 | |
122 class JsonPrefStoreTest : public testing::Test { | |
123 protected: | |
124 void SetUp() override { | |
125 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
126 } | |
127 | |
128 void TearDown() override { | |
129 // Make sure all pending tasks have been processed (e.g., deleting the | |
130 // JsonPrefStore may post write tasks). | |
131 RunLoop().RunUntilIdle(); | |
132 } | |
133 | |
134 // The path to temporary directory used to contain the test operations. | |
135 base::ScopedTempDir temp_dir_; | |
136 // A message loop that we can use as the file thread message loop. | |
137 MessageLoop message_loop_; | |
138 }; | |
139 | |
140 // Test fallback behavior for a nonexistent file. | |
141 TEST_F(JsonPrefStoreTest, NonExistentFile) { | |
142 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt"); | |
143 ASSERT_FALSE(PathExists(bogus_input_file)); | |
144 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
145 bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
146 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, | |
147 pref_store->ReadPrefs()); | |
148 EXPECT_FALSE(pref_store->ReadOnly()); | |
149 } | |
150 | |
151 // Test fallback behavior for a nonexistent file and alternate file. | |
152 TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) { | |
153 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt"); | |
154 base::FilePath bogus_alternate_input_file = | |
155 temp_dir_.path().AppendASCII("read_alternate.txt"); | |
156 ASSERT_FALSE(PathExists(bogus_input_file)); | |
157 ASSERT_FALSE(PathExists(bogus_alternate_input_file)); | |
158 scoped_refptr<JsonPrefStore> pref_store = | |
159 new JsonPrefStore(bogus_input_file, bogus_alternate_input_file, | |
160 message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
161 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, | |
162 pref_store->ReadPrefs()); | |
163 EXPECT_FALSE(pref_store->ReadOnly()); | |
164 } | |
165 | |
166 // Test fallback behavior for an invalid file. | |
167 TEST_F(JsonPrefStoreTest, InvalidFile) { | |
168 base::FilePath invalid_file = temp_dir_.path().AppendASCII("invalid.json"); | |
169 ASSERT_LT(0, base::WriteFile(invalid_file, | |
170 kInvalidJson, arraysize(kInvalidJson) - 1)); | |
171 | |
172 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
173 invalid_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
174 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE, | |
175 pref_store->ReadPrefs()); | |
176 EXPECT_FALSE(pref_store->ReadOnly()); | |
177 | |
178 // The file should have been moved aside. | |
179 EXPECT_FALSE(PathExists(invalid_file)); | |
180 base::FilePath moved_aside = temp_dir_.path().AppendASCII("invalid.bad"); | |
181 EXPECT_TRUE(PathExists(moved_aside)); | |
182 | |
183 std::string moved_aside_contents; | |
184 ASSERT_TRUE(base::ReadFileToString(moved_aside, &moved_aside_contents)); | |
185 EXPECT_EQ(kInvalidJson, moved_aside_contents); | |
186 } | |
187 | |
188 // This function is used to avoid code duplication while testing synchronous | |
189 // and asynchronous version of the JsonPrefStore loading. It validates that the | |
190 // given output file's contents matches kWriteGolden. | |
191 void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store, | |
192 const base::FilePath& output_file) { | |
193 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs"; | |
194 const char kMaxTabs[] = "tabs.max_tabs"; | |
195 const char kLongIntPref[] = "long_int.pref"; | |
196 | |
197 std::string cnn("http://www.cnn.com"); | |
198 | |
199 const Value* actual; | |
200 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual)); | |
201 std::string string_value; | |
202 EXPECT_TRUE(actual->GetAsString(&string_value)); | |
203 EXPECT_EQ(cnn, string_value); | |
204 | |
205 const char kSomeDirectory[] = "some_directory"; | |
206 | |
207 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual)); | |
208 base::FilePath::StringType path; | |
209 EXPECT_TRUE(actual->GetAsString(&path)); | |
210 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path); | |
211 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/")); | |
212 | |
213 pref_store->SetValue(kSomeDirectory, | |
214 make_scoped_ptr(new StringValue(some_path.value())), | |
215 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
216 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual)); | |
217 EXPECT_TRUE(actual->GetAsString(&path)); | |
218 EXPECT_EQ(some_path.value(), path); | |
219 | |
220 // Test reading some other data types from sub-dictionaries. | |
221 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual)); | |
222 bool boolean = false; | |
223 EXPECT_TRUE(actual->GetAsBoolean(&boolean)); | |
224 EXPECT_TRUE(boolean); | |
225 | |
226 pref_store->SetValue(kNewWindowsInTabs, | |
227 make_scoped_ptr(new FundamentalValue(false)), | |
228 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
229 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual)); | |
230 EXPECT_TRUE(actual->GetAsBoolean(&boolean)); | |
231 EXPECT_FALSE(boolean); | |
232 | |
233 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual)); | |
234 int integer = 0; | |
235 EXPECT_TRUE(actual->GetAsInteger(&integer)); | |
236 EXPECT_EQ(20, integer); | |
237 pref_store->SetValue(kMaxTabs, make_scoped_ptr(new FundamentalValue(10)), | |
238 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
239 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual)); | |
240 EXPECT_TRUE(actual->GetAsInteger(&integer)); | |
241 EXPECT_EQ(10, integer); | |
242 | |
243 pref_store->SetValue( | |
244 kLongIntPref, | |
245 make_scoped_ptr(new StringValue(base::Int64ToString(214748364842LL))), | |
246 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
247 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual)); | |
248 EXPECT_TRUE(actual->GetAsString(&string_value)); | |
249 int64_t value; | |
250 base::StringToInt64(string_value, &value); | |
251 EXPECT_EQ(214748364842LL, value); | |
252 | |
253 // Serialize and compare to expected output. | |
254 pref_store->CommitPendingWrite(); | |
255 RunLoop().RunUntilIdle(); | |
256 | |
257 std::string output_contents; | |
258 ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents)); | |
259 EXPECT_EQ(kWriteGolden, output_contents); | |
260 ASSERT_TRUE(base::DeleteFile(output_file, false)); | |
261 } | |
262 | |
263 TEST_F(JsonPrefStoreTest, Basic) { | |
264 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
265 ASSERT_LT(0, base::WriteFile(input_file, | |
266 kReadJson, arraysize(kReadJson) - 1)); | |
267 | |
268 // Test that the persistent value can be loaded. | |
269 ASSERT_TRUE(PathExists(input_file)); | |
270 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
271 input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
272 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
273 EXPECT_FALSE(pref_store->ReadOnly()); | |
274 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
275 | |
276 // The JSON file looks like this: | |
277 // { | |
278 // "homepage": "http://www.cnn.com", | |
279 // "some_directory": "/usr/local/", | |
280 // "tabs": { | |
281 // "new_windows_in_tabs": true, | |
282 // "max_tabs": 20 | |
283 // } | |
284 // } | |
285 | |
286 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
287 } | |
288 | |
289 TEST_F(JsonPrefStoreTest, BasicAsync) { | |
290 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
291 ASSERT_LT(0, base::WriteFile(input_file, | |
292 kReadJson, arraysize(kReadJson) - 1)); | |
293 | |
294 // Test that the persistent value can be loaded. | |
295 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
296 input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
297 | |
298 { | |
299 MockPrefStoreObserver mock_observer; | |
300 pref_store->AddObserver(&mock_observer); | |
301 | |
302 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate; | |
303 pref_store->ReadPrefsAsync(mock_error_delegate); | |
304 | |
305 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
306 EXPECT_CALL(*mock_error_delegate, | |
307 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); | |
308 RunLoop().RunUntilIdle(); | |
309 pref_store->RemoveObserver(&mock_observer); | |
310 | |
311 EXPECT_FALSE(pref_store->ReadOnly()); | |
312 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
313 } | |
314 | |
315 // The JSON file looks like this: | |
316 // { | |
317 // "homepage": "http://www.cnn.com", | |
318 // "some_directory": "/usr/local/", | |
319 // "tabs": { | |
320 // "new_windows_in_tabs": true, | |
321 // "max_tabs": 20 | |
322 // } | |
323 // } | |
324 | |
325 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
326 } | |
327 | |
328 TEST_F(JsonPrefStoreTest, PreserveEmptyValues) { | |
329 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json"); | |
330 | |
331 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
332 pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
333 | |
334 // Set some keys with empty values. | |
335 pref_store->SetValue("list", make_scoped_ptr(new base::ListValue), | |
336 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
337 pref_store->SetValue("dict", make_scoped_ptr(new base::DictionaryValue), | |
338 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
339 | |
340 // Write to file. | |
341 pref_store->CommitPendingWrite(); | |
342 RunLoop().RunUntilIdle(); | |
343 | |
344 // Reload. | |
345 pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(), | |
346 scoped_ptr<PrefFilter>()); | |
347 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
348 ASSERT_FALSE(pref_store->ReadOnly()); | |
349 | |
350 // Check values. | |
351 const Value* result = NULL; | |
352 EXPECT_TRUE(pref_store->GetValue("list", &result)); | |
353 EXPECT_TRUE(ListValue().Equals(result)); | |
354 EXPECT_TRUE(pref_store->GetValue("dict", &result)); | |
355 EXPECT_TRUE(DictionaryValue().Equals(result)); | |
356 } | |
357 | |
358 // This test is just documenting some potentially non-obvious behavior. It | |
359 // shouldn't be taken as normative. | |
360 TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) { | |
361 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json"); | |
362 | |
363 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
364 pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
365 | |
366 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); | |
367 dict->SetString("key", "value"); | |
368 pref_store->SetValue("dict", std::move(dict), | |
369 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
370 | |
371 pref_store->RemoveValue("dict.key", | |
372 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
373 | |
374 const base::Value* retrieved_dict = NULL; | |
375 bool has_dict = pref_store->GetValue("dict", &retrieved_dict); | |
376 EXPECT_FALSE(has_dict); | |
377 } | |
378 | |
379 // Tests asynchronous reading of the file when there is no file. | |
380 TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) { | |
381 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt"); | |
382 ASSERT_FALSE(PathExists(bogus_input_file)); | |
383 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( | |
384 bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
385 MockPrefStoreObserver mock_observer; | |
386 pref_store->AddObserver(&mock_observer); | |
387 | |
388 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate; | |
389 pref_store->ReadPrefsAsync(mock_error_delegate); | |
390 | |
391 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
392 EXPECT_CALL(*mock_error_delegate, | |
393 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1); | |
394 RunLoop().RunUntilIdle(); | |
395 pref_store->RemoveObserver(&mock_observer); | |
396 | |
397 EXPECT_FALSE(pref_store->ReadOnly()); | |
398 } | |
399 | |
400 TEST_F(JsonPrefStoreTest, ReadWithInterceptor) { | |
401 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
402 ASSERT_LT(0, base::WriteFile(input_file, | |
403 kReadJson, arraysize(kReadJson) - 1)); | |
404 | |
405 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter( | |
406 new InterceptingPrefFilter()); | |
407 InterceptingPrefFilter* raw_intercepting_pref_filter_ = | |
408 intercepting_pref_filter.get(); | |
409 scoped_refptr<JsonPrefStore> pref_store = | |
410 new JsonPrefStore(input_file, message_loop_.task_runner(), | |
411 std::move(intercepting_pref_filter)); | |
412 | |
413 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE, | |
414 pref_store->ReadPrefs()); | |
415 EXPECT_FALSE(pref_store->ReadOnly()); | |
416 | |
417 // The store shouldn't be considered initialized until the interceptor | |
418 // returns. | |
419 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs()); | |
420 EXPECT_FALSE(pref_store->IsInitializationComplete()); | |
421 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL)); | |
422 | |
423 raw_intercepting_pref_filter_->ReleasePrefs(); | |
424 | |
425 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs()); | |
426 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
427 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL)); | |
428 | |
429 // The JSON file looks like this: | |
430 // { | |
431 // "homepage": "http://www.cnn.com", | |
432 // "some_directory": "/usr/local/", | |
433 // "tabs": { | |
434 // "new_windows_in_tabs": true, | |
435 // "max_tabs": 20 | |
436 // } | |
437 // } | |
438 | |
439 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
440 } | |
441 | |
442 TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) { | |
443 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
444 ASSERT_LT(0, base::WriteFile(input_file, | |
445 kReadJson, arraysize(kReadJson) - 1)); | |
446 | |
447 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter( | |
448 new InterceptingPrefFilter()); | |
449 InterceptingPrefFilter* raw_intercepting_pref_filter_ = | |
450 intercepting_pref_filter.get(); | |
451 scoped_refptr<JsonPrefStore> pref_store = | |
452 new JsonPrefStore(input_file, message_loop_.task_runner(), | |
453 std::move(intercepting_pref_filter)); | |
454 | |
455 MockPrefStoreObserver mock_observer; | |
456 pref_store->AddObserver(&mock_observer); | |
457 | |
458 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below. | |
459 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate; | |
460 | |
461 { | |
462 pref_store->ReadPrefsAsync(mock_error_delegate); | |
463 | |
464 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0); | |
465 // EXPECT_CALL(*mock_error_delegate, | |
466 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); | |
467 RunLoop().RunUntilIdle(); | |
468 | |
469 EXPECT_FALSE(pref_store->ReadOnly()); | |
470 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs()); | |
471 EXPECT_FALSE(pref_store->IsInitializationComplete()); | |
472 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL)); | |
473 } | |
474 | |
475 { | |
476 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
477 // EXPECT_CALL(*mock_error_delegate, | |
478 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); | |
479 | |
480 raw_intercepting_pref_filter_->ReleasePrefs(); | |
481 | |
482 EXPECT_FALSE(pref_store->ReadOnly()); | |
483 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs()); | |
484 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
485 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL)); | |
486 } | |
487 | |
488 pref_store->RemoveObserver(&mock_observer); | |
489 | |
490 // The JSON file looks like this: | |
491 // { | |
492 // "homepage": "http://www.cnn.com", | |
493 // "some_directory": "/usr/local/", | |
494 // "tabs": { | |
495 // "new_windows_in_tabs": true, | |
496 // "max_tabs": 20 | |
497 // } | |
498 // } | |
499 | |
500 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
501 } | |
502 | |
503 TEST_F(JsonPrefStoreTest, AlternateFile) { | |
504 base::FilePath alternate_input_file = | |
505 temp_dir_.path().AppendASCII("alternate.json"); | |
506 ASSERT_LT(0, base::WriteFile(alternate_input_file, | |
507 kReadJson, arraysize(kReadJson) - 1)); | |
508 | |
509 // Test that the alternate file is moved to the main file and read as-is from | |
510 // there. | |
511 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
512 ASSERT_FALSE(PathExists(input_file)); | |
513 ASSERT_TRUE(PathExists(alternate_input_file)); | |
514 scoped_refptr<JsonPrefStore> pref_store = | |
515 new JsonPrefStore(input_file, alternate_input_file, | |
516 message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
517 | |
518 ASSERT_FALSE(PathExists(input_file)); | |
519 ASSERT_TRUE(PathExists(alternate_input_file)); | |
520 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
521 | |
522 ASSERT_TRUE(PathExists(input_file)); | |
523 ASSERT_FALSE(PathExists(alternate_input_file)); | |
524 | |
525 EXPECT_FALSE(pref_store->ReadOnly()); | |
526 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
527 | |
528 // The JSON file looks like this: | |
529 // { | |
530 // "homepage": "http://www.cnn.com", | |
531 // "some_directory": "/usr/local/", | |
532 // "tabs": { | |
533 // "new_windows_in_tabs": true, | |
534 // "max_tabs": 20 | |
535 // } | |
536 // } | |
537 | |
538 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
539 } | |
540 | |
541 TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) { | |
542 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
543 ASSERT_LT(0, base::WriteFile(input_file, | |
544 kReadJson, arraysize(kReadJson) - 1)); | |
545 | |
546 base::FilePath alternate_input_file = | |
547 temp_dir_.path().AppendASCII("alternate.json"); | |
548 ASSERT_LT(0, base::WriteFile(alternate_input_file, | |
549 kInvalidJson, arraysize(kInvalidJson) - 1)); | |
550 | |
551 // Test that the alternate file is ignored and that the read occurs from the | |
552 // existing main file. There is no attempt at even deleting the alternate | |
553 // file as this scenario should never happen in normal user-data-dirs. | |
554 scoped_refptr<JsonPrefStore> pref_store = | |
555 new JsonPrefStore(input_file, alternate_input_file, | |
556 message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
557 | |
558 ASSERT_TRUE(PathExists(input_file)); | |
559 ASSERT_TRUE(PathExists(alternate_input_file)); | |
560 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
561 | |
562 ASSERT_TRUE(PathExists(input_file)); | |
563 ASSERT_TRUE(PathExists(alternate_input_file)); | |
564 | |
565 EXPECT_FALSE(pref_store->ReadOnly()); | |
566 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
567 | |
568 // The JSON file looks like this: | |
569 // { | |
570 // "homepage": "http://www.cnn.com", | |
571 // "some_directory": "/usr/local/", | |
572 // "tabs": { | |
573 // "new_windows_in_tabs": true, | |
574 // "max_tabs": 20 | |
575 // } | |
576 // } | |
577 | |
578 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
579 } | |
580 | |
581 TEST_F(JsonPrefStoreTest, AlternateFileDNE) { | |
582 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
583 ASSERT_LT(0, base::WriteFile(input_file, | |
584 kReadJson, arraysize(kReadJson) - 1)); | |
585 | |
586 // Test that the basic read works fine when an alternate file is specified but | |
587 // does not exist. | |
588 base::FilePath alternate_input_file = | |
589 temp_dir_.path().AppendASCII("alternate.json"); | |
590 ASSERT_TRUE(PathExists(input_file)); | |
591 ASSERT_FALSE(PathExists(alternate_input_file)); | |
592 scoped_refptr<JsonPrefStore> pref_store = | |
593 new JsonPrefStore(input_file, alternate_input_file, | |
594 message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
595 | |
596 ASSERT_TRUE(PathExists(input_file)); | |
597 ASSERT_FALSE(PathExists(alternate_input_file)); | |
598 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); | |
599 | |
600 ASSERT_TRUE(PathExists(input_file)); | |
601 ASSERT_FALSE(PathExists(alternate_input_file)); | |
602 | |
603 EXPECT_FALSE(pref_store->ReadOnly()); | |
604 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
605 | |
606 // The JSON file looks like this: | |
607 // { | |
608 // "homepage": "http://www.cnn.com", | |
609 // "some_directory": "/usr/local/", | |
610 // "tabs": { | |
611 // "new_windows_in_tabs": true, | |
612 // "max_tabs": 20 | |
613 // } | |
614 // } | |
615 | |
616 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
617 } | |
618 | |
619 TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) { | |
620 base::FilePath alternate_input_file = | |
621 temp_dir_.path().AppendASCII("alternate.json"); | |
622 ASSERT_LT(0, base::WriteFile(alternate_input_file, | |
623 kReadJson, arraysize(kReadJson) - 1)); | |
624 | |
625 // Test that the alternate file is moved to the main file and read as-is from | |
626 // there even when the read is made asynchronously. | |
627 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); | |
628 scoped_refptr<JsonPrefStore> pref_store = | |
629 new JsonPrefStore(input_file, alternate_input_file, | |
630 message_loop_.task_runner(), scoped_ptr<PrefFilter>()); | |
631 | |
632 ASSERT_FALSE(PathExists(input_file)); | |
633 ASSERT_TRUE(PathExists(alternate_input_file)); | |
634 | |
635 { | |
636 MockPrefStoreObserver mock_observer; | |
637 pref_store->AddObserver(&mock_observer); | |
638 | |
639 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate; | |
640 pref_store->ReadPrefsAsync(mock_error_delegate); | |
641 | |
642 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); | |
643 EXPECT_CALL(*mock_error_delegate, | |
644 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); | |
645 RunLoop().RunUntilIdle(); | |
646 pref_store->RemoveObserver(&mock_observer); | |
647 | |
648 EXPECT_FALSE(pref_store->ReadOnly()); | |
649 EXPECT_TRUE(pref_store->IsInitializationComplete()); | |
650 } | |
651 | |
652 ASSERT_TRUE(PathExists(input_file)); | |
653 ASSERT_FALSE(PathExists(alternate_input_file)); | |
654 | |
655 // The JSON file looks like this: | |
656 // { | |
657 // "homepage": "http://www.cnn.com", | |
658 // "some_directory": "/usr/local/", | |
659 // "tabs": { | |
660 // "new_windows_in_tabs": true, | |
661 // "max_tabs": 20 | |
662 // } | |
663 // } | |
664 | |
665 RunBasicJsonPrefStoreTest(pref_store.get(), input_file); | |
666 } | |
667 | |
668 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) { | |
669 base::HistogramTester histogram_tester; | |
670 | |
671 SimpleTestClock* test_clock = new SimpleTestClock; | |
672 SetCurrentTimeInMinutes(0, test_clock); | |
673 JsonPrefStore::WriteCountHistogram histogram( | |
674 base::TimeDelta::FromSeconds(10), | |
675 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")), | |
676 scoped_ptr<base::Clock>(test_clock)); | |
677 int32_t report_interval = | |
678 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins; | |
679 | |
680 histogram.RecordWriteOccured(); | |
681 | |
682 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock); | |
683 histogram.ReportOutstandingWrites(); | |
684 scoped_ptr<HistogramSamples> samples = | |
685 histogram.GetHistogram()->SnapshotSamples(); | |
686 | |
687 std::string histogram_name = histogram.GetHistogram()->histogram_name(); | |
688 histogram_tester.ExpectBucketCount(histogram_name, 1, 1); | |
689 histogram_tester.ExpectTotalCount(histogram_name, 1); | |
690 | |
691 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State", | |
692 histogram.GetHistogram()->histogram_name()); | |
693 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31)); | |
694 } | |
695 | |
696 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) { | |
697 base::HistogramTester histogram_tester; | |
698 | |
699 SimpleTestClock* test_clock = new SimpleTestClock; | |
700 SetCurrentTimeInMinutes(0, test_clock); | |
701 JsonPrefStore::WriteCountHistogram histogram( | |
702 base::TimeDelta::FromSeconds(10), | |
703 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")), | |
704 scoped_ptr<base::Clock>(test_clock)); | |
705 int32_t report_interval = | |
706 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins; | |
707 | |
708 histogram.RecordWriteOccured(); | |
709 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock); | |
710 histogram.RecordWriteOccured(); | |
711 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock); | |
712 histogram.RecordWriteOccured(); | |
713 | |
714 // Nothing should be recorded until the report period has elapsed. | |
715 std::string histogram_name = histogram.GetHistogram()->histogram_name(); | |
716 histogram_tester.ExpectTotalCount(histogram_name, 0); | |
717 | |
718 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock); | |
719 histogram.RecordWriteOccured(); | |
720 | |
721 // Now the report period has elapsed. | |
722 histogram_tester.ExpectBucketCount(histogram_name, 3, 1); | |
723 histogram_tester.ExpectTotalCount(histogram_name, 1); | |
724 | |
725 // The last write won't be recorded because the second count period hasn't | |
726 // fully elapsed. | |
727 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock); | |
728 histogram.ReportOutstandingWrites(); | |
729 | |
730 histogram_tester.ExpectBucketCount(histogram_name, 3, 1); | |
731 histogram_tester.ExpectTotalCount(histogram_name, 1); | |
732 } | |
733 | |
734 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) { | |
735 base::HistogramTester histogram_tester; | |
736 | |
737 SimpleTestClock* test_clock = new SimpleTestClock; | |
738 SetCurrentTimeInMinutes(0, test_clock); | |
739 JsonPrefStore::WriteCountHistogram histogram( | |
740 base::TimeDelta::FromSeconds(10), | |
741 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")), | |
742 scoped_ptr<base::Clock>(test_clock)); | |
743 int32_t report_interval = | |
744 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins; | |
745 | |
746 histogram.RecordWriteOccured(); | |
747 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock); | |
748 histogram.RecordWriteOccured(); | |
749 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock); | |
750 histogram.RecordWriteOccured(); | |
751 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock); | |
752 histogram.RecordWriteOccured(); | |
753 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock); | |
754 histogram.RecordWriteOccured(); | |
755 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock); | |
756 histogram.RecordWriteOccured(); | |
757 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock); | |
758 histogram.RecordWriteOccured(); | |
759 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock); | |
760 histogram.RecordWriteOccured(); | |
761 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock); | |
762 histogram.RecordWriteOccured(); | |
763 | |
764 // The last write won't be recorded because the second count period hasn't | |
765 // fully elapsed | |
766 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock); | |
767 histogram.ReportOutstandingWrites(); | |
768 std::string histogram_name = histogram.GetHistogram()->histogram_name(); | |
769 histogram_tester.ExpectBucketCount(histogram_name, 3, 2); | |
770 histogram_tester.ExpectBucketCount(histogram_name, 2, 1); | |
771 histogram_tester.ExpectTotalCount(histogram_name, 3); | |
772 } | |
773 | |
774 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) { | |
775 base::HistogramTester histogram_tester; | |
776 | |
777 SimpleTestClock* test_clock = new SimpleTestClock; | |
778 SetCurrentTimeInMinutes(0, test_clock); | |
779 JsonPrefStore::WriteCountHistogram histogram( | |
780 base::TimeDelta::FromSeconds(10), | |
781 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")), | |
782 scoped_ptr<base::Clock>(test_clock)); | |
783 int32_t report_interval = | |
784 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins; | |
785 | |
786 // 1 write in the first period. | |
787 histogram.RecordWriteOccured(); | |
788 | |
789 // No writes in the second and third periods. | |
790 | |
791 // 2 writes in the fourth period. | |
792 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock); | |
793 histogram.RecordWriteOccured(); | |
794 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock); | |
795 histogram.RecordWriteOccured(); | |
796 | |
797 // No writes in the fifth period. | |
798 | |
799 // 3 writes in the sixth period. | |
800 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock); | |
801 histogram.RecordWriteOccured(); | |
802 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock); | |
803 histogram.RecordWriteOccured(); | |
804 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock); | |
805 histogram.RecordWriteOccured(); | |
806 | |
807 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock); | |
808 histogram.ReportOutstandingWrites(); | |
809 std::string histogram_name = histogram.GetHistogram()->histogram_name(); | |
810 histogram_tester.ExpectBucketCount(histogram_name, 0, 3); | |
811 histogram_tester.ExpectBucketCount(histogram_name, 1, 1); | |
812 histogram_tester.ExpectBucketCount(histogram_name, 2, 1); | |
813 histogram_tester.ExpectBucketCount(histogram_name, 3, 1); | |
814 histogram_tester.ExpectTotalCount(histogram_name, 6); | |
815 } | |
816 | |
817 class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest { | |
818 protected: | |
819 void SetUp() override { | |
820 JsonPrefStoreTest::SetUp(); | |
821 test_file_ = temp_dir_.path().AppendASCII("test.json"); | |
822 } | |
823 | |
824 // Creates a JsonPrefStore with the given |file_writer|. | |
825 scoped_refptr<JsonPrefStore> CreatePrefStore() { | |
826 return new JsonPrefStore(test_file_, message_loop_.task_runner(), | |
827 scoped_ptr<PrefFilter>()); | |
828 } | |
829 | |
830 // Return the ImportantFileWriter for a given JsonPrefStore. | |
831 ImportantFileWriter* GetImportantFileWriter( | |
832 scoped_refptr<JsonPrefStore> pref_store) { | |
833 return &(pref_store->writer_); | |
834 } | |
835 | |
836 // Get the contents of kTestFile. Pumps the message loop before returning the | |
837 // result. | |
838 std::string GetTestFileContents() { | |
839 RunLoop().RunUntilIdle(); | |
840 std::string file_contents; | |
841 ReadFileToString(test_file_, &file_contents); | |
842 return file_contents; | |
843 } | |
844 | |
845 private: | |
846 base::FilePath test_file_; | |
847 }; | |
848 | |
849 TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) { | |
850 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); | |
851 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); | |
852 | |
853 // Set a normal pref and check that it gets scheduled to be written. | |
854 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
855 pref_store->SetValue("normal", | |
856 make_scoped_ptr(new base::StringValue("normal")), | |
857 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
858 ASSERT_TRUE(file_writer->HasPendingWrite()); | |
859 file_writer->DoScheduledWrite(); | |
860 ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents()); | |
861 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
862 | |
863 // Set a lossy pref and check that it is not scheduled to be written. | |
864 // SetValue/RemoveValue. | |
865 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), | |
866 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
867 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
868 pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
869 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
870 | |
871 // SetValueSilently/RemoveValueSilently. | |
872 pref_store->SetValueSilently("lossy", | |
873 make_scoped_ptr(new base::StringValue("lossy")), | |
874 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
875 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
876 pref_store->RemoveValueSilently("lossy", | |
877 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
878 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
879 | |
880 // ReportValueChanged. | |
881 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), | |
882 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
883 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
884 pref_store->ReportValueChanged("lossy", | |
885 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
886 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
887 | |
888 // Call CommitPendingWrite and check that the lossy pref and the normal pref | |
889 // are there with the last values set above. | |
890 pref_store->CommitPendingWrite(); | |
891 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
892 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}", | |
893 GetTestFileContents()); | |
894 } | |
895 | |
896 TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) { | |
897 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); | |
898 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); | |
899 | |
900 // Set a lossy pref and check that it is not scheduled to be written. | |
901 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
902 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), | |
903 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
904 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
905 | |
906 // Set a normal pref and check that it is scheduled to be written. | |
907 pref_store->SetValue("normal", | |
908 make_scoped_ptr(new base::StringValue("normal")), | |
909 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
910 ASSERT_TRUE(file_writer->HasPendingWrite()); | |
911 | |
912 // Call DoScheduledWrite and check both prefs get written. | |
913 file_writer->DoScheduledWrite(); | |
914 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}", | |
915 GetTestFileContents()); | |
916 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
917 } | |
918 | |
919 TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) { | |
920 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); | |
921 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); | |
922 | |
923 // Set a normal pref and check that it is scheduled to be written. | |
924 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
925 pref_store->SetValue("normal", | |
926 make_scoped_ptr(new base::StringValue("normal")), | |
927 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
928 ASSERT_TRUE(file_writer->HasPendingWrite()); | |
929 | |
930 // Set a lossy pref and check that the write is still scheduled. | |
931 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), | |
932 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
933 ASSERT_TRUE(file_writer->HasPendingWrite()); | |
934 | |
935 // Call DoScheduledWrite and check both prefs get written. | |
936 file_writer->DoScheduledWrite(); | |
937 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}", | |
938 GetTestFileContents()); | |
939 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
940 } | |
941 | |
942 TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) { | |
943 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); | |
944 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); | |
945 | |
946 // Set a lossy pref and check that it is not scheduled to be written. | |
947 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")), | |
948 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG); | |
949 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
950 | |
951 // Schedule pending lossy writes and check that it is scheduled. | |
952 pref_store->SchedulePendingLossyWrites(); | |
953 ASSERT_TRUE(file_writer->HasPendingWrite()); | |
954 | |
955 // Call CommitPendingWrite and check that the lossy pref is there with the | |
956 // last value set above. | |
957 pref_store->CommitPendingWrite(); | |
958 ASSERT_FALSE(file_writer->HasPendingWrite()); | |
959 ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents()); | |
960 } | |
961 | |
962 } // namespace base | |
OLD | NEW |