Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / base / prefs / json_pref_store_unittest.cc
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 "base/bind.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"
24
25 namespace base {
26 namespace {
27
28 const char kHomePage[] = "homepage";
29
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 {
33  public:
34   InterceptingPrefFilter();
35   ~InterceptingPrefFilter() override;
36
37   // PrefFilter implementation:
38   void FilterOnLoad(
39       const PostFilterOnLoadCallback& post_filter_on_load_callback,
40       scoped_ptr<base::DictionaryValue> pref_store_contents) override;
41   void FilterUpdate(const std::string& path) override {}
42   void FilterSerializeData(
43       base::DictionaryValue* pref_store_contents) override {}
44
45   bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
46
47   // Finalize an intercepted read, handing |intercepted_prefs_| back to its
48   // JsonPrefStore.
49   void ReleasePrefs();
50
51  private:
52   PostFilterOnLoadCallback post_filter_on_load_callback_;
53   scoped_ptr<base::DictionaryValue> intercepted_prefs_;
54
55   DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter);
56 };
57
58 InterceptingPrefFilter::InterceptingPrefFilter() {}
59 InterceptingPrefFilter::~InterceptingPrefFilter() {}
60
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();
66 }
67
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();
72 }
73
74 class MockPrefStoreObserver : public PrefStore::Observer {
75  public:
76   MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
77   MOCK_METHOD1(OnInitializationCompleted, void (bool));
78 };
79
80 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
81  public:
82   MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
83 };
84
85 }  // namespace
86
87 class JsonPrefStoreTest : public testing::Test {
88  protected:
89   virtual void SetUp() override {
90     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
91
92     ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_));
93     data_dir_ = data_dir_.AppendASCII("prefs");
94     ASSERT_TRUE(PathExists(data_dir_));
95   }
96
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());
101     message_loop_.Run();
102   }
103
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_;
110 };
111
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(
117       bogus_input_file,
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());
123 }
124
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(
133       bogus_input_file,
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());
140 }
141
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());
154
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));
160 }
161
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";
170
171   std::string cnn("http://www.cnn.com");
172
173   const Value* actual;
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);
178
179   const char kSomeDirectory[] = "some_directory";
180
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/"));
186
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);
191
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);
197
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);
202
203   EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
204   int integer = 0;
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);
211
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));
216   int64 value;
217   base::StringToInt64(string_value, &value);
218   EXPECT_EQ(214748364842LL, value);
219
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));
226 }
227
228 TEST_F(JsonPrefStoreTest, Basic) {
229   ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
230                              temp_dir_.path().AppendASCII("write.json")));
231
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(
236       input_file,
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());
242
243   // The JSON file looks like this:
244   // {
245   //   "homepage": "http://www.cnn.com",
246   //   "some_directory": "/usr/local/",
247   //   "tabs": {
248   //     "new_windows_in_tabs": true,
249   //     "max_tabs": 20
250   //   }
251   // }
252
253   RunBasicJsonPrefStoreTest(
254       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
255 }
256
257 TEST_F(JsonPrefStoreTest, BasicAsync) {
258   ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
259                              temp_dir_.path().AppendASCII("write.json")));
260
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(
265       input_file,
266       message_loop_.message_loop_proxy().get(),
267       scoped_ptr<PrefFilter>());
268
269   {
270     MockPrefStoreObserver mock_observer;
271     pref_store->AddObserver(&mock_observer);
272
273     MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
274     pref_store->ReadPrefsAsync(mock_error_delegate);
275
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);
281
282     EXPECT_FALSE(pref_store->ReadOnly());
283     EXPECT_TRUE(pref_store->IsInitializationComplete());
284   }
285
286   // The JSON file looks like this:
287   // {
288   //   "homepage": "http://www.cnn.com",
289   //   "some_directory": "/usr/local/",
290   //   "tabs": {
291   //     "new_windows_in_tabs": true,
292   //     "max_tabs": 20
293   //   }
294   // }
295
296   RunBasicJsonPrefStoreTest(
297       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
298 }
299
300 TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
301   FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
302
303   scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
304       pref_file,
305       message_loop_.message_loop_proxy(),
306       scoped_ptr<PrefFilter>());
307
308   // Set some keys with empty values.
309   pref_store->SetValue("list", new base::ListValue);
310   pref_store->SetValue("dict", new base::DictionaryValue);
311
312   // Write to file.
313   pref_store->CommitPendingWrite();
314   MessageLoop::current()->RunUntilIdle();
315
316   // Reload.
317   pref_store = new JsonPrefStore(
318       pref_file,
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());
323
324   // Check values.
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));
330 }
331
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");
336
337   scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
338       pref_file,
339       message_loop_.message_loop_proxy(),
340       scoped_ptr<PrefFilter>());
341
342   base::DictionaryValue* dict = new base::DictionaryValue;
343   dict->SetString("key", "value");
344   pref_store->SetValue("dict", dict);
345
346   pref_store->RemoveValue("dict.key");
347
348   const base::Value* retrieved_dict = NULL;
349   bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
350   EXPECT_FALSE(has_dict);
351 }
352
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(
358       bogus_input_file,
359       message_loop_.message_loop_proxy().get(),
360       scoped_ptr<PrefFilter>());
361   MockPrefStoreObserver mock_observer;
362   pref_store->AddObserver(&mock_observer);
363
364   MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
365   pref_store->ReadPrefsAsync(mock_error_delegate);
366
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);
372
373   EXPECT_FALSE(pref_store->ReadOnly());
374 }
375
376 TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
377   ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
378                              temp_dir_.path().AppendASCII("write.json")));
379
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));
383
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.Pass());
392
393   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
394             pref_store->ReadPrefs());
395   EXPECT_FALSE(pref_store->ReadOnly());
396
397   // The store shouldn't be considered initialized until the interceptor
398   // returns.
399   EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
400   EXPECT_FALSE(pref_store->IsInitializationComplete());
401   EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
402
403   raw_intercepting_pref_filter_->ReleasePrefs();
404
405   EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
406   EXPECT_TRUE(pref_store->IsInitializationComplete());
407   EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
408
409   // The JSON file looks like this:
410   // {
411   //   "homepage": "http://www.cnn.com",
412   //   "some_directory": "/usr/local/",
413   //   "tabs": {
414   //     "new_windows_in_tabs": true,
415   //     "max_tabs": 20
416   //   }
417   // }
418
419   RunBasicJsonPrefStoreTest(
420       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
421 }
422
423 TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
424   ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
425                              temp_dir_.path().AppendASCII("write.json")));
426
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));
430
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.Pass());
439
440   MockPrefStoreObserver mock_observer;
441   pref_store->AddObserver(&mock_observer);
442
443   // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
444   MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
445
446   {
447     pref_store->ReadPrefsAsync(mock_error_delegate);
448
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();
453
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));
458   }
459
460   {
461     EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
462     // EXPECT_CALL(*mock_error_delegate,
463     //             OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
464
465     raw_intercepting_pref_filter_->ReleasePrefs();
466
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));
471   }
472
473   pref_store->RemoveObserver(&mock_observer);
474
475   // The JSON file looks like this:
476   // {
477   //   "homepage": "http://www.cnn.com",
478   //   "some_directory": "/usr/local/",
479   //   "tabs": {
480   //     "new_windows_in_tabs": true,
481   //     "max_tabs": 20
482   //   }
483   // }
484
485   RunBasicJsonPrefStoreTest(
486       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
487 }
488
489 TEST_F(JsonPrefStoreTest, AlternateFile) {
490   ASSERT_TRUE(
491       base::CopyFile(data_dir_.AppendASCII("read.json"),
492                      temp_dir_.path().AppendASCII("alternate.json")));
493
494   // Test that the alternate file is moved to the main file and read as-is from
495   // there.
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(
502       input_file,
503       alternate_input_file,
504       message_loop_.message_loop_proxy().get(),
505       scoped_ptr<PrefFilter>());
506
507   ASSERT_FALSE(PathExists(input_file));
508   ASSERT_TRUE(PathExists(alternate_input_file));
509   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
510
511   ASSERT_TRUE(PathExists(input_file));
512   ASSERT_FALSE(PathExists(alternate_input_file));
513
514   EXPECT_FALSE(pref_store->ReadOnly());
515   EXPECT_TRUE(pref_store->IsInitializationComplete());
516
517   // The JSON file looks like this:
518   // {
519   //   "homepage": "http://www.cnn.com",
520   //   "some_directory": "/usr/local/",
521   //   "tabs": {
522   //     "new_windows_in_tabs": true,
523   //     "max_tabs": 20
524   //   }
525   // }
526
527   RunBasicJsonPrefStoreTest(
528       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
529 }
530
531 TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
532   ASSERT_TRUE(
533       base::CopyFile(data_dir_.AppendASCII("read.json"),
534                      temp_dir_.path().AppendASCII("write.json")));
535   ASSERT_TRUE(
536       base::CopyFile(data_dir_.AppendASCII("invalid.json"),
537                      temp_dir_.path().AppendASCII("alternate.json")));
538
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(
548       input_file,
549       alternate_input_file,
550       message_loop_.message_loop_proxy().get(),
551       scoped_ptr<PrefFilter>());
552
553   ASSERT_TRUE(PathExists(input_file));
554   ASSERT_TRUE(PathExists(alternate_input_file));
555   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
556
557   ASSERT_TRUE(PathExists(input_file));
558   ASSERT_TRUE(PathExists(alternate_input_file));
559
560   EXPECT_FALSE(pref_store->ReadOnly());
561   EXPECT_TRUE(pref_store->IsInitializationComplete());
562
563   // The JSON file looks like this:
564   // {
565   //   "homepage": "http://www.cnn.com",
566   //   "some_directory": "/usr/local/",
567   //   "tabs": {
568   //     "new_windows_in_tabs": true,
569   //     "max_tabs": 20
570   //   }
571   // }
572
573   RunBasicJsonPrefStoreTest(
574       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
575 }
576
577 TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
578   ASSERT_TRUE(
579       base::CopyFile(data_dir_.AppendASCII("read.json"),
580                      temp_dir_.path().AppendASCII("write.json")));
581
582   // Test that the basic read works fine when an alternate file is specified but
583   // does not exist.
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(
590       input_file,
591       alternate_input_file,
592       message_loop_.message_loop_proxy().get(),
593       scoped_ptr<PrefFilter>());
594
595   ASSERT_TRUE(PathExists(input_file));
596   ASSERT_FALSE(PathExists(alternate_input_file));
597   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
598
599   ASSERT_TRUE(PathExists(input_file));
600   ASSERT_FALSE(PathExists(alternate_input_file));
601
602   EXPECT_FALSE(pref_store->ReadOnly());
603   EXPECT_TRUE(pref_store->IsInitializationComplete());
604
605   // The JSON file looks like this:
606   // {
607   //   "homepage": "http://www.cnn.com",
608   //   "some_directory": "/usr/local/",
609   //   "tabs": {
610   //     "new_windows_in_tabs": true,
611   //     "max_tabs": 20
612   //   }
613   // }
614
615   RunBasicJsonPrefStoreTest(
616       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
617 }
618
619 TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
620   ASSERT_TRUE(
621       base::CopyFile(data_dir_.AppendASCII("read.json"),
622                      temp_dir_.path().AppendASCII("alternate.json")));
623
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(
632       input_file,
633       alternate_input_file,
634       message_loop_.message_loop_proxy().get(),
635       scoped_ptr<PrefFilter>());
636
637   ASSERT_FALSE(PathExists(input_file));
638   ASSERT_TRUE(PathExists(alternate_input_file));
639
640   {
641     MockPrefStoreObserver mock_observer;
642     pref_store->AddObserver(&mock_observer);
643
644     MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
645     pref_store->ReadPrefsAsync(mock_error_delegate);
646
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);
652
653     EXPECT_FALSE(pref_store->ReadOnly());
654     EXPECT_TRUE(pref_store->IsInitializationComplete());
655   }
656
657   ASSERT_TRUE(PathExists(input_file));
658   ASSERT_FALSE(PathExists(alternate_input_file));
659
660   // The JSON file looks like this:
661   // {
662   //   "homepage": "http://www.cnn.com",
663   //   "some_directory": "/usr/local/",
664   //   "tabs": {
665   //     "new_windows_in_tabs": true,
666   //     "max_tabs": 20
667   //   }
668   // }
669
670   RunBasicJsonPrefStoreTest(
671       pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
672 }
673
674 }  // namespace base