blob: 67a8adbb4d4f93bca61d964ace97353736345f3f [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"
skyostil054861d2015-04-30 19:06:1510#include "base/location.h"
[email protected]3b63f8f42011-03-28 01:54:1511#include "base/memory/ref_counted.h"
12#include "base/memory/scoped_ptr.h"
[email protected]e33c9512014-05-12 02:24:1313#include "base/message_loop/message_loop.h"
raymesbfb910a2015-04-29 07:43:0914#include "base/metrics/histogram_samples.h"
15#include "base/metrics/statistics_recorder.h"
[email protected]277404c22010-04-22 13:09:4516#include "base/path_service.h"
[email protected]56cbcb3a2013-12-23 21:24:4617#include "base/prefs/pref_filter.h"
[email protected]f7b98b32013-02-05 08:14:1518#include "base/run_loop.h"
skyostil054861d2015-04-30 19:06:1519#include "base/single_thread_task_runner.h"
[email protected]dfa049e2013-02-07 02:57:2220#include "base/strings/string_number_conversions.h"
[email protected]d529cb02013-06-10 19:06:5721#include "base/strings/string_util.h"
[email protected]a4ea1f12013-06-07 18:37:0722#include "base/strings/utf_string_conversions.h"
raymesbfb910a2015-04-29 07:43:0923#include "base/test/simple_test_clock.h"
[email protected]0de615a2012-11-08 04:40:5924#include "base/threading/sequenced_worker_pool.h"
[email protected]34b99632011-01-01 01:01:0625#include "base/threading/thread.h"
[email protected]277404c22010-04-22 13:09:4526#include "base/values.h"
[email protected]845b43a82011-05-11 10:14:4327#include "testing/gmock/include/gmock/gmock.h"
[email protected]277404c22010-04-22 13:09:4528#include "testing/gtest/include/gtest/gtest.h"
29
[email protected]7e3ec42c2012-12-16 05:13:2130namespace base {
[email protected]845b43a82011-05-11 10:14:4331namespace {
32
[email protected]5bfdcfd2012-11-22 22:08:2433const char kHomePage[] = "homepage";
34
raymesbfb910a2015-04-29 07:43:0935// Set the time on the given SimpleTestClock to the given time in minutes.
36void SetCurrentTimeInMinutes(double minutes, base::SimpleTestClock* clock) {
37 const int32_t kBaseTimeMins = 100;
38 clock->SetNow(base::Time::FromDoubleT((kBaseTimeMins + minutes) * 60));
39}
40
[email protected]e33c9512014-05-12 02:24:1341// A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
42// to the |prefs| until explicitly asked to release them.
43class InterceptingPrefFilter : public PrefFilter {
44 public:
45 InterceptingPrefFilter();
dcheng56488182014-10-21 10:54:5146 ~InterceptingPrefFilter() override;
[email protected]e33c9512014-05-12 02:24:1347
48 // PrefFilter implementation:
dcheng56488182014-10-21 10:54:5149 void FilterOnLoad(
[email protected]e33c9512014-05-12 02:24:1350 const PostFilterOnLoadCallback& post_filter_on_load_callback,
mostynb9e096de2014-10-07 17:59:1151 scoped_ptr<base::DictionaryValue> pref_store_contents) override;
dcheng56488182014-10-21 10:54:5152 void FilterUpdate(const std::string& path) override {}
53 void FilterSerializeData(
mostynb9e096de2014-10-07 17:59:1154 base::DictionaryValue* pref_store_contents) override {}
[email protected]e33c9512014-05-12 02:24:1355
56 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
57
[email protected]cfcf0e52014-06-20 18:29:4758 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
[email protected]e33c9512014-05-12 02:24:1359 // JsonPrefStore.
60 void ReleasePrefs();
61
62 private:
63 PostFilterOnLoadCallback post_filter_on_load_callback_;
64 scoped_ptr<base::DictionaryValue> intercepted_prefs_;
65
66 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter);
67};
68
69InterceptingPrefFilter::InterceptingPrefFilter() {}
70InterceptingPrefFilter::~InterceptingPrefFilter() {}
71
72void InterceptingPrefFilter::FilterOnLoad(
73 const PostFilterOnLoadCallback& post_filter_on_load_callback,
74 scoped_ptr<base::DictionaryValue> pref_store_contents) {
75 post_filter_on_load_callback_ = post_filter_on_load_callback;
76 intercepted_prefs_ = pref_store_contents.Pass();
77}
78
79void InterceptingPrefFilter::ReleasePrefs() {
80 EXPECT_FALSE(post_filter_on_load_callback_.is_null());
81 post_filter_on_load_callback_.Run(intercepted_prefs_.Pass(), false);
82 post_filter_on_load_callback_.Reset();
83}
84
[email protected]845b43a82011-05-11 10:14:4385class MockPrefStoreObserver : public PrefStore::Observer {
86 public:
87 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
88 MOCK_METHOD1(OnInitializationCompleted, void (bool));
89};
90
91class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
92 public:
93 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
94};
95
96} // namespace
97
[email protected]277404c22010-04-22 13:09:4598class JsonPrefStoreTest : public testing::Test {
99 protected:
dcheng8aef37612014-12-23 02:56:47100 void SetUp() override {
[email protected]3a305db2011-04-12 13:40:53101 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]277404c22010-04-22 13:09:45102
[email protected]fd1d067b2013-04-07 16:27:46103 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_));
[email protected]00c87822012-11-27 19:09:17104 data_dir_ = data_dir_.AppendASCII("prefs");
[email protected]7567484142013-07-11 17:36:07105 ASSERT_TRUE(PathExists(data_dir_));
[email protected]277404c22010-04-22 13:09:45106 }
107
dcheng8aef37612014-12-23 02:56:47108 void TearDown() override {
[email protected]e33c9512014-05-12 02:24:13109 // Make sure all pending tasks have been processed (e.g., deleting the
110 // JsonPrefStore may post write tasks).
raymes4b6e14e2015-05-12 00:10:30111 RunLoop().RunUntilIdle();
[email protected]e33c9512014-05-12 02:24:13112 }
113
[email protected]3a305db2011-04-12 13:40:53114 // The path to temporary directory used to contain the test operations.
[email protected]ea1a3f62012-11-16 20:34:23115 base::ScopedTempDir temp_dir_;
[email protected]3a305db2011-04-12 13:40:53116 // The path to the directory where the test data is stored.
[email protected]023ad6ab2013-02-17 05:07:23117 base::FilePath data_dir_;
[email protected]ea587b02010-05-21 15:01:35118 // A message loop that we can use as the file thread message loop.
119 MessageLoop message_loop_;
raymesbfb910a2015-04-29 07:43:09120
121 private:
122 // Ensure histograms are reset for each test.
123 StatisticsRecorder statistics_recorder_;
[email protected]277404c22010-04-22 13:09:45124};
125
126// Test fallback behavior for a nonexistent file.
127TEST_F(JsonPrefStoreTest, NonExistentFile) {
raymes4b6e14e2015-05-12 00:10:30128 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07129 ASSERT_FALSE(PathExists(bogus_input_file));
[email protected]cadac622013-06-11 16:46:36130 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15131 bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17132 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
[email protected]9a8c4022011-01-25 14:25:33133 pref_store->ReadPrefs());
134 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45135}
136
[email protected]cfcf0e52014-06-20 18:29:47137// Test fallback behavior for a nonexistent file and alternate file.
138TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) {
raymes4b6e14e2015-05-12 00:10:30139 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]cfcf0e52014-06-20 18:29:47140 base::FilePath bogus_alternate_input_file =
raymes4b6e14e2015-05-12 00:10:30141 temp_dir_.path().AppendASCII("read_alternate.txt");
[email protected]cfcf0e52014-06-20 18:29:47142 ASSERT_FALSE(PathExists(bogus_input_file));
143 ASSERT_FALSE(PathExists(bogus_alternate_input_file));
skyostil054861d2015-04-30 19:06:15144 scoped_refptr<JsonPrefStore> pref_store =
145 new JsonPrefStore(bogus_input_file, bogus_alternate_input_file,
146 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47147 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
148 pref_store->ReadPrefs());
149 EXPECT_FALSE(pref_store->ReadOnly());
150}
151
[email protected]277404c22010-04-22 13:09:45152// Test fallback behavior for an invalid file.
153TEST_F(JsonPrefStoreTest, InvalidFile) {
[email protected]023ad6ab2013-02-17 05:07:23154 base::FilePath invalid_file_original = data_dir_.AppendASCII("invalid.json");
155 base::FilePath invalid_file = temp_dir_.path().AppendASCII("invalid.json");
[email protected]f0ff2ad2013-07-09 17:42:26156 ASSERT_TRUE(base::CopyFile(invalid_file_original, invalid_file));
skyostil054861d2015-04-30 19:06:15157 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
158 invalid_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17159 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
[email protected]9a8c4022011-01-25 14:25:33160 pref_store->ReadPrefs());
161 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45162
163 // The file should have been moved aside.
[email protected]7567484142013-07-11 17:36:07164 EXPECT_FALSE(PathExists(invalid_file));
[email protected]023ad6ab2013-02-17 05:07:23165 base::FilePath moved_aside = temp_dir_.path().AppendASCII("invalid.bad");
[email protected]7567484142013-07-11 17:36:07166 EXPECT_TRUE(PathExists(moved_aside));
[email protected]dcd16612013-07-15 20:18:09167 EXPECT_TRUE(TextContentsEqual(invalid_file_original, moved_aside));
[email protected]277404c22010-04-22 13:09:45168}
169
[email protected]845b43a82011-05-11 10:14:43170// This function is used to avoid code duplication while testing synchronous and
171// asynchronous version of the JsonPrefStore loading.
[email protected]0de615a2012-11-08 04:40:59172void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
[email protected]023ad6ab2013-02-17 05:07:23173 const base::FilePath& output_file,
174 const base::FilePath& golden_output_file) {
[email protected]57ecc4b2010-08-11 03:02:51175 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
176 const char kMaxTabs[] = "tabs.max_tabs";
177 const char kLongIntPref[] = "long_int.pref";
[email protected]277404c22010-04-22 13:09:45178
[email protected]57ecc4b2010-08-11 03:02:51179 std::string cnn("http://www.cnn.com");
[email protected]277404c22010-04-22 13:09:45180
[email protected]68bf41a2011-03-25 16:38:31181 const Value* actual;
[email protected]5bfdcfd2012-11-22 22:08:24182 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
[email protected]57ecc4b2010-08-11 03:02:51183 std::string string_value;
[email protected]f2d1f612010-12-09 15:10:17184 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]277404c22010-04-22 13:09:45185 EXPECT_EQ(cnn, string_value);
186
[email protected]57ecc4b2010-08-11 03:02:51187 const char kSomeDirectory[] = "some_directory";
[email protected]277404c22010-04-22 13:09:45188
[email protected]892f1d62012-11-08 18:24:34189 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]023ad6ab2013-02-17 05:07:23190 base::FilePath::StringType path;
[email protected]f2d1f612010-12-09 15:10:17191 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]023ad6ab2013-02-17 05:07:23192 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
193 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
[email protected]f2d1f612010-12-09 15:10:17194
raymes76de1af2015-05-06 03:22:21195 pref_store->SetValue(kSomeDirectory, new StringValue(some_path.value()),
196 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34197 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]f2d1f612010-12-09 15:10:17198 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]277404c22010-04-22 13:09:45199 EXPECT_EQ(some_path.value(), path);
200
201 // Test reading some other data types from sub-dictionaries.
[email protected]892f1d62012-11-08 18:24:34202 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17203 bool boolean = false;
204 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45205 EXPECT_TRUE(boolean);
206
raymes76de1af2015-05-06 03:22:21207 pref_store->SetValue(kNewWindowsInTabs, new FundamentalValue(false),
208 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34209 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17210 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45211 EXPECT_FALSE(boolean);
212
[email protected]892f1d62012-11-08 18:24:34213 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17214 int integer = 0;
215 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45216 EXPECT_EQ(20, integer);
raymes76de1af2015-05-06 03:22:21217 pref_store->SetValue(kMaxTabs, new FundamentalValue(10),
218 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34219 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17220 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45221 EXPECT_EQ(10, integer);
222
[email protected]9a8c4022011-01-25 14:25:33223 pref_store->SetValue(kLongIntPref,
raymes76de1af2015-05-06 03:22:21224 new StringValue(base::Int64ToString(214748364842LL)),
225 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34226 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
[email protected]f2d1f612010-12-09 15:10:17227 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]e83326f2010-07-31 17:29:25228 int64 value;
[email protected]57ecc4b2010-08-11 03:02:51229 base::StringToInt64(string_value, &value);
[email protected]e83326f2010-07-31 17:29:25230 EXPECT_EQ(214748364842LL, value);
[email protected]277404c22010-04-22 13:09:45231
232 // Serialize and compare to expected output.
[email protected]7567484142013-07-11 17:36:07233 ASSERT_TRUE(PathExists(golden_output_file));
[email protected]fbe17c8a2011-12-27 16:41:48234 pref_store->CommitPendingWrite();
[email protected]f7b98b32013-02-05 08:14:15235 RunLoop().RunUntilIdle();
[email protected]dcd16612013-07-15 20:18:09236 EXPECT_TRUE(TextContentsEqual(golden_output_file, output_file));
[email protected]dd3aa792013-07-16 19:10:23237 ASSERT_TRUE(base::DeleteFile(output_file, false));
[email protected]277404c22010-04-22 13:09:45238}
[email protected]845b43a82011-05-11 10:14:43239
240TEST_F(JsonPrefStoreTest, Basic) {
[email protected]f0ff2ad2013-07-09 17:42:26241 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
[email protected]e33c9512014-05-12 02:24:13242 temp_dir_.path().AppendASCII("write.json")));
[email protected]845b43a82011-05-11 10:14:43243
244 // Test that the persistent value can be loaded.
[email protected]023ad6ab2013-02-17 05:07:23245 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
[email protected]7567484142013-07-11 17:36:07246 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46247 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15248 input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43249 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
[email protected]e33c9512014-05-12 02:24:13250 EXPECT_FALSE(pref_store->ReadOnly());
251 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]845b43a82011-05-11 10:14:43252
253 // The JSON file looks like this:
254 // {
255 // "homepage": "http://www.cnn.com",
256 // "some_directory": "/usr/local/",
257 // "tabs": {
258 // "new_windows_in_tabs": true,
259 // "max_tabs": 20
260 // }
261 // }
262
[email protected]3703e922013-05-31 21:37:53263 RunBasicJsonPrefStoreTest(
264 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
[email protected]845b43a82011-05-11 10:14:43265}
266
267TEST_F(JsonPrefStoreTest, BasicAsync) {
[email protected]f0ff2ad2013-07-09 17:42:26268 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
[email protected]e33c9512014-05-12 02:24:13269 temp_dir_.path().AppendASCII("write.json")));
[email protected]845b43a82011-05-11 10:14:43270
271 // Test that the persistent value can be loaded.
[email protected]023ad6ab2013-02-17 05:07:23272 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
[email protected]7567484142013-07-11 17:36:07273 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46274 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15275 input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43276
[email protected]0de615a2012-11-08 04:40:59277 {
278 MockPrefStoreObserver mock_observer;
279 pref_store->AddObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43280
[email protected]0de615a2012-11-08 04:40:59281 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
282 pref_store->ReadPrefsAsync(mock_error_delegate);
[email protected]845b43a82011-05-11 10:14:43283
[email protected]0de615a2012-11-08 04:40:59284 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
285 EXPECT_CALL(*mock_error_delegate,
286 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
[email protected]7ff48ca2013-02-06 16:56:19287 RunLoop().RunUntilIdle();
[email protected]0de615a2012-11-08 04:40:59288 pref_store->RemoveObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43289
[email protected]e33c9512014-05-12 02:24:13290 EXPECT_FALSE(pref_store->ReadOnly());
291 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]0de615a2012-11-08 04:40:59292 }
[email protected]845b43a82011-05-11 10:14:43293
294 // The JSON file looks like this:
295 // {
296 // "homepage": "http://www.cnn.com",
297 // "some_directory": "/usr/local/",
298 // "tabs": {
299 // "new_windows_in_tabs": true,
300 // "max_tabs": 20
301 // }
302 // }
303
[email protected]3703e922013-05-31 21:37:53304 RunBasicJsonPrefStoreTest(
305 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
[email protected]845b43a82011-05-11 10:14:43306}
307
[email protected]aa3283392013-11-27 01:38:24308TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
309 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
310
[email protected]56cbcb3a2013-12-23 21:24:46311 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15312 pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24313
314 // Set some keys with empty values.
raymes76de1af2015-05-06 03:22:21315 pref_store->SetValue("list", new base::ListValue,
316 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
317 pref_store->SetValue("dict", new base::DictionaryValue,
318 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]aa3283392013-11-27 01:38:24319
320 // Write to file.
321 pref_store->CommitPendingWrite();
raymes4b6e14e2015-05-12 00:10:30322 RunLoop().RunUntilIdle();
[email protected]aa3283392013-11-27 01:38:24323
324 // Reload.
skyostil054861d2015-04-30 19:06:15325 pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
326 scoped_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24327 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
328 ASSERT_FALSE(pref_store->ReadOnly());
329
330 // Check values.
331 const Value* result = NULL;
332 EXPECT_TRUE(pref_store->GetValue("list", &result));
333 EXPECT_TRUE(ListValue().Equals(result));
334 EXPECT_TRUE(pref_store->GetValue("dict", &result));
335 EXPECT_TRUE(DictionaryValue().Equals(result));
336}
337
[email protected]eeedaa692014-01-30 09:22:27338// This test is just documenting some potentially non-obvious behavior. It
339// shouldn't be taken as normative.
340TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
341 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
342
343 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15344 pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]eeedaa692014-01-30 09:22:27345
346 base::DictionaryValue* dict = new base::DictionaryValue;
347 dict->SetString("key", "value");
raymes76de1af2015-05-06 03:22:21348 pref_store->SetValue("dict", dict,
349 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27350
raymes76de1af2015-05-06 03:22:21351 pref_store->RemoveValue("dict.key",
352 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27353
354 const base::Value* retrieved_dict = NULL;
355 bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
356 EXPECT_FALSE(has_dict);
357}
358
[email protected]845b43a82011-05-11 10:14:43359// Tests asynchronous reading of the file when there is no file.
360TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
raymes4b6e14e2015-05-12 00:10:30361 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07362 ASSERT_FALSE(PathExists(bogus_input_file));
[email protected]cadac622013-06-11 16:46:36363 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15364 bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43365 MockPrefStoreObserver mock_observer;
366 pref_store->AddObserver(&mock_observer);
367
368 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
369 pref_store->ReadPrefsAsync(mock_error_delegate);
370
371 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
372 EXPECT_CALL(*mock_error_delegate,
373 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
[email protected]7ff48ca2013-02-06 16:56:19374 RunLoop().RunUntilIdle();
[email protected]845b43a82011-05-11 10:14:43375 pref_store->RemoveObserver(&mock_observer);
376
377 EXPECT_FALSE(pref_store->ReadOnly());
378}
[email protected]ea3e4972012-04-12 03:41:37379
[email protected]e33c9512014-05-12 02:24:13380TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
381 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
382 temp_dir_.path().AppendASCII("write.json")));
383
384 // Test that the persistent value can be loaded.
385 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
386 ASSERT_TRUE(PathExists(input_file));
387
388 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter(
389 new InterceptingPrefFilter());
390 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
391 intercepting_pref_filter.get();
skyostil054861d2015-04-30 19:06:15392 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
393 input_file, message_loop_.task_runner(), intercepting_pref_filter.Pass());
[email protected]e33c9512014-05-12 02:24:13394
395 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
396 pref_store->ReadPrefs());
397 EXPECT_FALSE(pref_store->ReadOnly());
398
399 // The store shouldn't be considered initialized until the interceptor
400 // returns.
401 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
402 EXPECT_FALSE(pref_store->IsInitializationComplete());
403 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
404
405 raw_intercepting_pref_filter_->ReleasePrefs();
406
407 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
408 EXPECT_TRUE(pref_store->IsInitializationComplete());
409 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
410
411 // The JSON file looks like this:
412 // {
413 // "homepage": "http://www.cnn.com",
414 // "some_directory": "/usr/local/",
415 // "tabs": {
416 // "new_windows_in_tabs": true,
417 // "max_tabs": 20
418 // }
419 // }
420
421 RunBasicJsonPrefStoreTest(
422 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
423}
424
425TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
426 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
427 temp_dir_.path().AppendASCII("write.json")));
428
429 // Test that the persistent value can be loaded.
430 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
431 ASSERT_TRUE(PathExists(input_file));
432
433 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter(
434 new InterceptingPrefFilter());
435 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
436 intercepting_pref_filter.get();
skyostil054861d2015-04-30 19:06:15437 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
438 input_file, message_loop_.task_runner(), intercepting_pref_filter.Pass());
[email protected]e33c9512014-05-12 02:24:13439
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));
skyostil054861d2015-04-30 19:06:15501 scoped_refptr<JsonPrefStore> pref_store =
502 new JsonPrefStore(input_file, alternate_input_file,
503 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47504
505 ASSERT_FALSE(PathExists(input_file));
506 ASSERT_TRUE(PathExists(alternate_input_file));
507 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
508
509 ASSERT_TRUE(PathExists(input_file));
510 ASSERT_FALSE(PathExists(alternate_input_file));
511
512 EXPECT_FALSE(pref_store->ReadOnly());
513 EXPECT_TRUE(pref_store->IsInitializationComplete());
514
515 // The JSON file looks like this:
516 // {
517 // "homepage": "http://www.cnn.com",
518 // "some_directory": "/usr/local/",
519 // "tabs": {
520 // "new_windows_in_tabs": true,
521 // "max_tabs": 20
522 // }
523 // }
524
525 RunBasicJsonPrefStoreTest(
526 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
527}
528
529TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
530 ASSERT_TRUE(
531 base::CopyFile(data_dir_.AppendASCII("read.json"),
532 temp_dir_.path().AppendASCII("write.json")));
533 ASSERT_TRUE(
534 base::CopyFile(data_dir_.AppendASCII("invalid.json"),
535 temp_dir_.path().AppendASCII("alternate.json")));
536
537 // Test that the alternate file is ignored and that the read occurs from the
538 // existing main file. There is no attempt at even deleting the alternate
539 // file as this scenario should never happen in normal user-data-dirs.
540 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
541 base::FilePath alternate_input_file =
542 temp_dir_.path().AppendASCII("alternate.json");
543 ASSERT_TRUE(PathExists(input_file));
544 ASSERT_TRUE(PathExists(alternate_input_file));
skyostil054861d2015-04-30 19:06:15545 scoped_refptr<JsonPrefStore> pref_store =
546 new JsonPrefStore(input_file, alternate_input_file,
547 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47548
549 ASSERT_TRUE(PathExists(input_file));
550 ASSERT_TRUE(PathExists(alternate_input_file));
551 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
552
553 ASSERT_TRUE(PathExists(input_file));
554 ASSERT_TRUE(PathExists(alternate_input_file));
555
556 EXPECT_FALSE(pref_store->ReadOnly());
557 EXPECT_TRUE(pref_store->IsInitializationComplete());
558
559 // The JSON file looks like this:
560 // {
561 // "homepage": "http://www.cnn.com",
562 // "some_directory": "/usr/local/",
563 // "tabs": {
564 // "new_windows_in_tabs": true,
565 // "max_tabs": 20
566 // }
567 // }
568
569 RunBasicJsonPrefStoreTest(
570 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
571}
572
573TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
574 ASSERT_TRUE(
575 base::CopyFile(data_dir_.AppendASCII("read.json"),
576 temp_dir_.path().AppendASCII("write.json")));
577
578 // Test that the basic read works fine when an alternate file is specified but
579 // does not exist.
580 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
581 base::FilePath alternate_input_file =
582 temp_dir_.path().AppendASCII("alternate.json");
583 ASSERT_TRUE(PathExists(input_file));
584 ASSERT_FALSE(PathExists(alternate_input_file));
skyostil054861d2015-04-30 19:06:15585 scoped_refptr<JsonPrefStore> pref_store =
586 new JsonPrefStore(input_file, alternate_input_file,
587 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47588
589 ASSERT_TRUE(PathExists(input_file));
590 ASSERT_FALSE(PathExists(alternate_input_file));
591 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
592
593 ASSERT_TRUE(PathExists(input_file));
594 ASSERT_FALSE(PathExists(alternate_input_file));
595
596 EXPECT_FALSE(pref_store->ReadOnly());
597 EXPECT_TRUE(pref_store->IsInitializationComplete());
598
599 // The JSON file looks like this:
600 // {
601 // "homepage": "http://www.cnn.com",
602 // "some_directory": "/usr/local/",
603 // "tabs": {
604 // "new_windows_in_tabs": true,
605 // "max_tabs": 20
606 // }
607 // }
608
609 RunBasicJsonPrefStoreTest(
610 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
611}
612
613TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
614 ASSERT_TRUE(
615 base::CopyFile(data_dir_.AppendASCII("read.json"),
616 temp_dir_.path().AppendASCII("alternate.json")));
617
618 // Test that the alternate file is moved to the main file and read as-is from
619 // there even when the read is made asynchronously.
620 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
621 base::FilePath alternate_input_file =
622 temp_dir_.path().AppendASCII("alternate.json");
623 ASSERT_FALSE(PathExists(input_file));
624 ASSERT_TRUE(PathExists(alternate_input_file));
skyostil054861d2015-04-30 19:06:15625 scoped_refptr<JsonPrefStore> pref_store =
626 new JsonPrefStore(input_file, alternate_input_file,
627 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47628
629 ASSERT_FALSE(PathExists(input_file));
630 ASSERT_TRUE(PathExists(alternate_input_file));
631
632 {
633 MockPrefStoreObserver mock_observer;
634 pref_store->AddObserver(&mock_observer);
635
636 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
637 pref_store->ReadPrefsAsync(mock_error_delegate);
638
639 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
640 EXPECT_CALL(*mock_error_delegate,
641 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
642 RunLoop().RunUntilIdle();
643 pref_store->RemoveObserver(&mock_observer);
644
645 EXPECT_FALSE(pref_store->ReadOnly());
646 EXPECT_TRUE(pref_store->IsInitializationComplete());
647 }
648
649 ASSERT_TRUE(PathExists(input_file));
650 ASSERT_FALSE(PathExists(alternate_input_file));
651
652 // The JSON file looks like this:
653 // {
654 // "homepage": "http://www.cnn.com",
655 // "some_directory": "/usr/local/",
656 // "tabs": {
657 // "new_windows_in_tabs": true,
658 // "max_tabs": 20
659 // }
660 // }
661
662 RunBasicJsonPrefStoreTest(
663 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
664}
665
raymesbfb910a2015-04-29 07:43:09666TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
667 SimpleTestClock* test_clock = new SimpleTestClock;
668 SetCurrentTimeInMinutes(0, test_clock);
669 JsonPrefStore::WriteCountHistogram histogram(
670 base::TimeDelta::FromSeconds(10),
671 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
672 scoped_ptr<base::Clock>(test_clock));
673 int32 report_interval =
674 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
675
676 histogram.RecordWriteOccured();
677
678 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
679 histogram.ReportOutstandingWrites();
680 scoped_ptr<HistogramSamples> samples =
681 histogram.GetHistogram()->SnapshotSamples();
682 ASSERT_EQ(1, samples->GetCount(1));
683 ASSERT_EQ(1, samples->TotalCount());
684
685 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State",
686 histogram.GetHistogram()->histogram_name());
687 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31));
688}
689
690TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) {
691 SimpleTestClock* test_clock = new SimpleTestClock;
692 SetCurrentTimeInMinutes(0, test_clock);
693 JsonPrefStore::WriteCountHistogram histogram(
694 base::TimeDelta::FromSeconds(10),
695 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
696 scoped_ptr<base::Clock>(test_clock));
697 int32 report_interval =
698 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
699
700 histogram.RecordWriteOccured();
701 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
702 histogram.RecordWriteOccured();
703 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
704 histogram.RecordWriteOccured();
705
706 // Nothing should be recorded until the report period has elapsed.
707 scoped_ptr<HistogramSamples> samples =
708 histogram.GetHistogram()->SnapshotSamples();
709 ASSERT_EQ(0, samples->TotalCount());
710
711 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
712 histogram.RecordWriteOccured();
713
714 // Now the report period has elapsed.
715 samples = histogram.GetHistogram()->SnapshotSamples();
716 ASSERT_EQ(1, samples->GetCount(3));
717 ASSERT_EQ(1, samples->TotalCount());
718
719 // The last write won't be recorded because the second count period hasn't
720 // fully elapsed.
721 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
722 histogram.ReportOutstandingWrites();
723
724 samples = histogram.GetHistogram()->SnapshotSamples();
725 ASSERT_EQ(1, samples->GetCount(3));
726 ASSERT_EQ(1, samples->TotalCount());
727}
728
729TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) {
730 SimpleTestClock* test_clock = new SimpleTestClock;
731 SetCurrentTimeInMinutes(0, test_clock);
732 JsonPrefStore::WriteCountHistogram histogram(
733 base::TimeDelta::FromSeconds(10),
734 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
735 scoped_ptr<base::Clock>(test_clock));
736 int32 report_interval =
737 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
738
739 histogram.RecordWriteOccured();
740 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
741 histogram.RecordWriteOccured();
742 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
743 histogram.RecordWriteOccured();
744 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
745 histogram.RecordWriteOccured();
746 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
747 histogram.RecordWriteOccured();
748 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock);
749 histogram.RecordWriteOccured();
750 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock);
751 histogram.RecordWriteOccured();
752 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock);
753 histogram.RecordWriteOccured();
754 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
755 histogram.RecordWriteOccured();
756
757 // The last write won't be recorded because the second count period hasn't
758 // fully elapsed
759 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock);
760 histogram.ReportOutstandingWrites();
761 scoped_ptr<HistogramSamples> samples =
762 histogram.GetHistogram()->SnapshotSamples();
763 ASSERT_EQ(2, samples->GetCount(3));
764 ASSERT_EQ(1, samples->GetCount(2));
765 ASSERT_EQ(3, samples->TotalCount());
766}
767
768TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) {
769 SimpleTestClock* test_clock = new SimpleTestClock;
770 SetCurrentTimeInMinutes(0, test_clock);
771 JsonPrefStore::WriteCountHistogram histogram(
772 base::TimeDelta::FromSeconds(10),
773 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
774 scoped_ptr<base::Clock>(test_clock));
775 int32 report_interval =
776 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
777
778 // 1 write in the first period.
779 histogram.RecordWriteOccured();
780
781 // No writes in the second and third periods.
782
783 // 2 writes in the fourth period.
784 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock);
785 histogram.RecordWriteOccured();
786 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
787 histogram.RecordWriteOccured();
788
789 // No writes in the fifth period.
790
791 // 3 writes in the sixth period.
792 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock);
793 histogram.RecordWriteOccured();
794 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock);
795 histogram.RecordWriteOccured();
796 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock);
797 histogram.RecordWriteOccured();
798
799 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock);
800 histogram.ReportOutstandingWrites();
801 scoped_ptr<HistogramSamples> samples =
802 histogram.GetHistogram()->SnapshotSamples();
803 ASSERT_EQ(3, samples->GetCount(0));
804 ASSERT_EQ(1, samples->GetCount(1));
805 ASSERT_EQ(1, samples->GetCount(2));
806 ASSERT_EQ(1, samples->GetCount(3));
807 ASSERT_EQ(6, samples->TotalCount());
808}
809
raymes4b6e14e2015-05-12 00:10:30810class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
811 protected:
812 void SetUp() override {
813 JsonPrefStoreTest::SetUp();
814 test_file_ = temp_dir_.path().AppendASCII("test.json");
815 }
816
817 // Creates a JsonPrefStore with the given |file_writer|.
818 scoped_refptr<JsonPrefStore> CreatePrefStore() {
819 return new JsonPrefStore(test_file_, message_loop_.task_runner(),
820 scoped_ptr<PrefFilter>());
821 }
822
823 // Return the ImportantFileWriter for a given JsonPrefStore.
824 ImportantFileWriter* GetImportantFileWriter(
825 scoped_refptr<JsonPrefStore> pref_store) {
826 return &(pref_store->writer_);
827 }
828
829 // Get the contents of kTestFile. Pumps the message loop before returning the
830 // result.
831 std::string GetTestFileContents() {
832 RunLoop().RunUntilIdle();
833 std::string file_contents;
834 ReadFileToString(test_file_, &file_contents);
835 return file_contents;
836 }
837
838 private:
839 base::FilePath test_file_;
840};
841
842TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) {
843 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
844 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
845
846 // Set a normal pref and check that it gets scheduled to be written.
847 ASSERT_FALSE(file_writer->HasPendingWrite());
848 pref_store->SetValue("normal", new base::StringValue("normal"),
849 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
850 ASSERT_TRUE(file_writer->HasPendingWrite());
851 file_writer->DoScheduledWrite();
852 ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents());
853 ASSERT_FALSE(file_writer->HasPendingWrite());
854
855 // Set a lossy pref and check that it is not scheduled to be written.
856 // SetValue/RemoveValue.
857 pref_store->SetValue("lossy", new base::StringValue("lossy"),
858 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
859 ASSERT_FALSE(file_writer->HasPendingWrite());
860 pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
861 ASSERT_FALSE(file_writer->HasPendingWrite());
862
863 // SetValueSilently/RemoveValueSilently.
864 pref_store->SetValueSilently("lossy", new base::StringValue("lossy"),
865 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
866 ASSERT_FALSE(file_writer->HasPendingWrite());
867 pref_store->RemoveValueSilently("lossy",
868 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
869 ASSERT_FALSE(file_writer->HasPendingWrite());
870
871 // ReportValueChanged.
872 pref_store->SetValue("lossy", new base::StringValue("lossy"),
873 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
874 ASSERT_FALSE(file_writer->HasPendingWrite());
875 pref_store->ReportValueChanged("lossy",
876 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
877 ASSERT_FALSE(file_writer->HasPendingWrite());
878
879 // Call CommitPendingWrite and check that the lossy pref and the normal pref
880 // are there with the last values set above.
881 pref_store->CommitPendingWrite();
882 ASSERT_FALSE(file_writer->HasPendingWrite());
883 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
884 GetTestFileContents());
885}
886
887TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) {
888 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
889 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
890
891 // Set a lossy pref and check that it is not scheduled to be written.
892 ASSERT_FALSE(file_writer->HasPendingWrite());
893 pref_store->SetValue("lossy", new base::StringValue("lossy"),
894 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
895 ASSERT_FALSE(file_writer->HasPendingWrite());
896
897 // Set a normal pref and check that it is scheduled to be written.
898 pref_store->SetValue("normal", new base::StringValue("normal"),
899 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
900 ASSERT_TRUE(file_writer->HasPendingWrite());
901
902 // Call DoScheduledWrite and check both prefs get written.
903 file_writer->DoScheduledWrite();
904 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
905 GetTestFileContents());
906 ASSERT_FALSE(file_writer->HasPendingWrite());
907}
908
909TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) {
910 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
911 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
912
913 // Set a normal pref and check that it is scheduled to be written.
914 ASSERT_FALSE(file_writer->HasPendingWrite());
915 pref_store->SetValue("normal", new base::StringValue("normal"),
916 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
917 ASSERT_TRUE(file_writer->HasPendingWrite());
918
919 // Set a lossy pref and check that the write is still scheduled.
920 pref_store->SetValue("lossy", new base::StringValue("lossy"),
921 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
922 ASSERT_TRUE(file_writer->HasPendingWrite());
923
924 // Call DoScheduledWrite and check both prefs get written.
925 file_writer->DoScheduledWrite();
926 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
927 GetTestFileContents());
928 ASSERT_FALSE(file_writer->HasPendingWrite());
929}
930
[email protected]7e3ec42c2012-12-16 05:13:21931} // namespace base