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.
5 #include "base/prefs/json_pref_store.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "base/prefs/pref_filter.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/threading/sequenced_worker_pool.h"
20 #include "base/threading/thread.h"
21 #include "base/values.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
28 const char kHomePage
[] = "homepage";
30 // A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
31 // to the |prefs| until explicitly asked to release them.
32 class InterceptingPrefFilter
: public PrefFilter
{
34 InterceptingPrefFilter();
35 virtual ~InterceptingPrefFilter();
37 // PrefFilter implementation:
38 virtual void FilterOnLoad(
39 const PostFilterOnLoadCallback
& post_filter_on_load_callback
,
40 scoped_ptr
<base::DictionaryValue
> pref_store_contents
) OVERRIDE
;
41 virtual void FilterUpdate(const std::string
& path
) OVERRIDE
{}
42 virtual void FilterSerializeData(
43 base::DictionaryValue
* pref_store_contents
) OVERRIDE
{}
45 bool has_intercepted_prefs() const { return intercepted_prefs_
!= NULL
; }
47 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
52 PostFilterOnLoadCallback post_filter_on_load_callback_
;
53 scoped_ptr
<base::DictionaryValue
> intercepted_prefs_
;
55 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter
);
58 InterceptingPrefFilter::InterceptingPrefFilter() {}
59 InterceptingPrefFilter::~InterceptingPrefFilter() {}
61 void InterceptingPrefFilter::FilterOnLoad(
62 const PostFilterOnLoadCallback
& post_filter_on_load_callback
,
63 scoped_ptr
<base::DictionaryValue
> pref_store_contents
) {
64 post_filter_on_load_callback_
= post_filter_on_load_callback
;
65 intercepted_prefs_
= pref_store_contents
.Pass();
68 void InterceptingPrefFilter::ReleasePrefs() {
69 EXPECT_FALSE(post_filter_on_load_callback_
.is_null());
70 post_filter_on_load_callback_
.Run(intercepted_prefs_
.Pass(), false);
71 post_filter_on_load_callback_
.Reset();
74 class MockPrefStoreObserver
: public PrefStore::Observer
{
76 MOCK_METHOD1(OnPrefValueChanged
, void (const std::string
&));
77 MOCK_METHOD1(OnInitializationCompleted
, void (bool));
80 class MockReadErrorDelegate
: public PersistentPrefStore::ReadErrorDelegate
{
82 MOCK_METHOD1(OnError
, void(PersistentPrefStore::PrefReadError
));
87 class JsonPrefStoreTest
: public testing::Test
{
89 virtual void SetUp() OVERRIDE
{
90 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
92 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA
, &data_dir_
));
93 data_dir_
= data_dir_
.AppendASCII("prefs");
94 ASSERT_TRUE(PathExists(data_dir_
));
97 virtual void TearDown() OVERRIDE
{
98 // Make sure all pending tasks have been processed (e.g., deleting the
99 // JsonPrefStore may post write tasks).
100 message_loop_
.PostTask(FROM_HERE
, MessageLoop::QuitWhenIdleClosure());
104 // The path to temporary directory used to contain the test operations.
105 base::ScopedTempDir temp_dir_
;
106 // The path to the directory where the test data is stored.
107 base::FilePath data_dir_
;
108 // A message loop that we can use as the file thread message loop.
109 MessageLoop message_loop_
;
112 // Test fallback behavior for a nonexistent file.
113 TEST_F(JsonPrefStoreTest
, NonExistentFile
) {
114 base::FilePath bogus_input_file
= data_dir_
.AppendASCII("read.txt");
115 ASSERT_FALSE(PathExists(bogus_input_file
));
116 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
118 message_loop_
.message_loop_proxy().get(),
119 scoped_ptr
<PrefFilter
>());
120 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE
,
121 pref_store
->ReadPrefs());
122 EXPECT_FALSE(pref_store
->ReadOnly());
125 // Test fallback behavior for a nonexistent file and alternate file.
126 TEST_F(JsonPrefStoreTest
, NonExistentFileAndAlternateFile
) {
127 base::FilePath bogus_input_file
= data_dir_
.AppendASCII("read.txt");
128 base::FilePath bogus_alternate_input_file
=
129 data_dir_
.AppendASCII("read_alternate.txt");
130 ASSERT_FALSE(PathExists(bogus_input_file
));
131 ASSERT_FALSE(PathExists(bogus_alternate_input_file
));
132 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
134 bogus_alternate_input_file
,
135 message_loop_
.message_loop_proxy().get(),
136 scoped_ptr
<PrefFilter
>());
137 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE
,
138 pref_store
->ReadPrefs());
139 EXPECT_FALSE(pref_store
->ReadOnly());
142 // Test fallback behavior for an invalid file.
143 TEST_F(JsonPrefStoreTest
, InvalidFile
) {
144 base::FilePath invalid_file_original
= data_dir_
.AppendASCII("invalid.json");
145 base::FilePath invalid_file
= temp_dir_
.path().AppendASCII("invalid.json");
146 ASSERT_TRUE(base::CopyFile(invalid_file_original
, invalid_file
));
147 scoped_refptr
<JsonPrefStore
> pref_store
=
148 new JsonPrefStore(invalid_file
,
149 message_loop_
.message_loop_proxy().get(),
150 scoped_ptr
<PrefFilter
>());
151 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE
,
152 pref_store
->ReadPrefs());
153 EXPECT_FALSE(pref_store
->ReadOnly());
155 // The file should have been moved aside.
156 EXPECT_FALSE(PathExists(invalid_file
));
157 base::FilePath moved_aside
= temp_dir_
.path().AppendASCII("invalid.bad");
158 EXPECT_TRUE(PathExists(moved_aside
));
159 EXPECT_TRUE(TextContentsEqual(invalid_file_original
, moved_aside
));
162 // This function is used to avoid code duplication while testing synchronous and
163 // asynchronous version of the JsonPrefStore loading.
164 void RunBasicJsonPrefStoreTest(JsonPrefStore
* pref_store
,
165 const base::FilePath
& output_file
,
166 const base::FilePath
& golden_output_file
) {
167 const char kNewWindowsInTabs
[] = "tabs.new_windows_in_tabs";
168 const char kMaxTabs
[] = "tabs.max_tabs";
169 const char kLongIntPref
[] = "long_int.pref";
171 std::string
cnn("http://www.cnn.com");
174 EXPECT_TRUE(pref_store
->GetValue(kHomePage
, &actual
));
175 std::string string_value
;
176 EXPECT_TRUE(actual
->GetAsString(&string_value
));
177 EXPECT_EQ(cnn
, string_value
);
179 const char kSomeDirectory
[] = "some_directory";
181 EXPECT_TRUE(pref_store
->GetValue(kSomeDirectory
, &actual
));
182 base::FilePath::StringType path
;
183 EXPECT_TRUE(actual
->GetAsString(&path
));
184 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path
);
185 base::FilePath
some_path(FILE_PATH_LITERAL("/usr/sbin/"));
187 pref_store
->SetValue(kSomeDirectory
, new StringValue(some_path
.value()));
188 EXPECT_TRUE(pref_store
->GetValue(kSomeDirectory
, &actual
));
189 EXPECT_TRUE(actual
->GetAsString(&path
));
190 EXPECT_EQ(some_path
.value(), path
);
192 // Test reading some other data types from sub-dictionaries.
193 EXPECT_TRUE(pref_store
->GetValue(kNewWindowsInTabs
, &actual
));
194 bool boolean
= false;
195 EXPECT_TRUE(actual
->GetAsBoolean(&boolean
));
196 EXPECT_TRUE(boolean
);
198 pref_store
->SetValue(kNewWindowsInTabs
, new FundamentalValue(false));
199 EXPECT_TRUE(pref_store
->GetValue(kNewWindowsInTabs
, &actual
));
200 EXPECT_TRUE(actual
->GetAsBoolean(&boolean
));
201 EXPECT_FALSE(boolean
);
203 EXPECT_TRUE(pref_store
->GetValue(kMaxTabs
, &actual
));
205 EXPECT_TRUE(actual
->GetAsInteger(&integer
));
206 EXPECT_EQ(20, integer
);
207 pref_store
->SetValue(kMaxTabs
, new FundamentalValue(10));
208 EXPECT_TRUE(pref_store
->GetValue(kMaxTabs
, &actual
));
209 EXPECT_TRUE(actual
->GetAsInteger(&integer
));
210 EXPECT_EQ(10, integer
);
212 pref_store
->SetValue(kLongIntPref
,
213 new StringValue(base::Int64ToString(214748364842LL)));
214 EXPECT_TRUE(pref_store
->GetValue(kLongIntPref
, &actual
));
215 EXPECT_TRUE(actual
->GetAsString(&string_value
));
217 base::StringToInt64(string_value
, &value
);
218 EXPECT_EQ(214748364842LL, value
);
220 // Serialize and compare to expected output.
221 ASSERT_TRUE(PathExists(golden_output_file
));
222 pref_store
->CommitPendingWrite();
223 RunLoop().RunUntilIdle();
224 EXPECT_TRUE(TextContentsEqual(golden_output_file
, output_file
));
225 ASSERT_TRUE(base::DeleteFile(output_file
, false));
228 TEST_F(JsonPrefStoreTest
, Basic
) {
229 ASSERT_TRUE(base::CopyFile(data_dir_
.AppendASCII("read.json"),
230 temp_dir_
.path().AppendASCII("write.json")));
232 // Test that the persistent value can be loaded.
233 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
234 ASSERT_TRUE(PathExists(input_file
));
235 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
237 message_loop_
.message_loop_proxy().get(),
238 scoped_ptr
<PrefFilter
>());
239 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE
, pref_store
->ReadPrefs());
240 EXPECT_FALSE(pref_store
->ReadOnly());
241 EXPECT_TRUE(pref_store
->IsInitializationComplete());
243 // The JSON file looks like this:
245 // "homepage": "http://www.cnn.com",
246 // "some_directory": "/usr/local/",
248 // "new_windows_in_tabs": true,
253 RunBasicJsonPrefStoreTest(
254 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
257 TEST_F(JsonPrefStoreTest
, BasicAsync
) {
258 ASSERT_TRUE(base::CopyFile(data_dir_
.AppendASCII("read.json"),
259 temp_dir_
.path().AppendASCII("write.json")));
261 // Test that the persistent value can be loaded.
262 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
263 ASSERT_TRUE(PathExists(input_file
));
264 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
266 message_loop_
.message_loop_proxy().get(),
267 scoped_ptr
<PrefFilter
>());
270 MockPrefStoreObserver mock_observer
;
271 pref_store
->AddObserver(&mock_observer
);
273 MockReadErrorDelegate
* mock_error_delegate
= new MockReadErrorDelegate
;
274 pref_store
->ReadPrefsAsync(mock_error_delegate
);
276 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
277 EXPECT_CALL(*mock_error_delegate
,
278 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE
)).Times(0);
279 RunLoop().RunUntilIdle();
280 pref_store
->RemoveObserver(&mock_observer
);
282 EXPECT_FALSE(pref_store
->ReadOnly());
283 EXPECT_TRUE(pref_store
->IsInitializationComplete());
286 // The JSON file looks like this:
288 // "homepage": "http://www.cnn.com",
289 // "some_directory": "/usr/local/",
291 // "new_windows_in_tabs": true,
296 RunBasicJsonPrefStoreTest(
297 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
300 TEST_F(JsonPrefStoreTest
, PreserveEmptyValues
) {
301 FilePath pref_file
= temp_dir_
.path().AppendASCII("empty_values.json");
303 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
305 message_loop_
.message_loop_proxy(),
306 scoped_ptr
<PrefFilter
>());
308 // Set some keys with empty values.
309 pref_store
->SetValue("list", new base::ListValue
);
310 pref_store
->SetValue("dict", new base::DictionaryValue
);
313 pref_store
->CommitPendingWrite();
314 MessageLoop::current()->RunUntilIdle();
317 pref_store
= new JsonPrefStore(
319 message_loop_
.message_loop_proxy(),
320 scoped_ptr
<PrefFilter
>());
321 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE
, pref_store
->ReadPrefs());
322 ASSERT_FALSE(pref_store
->ReadOnly());
325 const Value
* result
= NULL
;
326 EXPECT_TRUE(pref_store
->GetValue("list", &result
));
327 EXPECT_TRUE(ListValue().Equals(result
));
328 EXPECT_TRUE(pref_store
->GetValue("dict", &result
));
329 EXPECT_TRUE(DictionaryValue().Equals(result
));
332 // This test is just documenting some potentially non-obvious behavior. It
333 // shouldn't be taken as normative.
334 TEST_F(JsonPrefStoreTest
, RemoveClearsEmptyParent
) {
335 FilePath pref_file
= temp_dir_
.path().AppendASCII("empty_values.json");
337 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
339 message_loop_
.message_loop_proxy(),
340 scoped_ptr
<PrefFilter
>());
342 base::DictionaryValue
* dict
= new base::DictionaryValue
;
343 dict
->SetString("key", "value");
344 pref_store
->SetValue("dict", dict
);
346 pref_store
->RemoveValue("dict.key");
348 const base::Value
* retrieved_dict
= NULL
;
349 bool has_dict
= pref_store
->GetValue("dict", &retrieved_dict
);
350 EXPECT_FALSE(has_dict
);
353 // Tests asynchronous reading of the file when there is no file.
354 TEST_F(JsonPrefStoreTest
, AsyncNonExistingFile
) {
355 base::FilePath bogus_input_file
= data_dir_
.AppendASCII("read.txt");
356 ASSERT_FALSE(PathExists(bogus_input_file
));
357 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
359 message_loop_
.message_loop_proxy().get(),
360 scoped_ptr
<PrefFilter
>());
361 MockPrefStoreObserver mock_observer
;
362 pref_store
->AddObserver(&mock_observer
);
364 MockReadErrorDelegate
*mock_error_delegate
= new MockReadErrorDelegate
;
365 pref_store
->ReadPrefsAsync(mock_error_delegate
);
367 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
368 EXPECT_CALL(*mock_error_delegate
,
369 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE
)).Times(1);
370 RunLoop().RunUntilIdle();
371 pref_store
->RemoveObserver(&mock_observer
);
373 EXPECT_FALSE(pref_store
->ReadOnly());
376 TEST_F(JsonPrefStoreTest
, ReadWithInterceptor
) {
377 ASSERT_TRUE(base::CopyFile(data_dir_
.AppendASCII("read.json"),
378 temp_dir_
.path().AppendASCII("write.json")));
380 // Test that the persistent value can be loaded.
381 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
382 ASSERT_TRUE(PathExists(input_file
));
384 scoped_ptr
<InterceptingPrefFilter
> intercepting_pref_filter(
385 new InterceptingPrefFilter());
386 InterceptingPrefFilter
* raw_intercepting_pref_filter_
=
387 intercepting_pref_filter
.get();
388 scoped_refptr
<JsonPrefStore
> pref_store
=
389 new JsonPrefStore(input_file
,
390 message_loop_
.message_loop_proxy().get(),
391 intercepting_pref_filter
.PassAs
<PrefFilter
>());
393 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE
,
394 pref_store
->ReadPrefs());
395 EXPECT_FALSE(pref_store
->ReadOnly());
397 // The store shouldn't be considered initialized until the interceptor
399 EXPECT_TRUE(raw_intercepting_pref_filter_
->has_intercepted_prefs());
400 EXPECT_FALSE(pref_store
->IsInitializationComplete());
401 EXPECT_FALSE(pref_store
->GetValue(kHomePage
, NULL
));
403 raw_intercepting_pref_filter_
->ReleasePrefs();
405 EXPECT_FALSE(raw_intercepting_pref_filter_
->has_intercepted_prefs());
406 EXPECT_TRUE(pref_store
->IsInitializationComplete());
407 EXPECT_TRUE(pref_store
->GetValue(kHomePage
, NULL
));
409 // The JSON file looks like this:
411 // "homepage": "http://www.cnn.com",
412 // "some_directory": "/usr/local/",
414 // "new_windows_in_tabs": true,
419 RunBasicJsonPrefStoreTest(
420 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
423 TEST_F(JsonPrefStoreTest
, ReadAsyncWithInterceptor
) {
424 ASSERT_TRUE(base::CopyFile(data_dir_
.AppendASCII("read.json"),
425 temp_dir_
.path().AppendASCII("write.json")));
427 // Test that the persistent value can be loaded.
428 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
429 ASSERT_TRUE(PathExists(input_file
));
431 scoped_ptr
<InterceptingPrefFilter
> intercepting_pref_filter(
432 new InterceptingPrefFilter());
433 InterceptingPrefFilter
* raw_intercepting_pref_filter_
=
434 intercepting_pref_filter
.get();
435 scoped_refptr
<JsonPrefStore
> pref_store
=
436 new JsonPrefStore(input_file
,
437 message_loop_
.message_loop_proxy().get(),
438 intercepting_pref_filter
.PassAs
<PrefFilter
>());
440 MockPrefStoreObserver mock_observer
;
441 pref_store
->AddObserver(&mock_observer
);
443 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
444 MockReadErrorDelegate
* mock_error_delegate
= new MockReadErrorDelegate
;
447 pref_store
->ReadPrefsAsync(mock_error_delegate
);
449 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(0);
450 // EXPECT_CALL(*mock_error_delegate,
451 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
452 RunLoop().RunUntilIdle();
454 EXPECT_FALSE(pref_store
->ReadOnly());
455 EXPECT_TRUE(raw_intercepting_pref_filter_
->has_intercepted_prefs());
456 EXPECT_FALSE(pref_store
->IsInitializationComplete());
457 EXPECT_FALSE(pref_store
->GetValue(kHomePage
, NULL
));
461 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
462 // EXPECT_CALL(*mock_error_delegate,
463 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
465 raw_intercepting_pref_filter_
->ReleasePrefs();
467 EXPECT_FALSE(pref_store
->ReadOnly());
468 EXPECT_FALSE(raw_intercepting_pref_filter_
->has_intercepted_prefs());
469 EXPECT_TRUE(pref_store
->IsInitializationComplete());
470 EXPECT_TRUE(pref_store
->GetValue(kHomePage
, NULL
));
473 pref_store
->RemoveObserver(&mock_observer
);
475 // The JSON file looks like this:
477 // "homepage": "http://www.cnn.com",
478 // "some_directory": "/usr/local/",
480 // "new_windows_in_tabs": true,
485 RunBasicJsonPrefStoreTest(
486 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
489 TEST_F(JsonPrefStoreTest
, AlternateFile
) {
491 base::CopyFile(data_dir_
.AppendASCII("read.json"),
492 temp_dir_
.path().AppendASCII("alternate.json")));
494 // Test that the alternate file is moved to the main file and read as-is from
496 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
497 base::FilePath alternate_input_file
=
498 temp_dir_
.path().AppendASCII("alternate.json");
499 ASSERT_FALSE(PathExists(input_file
));
500 ASSERT_TRUE(PathExists(alternate_input_file
));
501 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
503 alternate_input_file
,
504 message_loop_
.message_loop_proxy().get(),
505 scoped_ptr
<PrefFilter
>());
507 ASSERT_FALSE(PathExists(input_file
));
508 ASSERT_TRUE(PathExists(alternate_input_file
));
509 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE
, pref_store
->ReadPrefs());
511 ASSERT_TRUE(PathExists(input_file
));
512 ASSERT_FALSE(PathExists(alternate_input_file
));
514 EXPECT_FALSE(pref_store
->ReadOnly());
515 EXPECT_TRUE(pref_store
->IsInitializationComplete());
517 // The JSON file looks like this:
519 // "homepage": "http://www.cnn.com",
520 // "some_directory": "/usr/local/",
522 // "new_windows_in_tabs": true,
527 RunBasicJsonPrefStoreTest(
528 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
531 TEST_F(JsonPrefStoreTest
, AlternateFileIgnoredWhenMainFileExists
) {
533 base::CopyFile(data_dir_
.AppendASCII("read.json"),
534 temp_dir_
.path().AppendASCII("write.json")));
536 base::CopyFile(data_dir_
.AppendASCII("invalid.json"),
537 temp_dir_
.path().AppendASCII("alternate.json")));
539 // Test that the alternate file is ignored and that the read occurs from the
540 // existing main file. There is no attempt at even deleting the alternate
541 // file as this scenario should never happen in normal user-data-dirs.
542 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
543 base::FilePath alternate_input_file
=
544 temp_dir_
.path().AppendASCII("alternate.json");
545 ASSERT_TRUE(PathExists(input_file
));
546 ASSERT_TRUE(PathExists(alternate_input_file
));
547 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
549 alternate_input_file
,
550 message_loop_
.message_loop_proxy().get(),
551 scoped_ptr
<PrefFilter
>());
553 ASSERT_TRUE(PathExists(input_file
));
554 ASSERT_TRUE(PathExists(alternate_input_file
));
555 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE
, pref_store
->ReadPrefs());
557 ASSERT_TRUE(PathExists(input_file
));
558 ASSERT_TRUE(PathExists(alternate_input_file
));
560 EXPECT_FALSE(pref_store
->ReadOnly());
561 EXPECT_TRUE(pref_store
->IsInitializationComplete());
563 // The JSON file looks like this:
565 // "homepage": "http://www.cnn.com",
566 // "some_directory": "/usr/local/",
568 // "new_windows_in_tabs": true,
573 RunBasicJsonPrefStoreTest(
574 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
577 TEST_F(JsonPrefStoreTest
, AlternateFileDNE
) {
579 base::CopyFile(data_dir_
.AppendASCII("read.json"),
580 temp_dir_
.path().AppendASCII("write.json")));
582 // Test that the basic read works fine when an alternate file is specified but
584 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
585 base::FilePath alternate_input_file
=
586 temp_dir_
.path().AppendASCII("alternate.json");
587 ASSERT_TRUE(PathExists(input_file
));
588 ASSERT_FALSE(PathExists(alternate_input_file
));
589 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
591 alternate_input_file
,
592 message_loop_
.message_loop_proxy().get(),
593 scoped_ptr
<PrefFilter
>());
595 ASSERT_TRUE(PathExists(input_file
));
596 ASSERT_FALSE(PathExists(alternate_input_file
));
597 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE
, pref_store
->ReadPrefs());
599 ASSERT_TRUE(PathExists(input_file
));
600 ASSERT_FALSE(PathExists(alternate_input_file
));
602 EXPECT_FALSE(pref_store
->ReadOnly());
603 EXPECT_TRUE(pref_store
->IsInitializationComplete());
605 // The JSON file looks like this:
607 // "homepage": "http://www.cnn.com",
608 // "some_directory": "/usr/local/",
610 // "new_windows_in_tabs": true,
615 RunBasicJsonPrefStoreTest(
616 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));
619 TEST_F(JsonPrefStoreTest
, BasicAsyncWithAlternateFile
) {
621 base::CopyFile(data_dir_
.AppendASCII("read.json"),
622 temp_dir_
.path().AppendASCII("alternate.json")));
624 // Test that the alternate file is moved to the main file and read as-is from
625 // there even when the read is made asynchronously.
626 base::FilePath input_file
= temp_dir_
.path().AppendASCII("write.json");
627 base::FilePath alternate_input_file
=
628 temp_dir_
.path().AppendASCII("alternate.json");
629 ASSERT_FALSE(PathExists(input_file
));
630 ASSERT_TRUE(PathExists(alternate_input_file
));
631 scoped_refptr
<JsonPrefStore
> pref_store
= new JsonPrefStore(
633 alternate_input_file
,
634 message_loop_
.message_loop_proxy().get(),
635 scoped_ptr
<PrefFilter
>());
637 ASSERT_FALSE(PathExists(input_file
));
638 ASSERT_TRUE(PathExists(alternate_input_file
));
641 MockPrefStoreObserver mock_observer
;
642 pref_store
->AddObserver(&mock_observer
);
644 MockReadErrorDelegate
* mock_error_delegate
= new MockReadErrorDelegate
;
645 pref_store
->ReadPrefsAsync(mock_error_delegate
);
647 EXPECT_CALL(mock_observer
, OnInitializationCompleted(true)).Times(1);
648 EXPECT_CALL(*mock_error_delegate
,
649 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE
)).Times(0);
650 RunLoop().RunUntilIdle();
651 pref_store
->RemoveObserver(&mock_observer
);
653 EXPECT_FALSE(pref_store
->ReadOnly());
654 EXPECT_TRUE(pref_store
->IsInitializationComplete());
657 ASSERT_TRUE(PathExists(input_file
));
658 ASSERT_FALSE(PathExists(alternate_input_file
));
660 // The JSON file looks like this:
662 // "homepage": "http://www.cnn.com",
663 // "some_directory": "/usr/local/",
665 // "new_windows_in_tabs": true,
670 RunBasicJsonPrefStoreTest(
671 pref_store
.get(), input_file
, data_dir_
.AppendASCII("write.golden.json"));