blob: d09d9d3926cacec756812d414513ce4639cbcd03 [file] [log] [blame]
[email protected]ea3e4972012-04-12 03:41:371// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]277404c22010-04-22 13:09:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]00c87822012-11-27 19:09:175#include "base/prefs/json_pref_store.h"
6
[email protected]e33c9512014-05-12 02:24:137#include "base/bind.h"
[email protected]e3177dd52014-08-13 20:22:148#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:239#include "base/files/scoped_temp_dir.h"
[email protected]3b63f8f42011-03-28 01:54:1510#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
[email protected]e33c9512014-05-12 02:24:1312#include "base/message_loop/message_loop.h"
[email protected]277404c22010-04-22 13:09:4513#include "base/path_service.h"
[email protected]56cbcb3a2013-12-23 21:24:4614#include "base/prefs/pref_filter.h"
[email protected]f7b98b32013-02-05 08:14:1515#include "base/run_loop.h"
[email protected]dfa049e2013-02-07 02:57:2216#include "base/strings/string_number_conversions.h"
[email protected]d529cb02013-06-10 19:06:5717#include "base/strings/string_util.h"
[email protected]a4ea1f12013-06-07 18:37:0718#include "base/strings/utf_string_conversions.h"
[email protected]0de615a2012-11-08 04:40:5919#include "base/threading/sequenced_worker_pool.h"
[email protected]34b99632011-01-01 01:01:0620#include "base/threading/thread.h"
[email protected]277404c22010-04-22 13:09:4521#include "base/values.h"
[email protected]845b43a82011-05-11 10:14:4322#include "testing/gmock/include/gmock/gmock.h"
[email protected]277404c22010-04-22 13:09:4523#include "testing/gtest/include/gtest/gtest.h"
24
[email protected]7e3ec42c2012-12-16 05:13:2125namespace base {
[email protected]845b43a82011-05-11 10:14:4326namespace {
27
[email protected]5bfdcfd2012-11-22 22:08:2428const char kHomePage[] = "homepage";
29
[email protected]e33c9512014-05-12 02:24:1330// A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
31// to the |prefs| until explicitly asked to release them.
32class InterceptingPrefFilter : public PrefFilter {
33 public:
34 InterceptingPrefFilter();
35 virtual ~InterceptingPrefFilter();
36
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(
[email protected]1b5837662014-06-18 20:45:2143 base::DictionaryValue* pref_store_contents) OVERRIDE {}
[email protected]e33c9512014-05-12 02:24:1344
45 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
46
[email protected]cfcf0e52014-06-20 18:29:4747 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
[email protected]e33c9512014-05-12 02:24:1348 // 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
58InterceptingPrefFilter::InterceptingPrefFilter() {}
59InterceptingPrefFilter::~InterceptingPrefFilter() {}
60
61void 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
68void 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
[email protected]845b43a82011-05-11 10:14:4374class MockPrefStoreObserver : public PrefStore::Observer {
75 public:
76 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
77 MOCK_METHOD1(OnInitializationCompleted, void (bool));
78};
79
80class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
81 public:
82 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
83};
84
85} // namespace
86
[email protected]277404c22010-04-22 13:09:4587class JsonPrefStoreTest : public testing::Test {
88 protected:
[email protected]0de615a2012-11-08 04:40:5989 virtual void SetUp() OVERRIDE {
[email protected]3a305db2011-04-12 13:40:5390 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]277404c22010-04-22 13:09:4591
[email protected]fd1d067b2013-04-07 16:27:4692 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_));
[email protected]00c87822012-11-27 19:09:1793 data_dir_ = data_dir_.AppendASCII("prefs");
[email protected]7567484142013-07-11 17:36:0794 ASSERT_TRUE(PathExists(data_dir_));
[email protected]277404c22010-04-22 13:09:4595 }
96
[email protected]e33c9512014-05-12 02:24:1397 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
[email protected]3a305db2011-04-12 13:40:53104 // The path to temporary directory used to contain the test operations.
[email protected]ea1a3f62012-11-16 20:34:23105 base::ScopedTempDir temp_dir_;
[email protected]3a305db2011-04-12 13:40:53106 // The path to the directory where the test data is stored.
[email protected]023ad6ab2013-02-17 05:07:23107 base::FilePath data_dir_;
[email protected]ea587b02010-05-21 15:01:35108 // A message loop that we can use as the file thread message loop.
109 MessageLoop message_loop_;
[email protected]277404c22010-04-22 13:09:45110};
111
112// Test fallback behavior for a nonexistent file.
113TEST_F(JsonPrefStoreTest, NonExistentFile) {
[email protected]023ad6ab2013-02-17 05:07:23114 base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07115 ASSERT_FALSE(PathExists(bogus_input_file));
[email protected]cadac622013-06-11 16:46:36116 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
[email protected]56cbcb3a2013-12-23 21:24:46117 bogus_input_file,
118 message_loop_.message_loop_proxy().get(),
119 scoped_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17120 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
[email protected]9a8c4022011-01-25 14:25:33121 pref_store->ReadPrefs());
122 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45123}
124
[email protected]cfcf0e52014-06-20 18:29:47125// Test fallback behavior for a nonexistent file and alternate file.
126TEST_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
[email protected]277404c22010-04-22 13:09:45142// Test fallback behavior for an invalid file.
143TEST_F(JsonPrefStoreTest, InvalidFile) {
[email protected]023ad6ab2013-02-17 05:07:23144 base::FilePath invalid_file_original = data_dir_.AppendASCII("invalid.json");
145 base::FilePath invalid_file = temp_dir_.path().AppendASCII("invalid.json");
[email protected]f0ff2ad2013-07-09 17:42:26146 ASSERT_TRUE(base::CopyFile(invalid_file_original, invalid_file));
[email protected]9a8c4022011-01-25 14:25:33147 scoped_refptr<JsonPrefStore> pref_store =
[email protected]56cbcb3a2013-12-23 21:24:46148 new JsonPrefStore(invalid_file,
149 message_loop_.message_loop_proxy().get(),
150 scoped_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17151 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
[email protected]9a8c4022011-01-25 14:25:33152 pref_store->ReadPrefs());
153 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45154
155 // The file should have been moved aside.
[email protected]7567484142013-07-11 17:36:07156 EXPECT_FALSE(PathExists(invalid_file));
[email protected]023ad6ab2013-02-17 05:07:23157 base::FilePath moved_aside = temp_dir_.path().AppendASCII("invalid.bad");
[email protected]7567484142013-07-11 17:36:07158 EXPECT_TRUE(PathExists(moved_aside));
[email protected]dcd16612013-07-15 20:18:09159 EXPECT_TRUE(TextContentsEqual(invalid_file_original, moved_aside));
[email protected]277404c22010-04-22 13:09:45160}
161
[email protected]845b43a82011-05-11 10:14:43162// This function is used to avoid code duplication while testing synchronous and
163// asynchronous version of the JsonPrefStore loading.
[email protected]0de615a2012-11-08 04:40:59164void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
[email protected]023ad6ab2013-02-17 05:07:23165 const base::FilePath& output_file,
166 const base::FilePath& golden_output_file) {
[email protected]57ecc4b2010-08-11 03:02:51167 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
168 const char kMaxTabs[] = "tabs.max_tabs";
169 const char kLongIntPref[] = "long_int.pref";
[email protected]277404c22010-04-22 13:09:45170
[email protected]57ecc4b2010-08-11 03:02:51171 std::string cnn("http://www.cnn.com");
[email protected]277404c22010-04-22 13:09:45172
[email protected]68bf41a2011-03-25 16:38:31173 const Value* actual;
[email protected]5bfdcfd2012-11-22 22:08:24174 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
[email protected]57ecc4b2010-08-11 03:02:51175 std::string string_value;
[email protected]f2d1f612010-12-09 15:10:17176 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]277404c22010-04-22 13:09:45177 EXPECT_EQ(cnn, string_value);
178
[email protected]57ecc4b2010-08-11 03:02:51179 const char kSomeDirectory[] = "some_directory";
[email protected]277404c22010-04-22 13:09:45180
[email protected]892f1d62012-11-08 18:24:34181 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]023ad6ab2013-02-17 05:07:23182 base::FilePath::StringType path;
[email protected]f2d1f612010-12-09 15:10:17183 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]023ad6ab2013-02-17 05:07:23184 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
185 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
[email protected]f2d1f612010-12-09 15:10:17186
[email protected]7e3ec42c2012-12-16 05:13:21187 pref_store->SetValue(kSomeDirectory, new StringValue(some_path.value()));
[email protected]892f1d62012-11-08 18:24:34188 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]f2d1f612010-12-09 15:10:17189 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]277404c22010-04-22 13:09:45190 EXPECT_EQ(some_path.value(), path);
191
192 // Test reading some other data types from sub-dictionaries.
[email protected]892f1d62012-11-08 18:24:34193 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17194 bool boolean = false;
195 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45196 EXPECT_TRUE(boolean);
197
[email protected]7e3ec42c2012-12-16 05:13:21198 pref_store->SetValue(kNewWindowsInTabs, new FundamentalValue(false));
[email protected]892f1d62012-11-08 18:24:34199 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17200 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45201 EXPECT_FALSE(boolean);
202
[email protected]892f1d62012-11-08 18:24:34203 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17204 int integer = 0;
205 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45206 EXPECT_EQ(20, integer);
[email protected]7e3ec42c2012-12-16 05:13:21207 pref_store->SetValue(kMaxTabs, new FundamentalValue(10));
[email protected]892f1d62012-11-08 18:24:34208 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17209 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45210 EXPECT_EQ(10, integer);
211
[email protected]9a8c4022011-01-25 14:25:33212 pref_store->SetValue(kLongIntPref,
[email protected]7e3ec42c2012-12-16 05:13:21213 new StringValue(base::Int64ToString(214748364842LL)));
[email protected]892f1d62012-11-08 18:24:34214 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
[email protected]f2d1f612010-12-09 15:10:17215 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]e83326f2010-07-31 17:29:25216 int64 value;
[email protected]57ecc4b2010-08-11 03:02:51217 base::StringToInt64(string_value, &value);
[email protected]e83326f2010-07-31 17:29:25218 EXPECT_EQ(214748364842LL, value);
[email protected]277404c22010-04-22 13:09:45219
220 // Serialize and compare to expected output.
[email protected]7567484142013-07-11 17:36:07221 ASSERT_TRUE(PathExists(golden_output_file));
[email protected]fbe17c8a2011-12-27 16:41:48222 pref_store->CommitPendingWrite();
[email protected]f7b98b32013-02-05 08:14:15223 RunLoop().RunUntilIdle();
[email protected]dcd16612013-07-15 20:18:09224 EXPECT_TRUE(TextContentsEqual(golden_output_file, output_file));
[email protected]dd3aa792013-07-16 19:10:23225 ASSERT_TRUE(base::DeleteFile(output_file, false));
[email protected]277404c22010-04-22 13:09:45226}
[email protected]845b43a82011-05-11 10:14:43227
228TEST_F(JsonPrefStoreTest, Basic) {
[email protected]f0ff2ad2013-07-09 17:42:26229 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
[email protected]e33c9512014-05-12 02:24:13230 temp_dir_.path().AppendASCII("write.json")));
[email protected]845b43a82011-05-11 10:14:43231
232 // Test that the persistent value can be loaded.
[email protected]023ad6ab2013-02-17 05:07:23233 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
[email protected]7567484142013-07-11 17:36:07234 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46235 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
236 input_file,
237 message_loop_.message_loop_proxy().get(),
238 scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43239 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
[email protected]e33c9512014-05-12 02:24:13240 EXPECT_FALSE(pref_store->ReadOnly());
241 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]845b43a82011-05-11 10:14:43242
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
[email protected]3703e922013-05-31 21:37:53253 RunBasicJsonPrefStoreTest(
254 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
[email protected]845b43a82011-05-11 10:14:43255}
256
257TEST_F(JsonPrefStoreTest, BasicAsync) {
[email protected]f0ff2ad2013-07-09 17:42:26258 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
[email protected]e33c9512014-05-12 02:24:13259 temp_dir_.path().AppendASCII("write.json")));
[email protected]845b43a82011-05-11 10:14:43260
261 // Test that the persistent value can be loaded.
[email protected]023ad6ab2013-02-17 05:07:23262 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
[email protected]7567484142013-07-11 17:36:07263 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46264 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
265 input_file,
266 message_loop_.message_loop_proxy().get(),
267 scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43268
[email protected]0de615a2012-11-08 04:40:59269 {
270 MockPrefStoreObserver mock_observer;
271 pref_store->AddObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43272
[email protected]0de615a2012-11-08 04:40:59273 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
274 pref_store->ReadPrefsAsync(mock_error_delegate);
[email protected]845b43a82011-05-11 10:14:43275
[email protected]0de615a2012-11-08 04:40:59276 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
277 EXPECT_CALL(*mock_error_delegate,
278 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
[email protected]7ff48ca2013-02-06 16:56:19279 RunLoop().RunUntilIdle();
[email protected]0de615a2012-11-08 04:40:59280 pref_store->RemoveObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43281
[email protected]e33c9512014-05-12 02:24:13282 EXPECT_FALSE(pref_store->ReadOnly());
283 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]0de615a2012-11-08 04:40:59284 }
[email protected]845b43a82011-05-11 10:14:43285
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
[email protected]3703e922013-05-31 21:37:53296 RunBasicJsonPrefStoreTest(
297 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
[email protected]845b43a82011-05-11 10:14:43298}
299
[email protected]aa3283392013-11-27 01:38:24300TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
301 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
302
[email protected]56cbcb3a2013-12-23 21:24:46303 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
304 pref_file,
305 message_loop_.message_loop_proxy(),
306 scoped_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24307
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.
[email protected]56cbcb3a2013-12-23 21:24:46317 pref_store = new JsonPrefStore(
318 pref_file,
319 message_loop_.message_loop_proxy(),
320 scoped_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24321 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
[email protected]eeedaa692014-01-30 09:22:27332// This test is just documenting some potentially non-obvious behavior. It
333// shouldn't be taken as normative.
334TEST_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
[email protected]845b43a82011-05-11 10:14:43353// Tests asynchronous reading of the file when there is no file.
354TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
[email protected]023ad6ab2013-02-17 05:07:23355 base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07356 ASSERT_FALSE(PathExists(bogus_input_file));
[email protected]cadac622013-06-11 16:46:36357 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
[email protected]56cbcb3a2013-12-23 21:24:46358 bogus_input_file,
359 message_loop_.message_loop_proxy().get(),
360 scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43361 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);
[email protected]7ff48ca2013-02-06 16:56:19370 RunLoop().RunUntilIdle();
[email protected]845b43a82011-05-11 10:14:43371 pref_store->RemoveObserver(&mock_observer);
372
373 EXPECT_FALSE(pref_store->ReadOnly());
374}
[email protected]ea3e4972012-04-12 03:41:37375
[email protected]e33c9512014-05-12 02:24:13376TEST_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.PassAs<PrefFilter>());
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
423TEST_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.PassAs<PrefFilter>());
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
[email protected]cfcf0e52014-06-20 18:29:47489TEST_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
531TEST_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
577TEST_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
619TEST_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
[email protected]7e3ec42c2012-12-16 05:13:21674} // namespace base