blob: bc9eecaace09bb337d1d700733ec63fe2f30248a [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
avi9ef8bb02015-12-24 05:29:367#include <stdint.h>
8
danakj0c8d4aa2015-11-25 05:29:589#include <utility>
10
[email protected]e33c9512014-05-12 02:24:1311#include "base/bind.h"
[email protected]e3177dd52014-08-13 20:22:1412#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2313#include "base/files/scoped_temp_dir.h"
skyostil054861d2015-04-30 19:06:1514#include "base/location.h"
avi9ef8bb02015-12-24 05:29:3615#include "base/macros.h"
[email protected]3b63f8f42011-03-28 01:54:1516#include "base/memory/ref_counted.h"
17#include "base/memory/scoped_ptr.h"
[email protected]e33c9512014-05-12 02:24:1318#include "base/message_loop/message_loop.h"
raymesbfb910a2015-04-29 07:43:0919#include "base/metrics/histogram_samples.h"
[email protected]277404c22010-04-22 13:09:4520#include "base/path_service.h"
[email protected]56cbcb3a2013-12-23 21:24:4621#include "base/prefs/pref_filter.h"
[email protected]f7b98b32013-02-05 08:14:1522#include "base/run_loop.h"
skyostil054861d2015-04-30 19:06:1523#include "base/single_thread_task_runner.h"
[email protected]dfa049e2013-02-07 02:57:2224#include "base/strings/string_number_conversions.h"
[email protected]d529cb02013-06-10 19:06:5725#include "base/strings/string_util.h"
[email protected]a4ea1f12013-06-07 18:37:0726#include "base/strings/utf_string_conversions.h"
brettw58cd1f12016-01-30 05:56:0527#include "base/test/histogram_tester.h"
raymesbfb910a2015-04-29 07:43:0928#include "base/test/simple_test_clock.h"
[email protected]0de615a2012-11-08 04:40:5929#include "base/threading/sequenced_worker_pool.h"
[email protected]34b99632011-01-01 01:01:0630#include "base/threading/thread.h"
[email protected]277404c22010-04-22 13:09:4531#include "base/values.h"
[email protected]845b43a82011-05-11 10:14:4332#include "testing/gmock/include/gmock/gmock.h"
[email protected]277404c22010-04-22 13:09:4533#include "testing/gtest/include/gtest/gtest.h"
34
[email protected]7e3ec42c2012-12-16 05:13:2135namespace base {
[email protected]845b43a82011-05-11 10:14:4336namespace {
37
[email protected]5bfdcfd2012-11-22 22:08:2438const char kHomePage[] = "homepage";
39
brettw58cd1f12016-01-30 05:56:0540const char kReadJson[] =
41 "{\n"
42 " \"homepage\": \"http://www.cnn.com\",\n"
43 " \"some_directory\": \"/usr/local/\",\n"
44 " \"tabs\": {\n"
45 " \"new_windows_in_tabs\": true,\n"
46 " \"max_tabs\": 20\n"
47 " }\n"
48 "}";
49
50const char kInvalidJson[] = "!@#$%^&";
51
52// Expected output for tests using RunBasicJsonPrefStoreTest().
53const char kWriteGolden[] =
54 "{\"homepage\":\"http://www.cnn.com\","
55 "\"long_int\":{\"pref\":\"214748364842\"},"
56 "\"some_directory\":\"/usr/sbin/\","
57 "\"tabs\":{\"max_tabs\":10,\"new_windows_in_tabs\":false}}";
58
raymesbfb910a2015-04-29 07:43:0959// Set the time on the given SimpleTestClock to the given time in minutes.
60void SetCurrentTimeInMinutes(double minutes, base::SimpleTestClock* clock) {
61 const int32_t kBaseTimeMins = 100;
62 clock->SetNow(base::Time::FromDoubleT((kBaseTimeMins + minutes) * 60));
63}
64
[email protected]e33c9512014-05-12 02:24:1365// A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
66// to the |prefs| until explicitly asked to release them.
67class InterceptingPrefFilter : public PrefFilter {
68 public:
69 InterceptingPrefFilter();
dcheng56488182014-10-21 10:54:5170 ~InterceptingPrefFilter() override;
[email protected]e33c9512014-05-12 02:24:1371
72 // PrefFilter implementation:
dcheng56488182014-10-21 10:54:5173 void FilterOnLoad(
[email protected]e33c9512014-05-12 02:24:1374 const PostFilterOnLoadCallback& post_filter_on_load_callback,
mostynb9e096de2014-10-07 17:59:1175 scoped_ptr<base::DictionaryValue> pref_store_contents) override;
dcheng56488182014-10-21 10:54:5176 void FilterUpdate(const std::string& path) override {}
77 void FilterSerializeData(
mostynb9e096de2014-10-07 17:59:1178 base::DictionaryValue* pref_store_contents) override {}
[email protected]e33c9512014-05-12 02:24:1379
80 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
81
[email protected]cfcf0e52014-06-20 18:29:4782 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
[email protected]e33c9512014-05-12 02:24:1383 // JsonPrefStore.
84 void ReleasePrefs();
85
86 private:
87 PostFilterOnLoadCallback post_filter_on_load_callback_;
88 scoped_ptr<base::DictionaryValue> intercepted_prefs_;
89
90 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter);
91};
92
93InterceptingPrefFilter::InterceptingPrefFilter() {}
94InterceptingPrefFilter::~InterceptingPrefFilter() {}
95
96void InterceptingPrefFilter::FilterOnLoad(
97 const PostFilterOnLoadCallback& post_filter_on_load_callback,
98 scoped_ptr<base::DictionaryValue> pref_store_contents) {
99 post_filter_on_load_callback_ = post_filter_on_load_callback;
danakj0c8d4aa2015-11-25 05:29:58100 intercepted_prefs_ = std::move(pref_store_contents);
[email protected]e33c9512014-05-12 02:24:13101}
102
103void InterceptingPrefFilter::ReleasePrefs() {
104 EXPECT_FALSE(post_filter_on_load_callback_.is_null());
danakj0c8d4aa2015-11-25 05:29:58105 post_filter_on_load_callback_.Run(std::move(intercepted_prefs_), false);
[email protected]e33c9512014-05-12 02:24:13106 post_filter_on_load_callback_.Reset();
107}
108
[email protected]845b43a82011-05-11 10:14:43109class MockPrefStoreObserver : public PrefStore::Observer {
110 public:
111 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
112 MOCK_METHOD1(OnInitializationCompleted, void (bool));
113};
114
115class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
116 public:
117 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
118};
119
120} // namespace
121
[email protected]277404c22010-04-22 13:09:45122class JsonPrefStoreTest : public testing::Test {
123 protected:
dcheng8aef37612014-12-23 02:56:47124 void SetUp() override {
[email protected]3a305db2011-04-12 13:40:53125 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]277404c22010-04-22 13:09:45126 }
127
dcheng8aef37612014-12-23 02:56:47128 void TearDown() override {
[email protected]e33c9512014-05-12 02:24:13129 // Make sure all pending tasks have been processed (e.g., deleting the
130 // JsonPrefStore may post write tasks).
raymes4b6e14e2015-05-12 00:10:30131 RunLoop().RunUntilIdle();
[email protected]e33c9512014-05-12 02:24:13132 }
133
[email protected]3a305db2011-04-12 13:40:53134 // The path to temporary directory used to contain the test operations.
[email protected]ea1a3f62012-11-16 20:34:23135 base::ScopedTempDir temp_dir_;
[email protected]ea587b02010-05-21 15:01:35136 // A message loop that we can use as the file thread message loop.
137 MessageLoop message_loop_;
[email protected]277404c22010-04-22 13:09:45138};
139
140// Test fallback behavior for a nonexistent file.
141TEST_F(JsonPrefStoreTest, NonExistentFile) {
raymes4b6e14e2015-05-12 00:10:30142 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07143 ASSERT_FALSE(PathExists(bogus_input_file));
[email protected]cadac622013-06-11 16:46:36144 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15145 bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17146 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
[email protected]9a8c4022011-01-25 14:25:33147 pref_store->ReadPrefs());
148 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45149}
150
[email protected]cfcf0e52014-06-20 18:29:47151// Test fallback behavior for a nonexistent file and alternate file.
152TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) {
raymes4b6e14e2015-05-12 00:10:30153 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]cfcf0e52014-06-20 18:29:47154 base::FilePath bogus_alternate_input_file =
raymes4b6e14e2015-05-12 00:10:30155 temp_dir_.path().AppendASCII("read_alternate.txt");
[email protected]cfcf0e52014-06-20 18:29:47156 ASSERT_FALSE(PathExists(bogus_input_file));
157 ASSERT_FALSE(PathExists(bogus_alternate_input_file));
skyostil054861d2015-04-30 19:06:15158 scoped_refptr<JsonPrefStore> pref_store =
159 new JsonPrefStore(bogus_input_file, bogus_alternate_input_file,
160 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47161 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
162 pref_store->ReadPrefs());
163 EXPECT_FALSE(pref_store->ReadOnly());
164}
165
[email protected]277404c22010-04-22 13:09:45166// Test fallback behavior for an invalid file.
167TEST_F(JsonPrefStoreTest, InvalidFile) {
[email protected]023ad6ab2013-02-17 05:07:23168 base::FilePath invalid_file = temp_dir_.path().AppendASCII("invalid.json");
brettw58cd1f12016-01-30 05:56:05169 ASSERT_LT(0, base::WriteFile(invalid_file,
170 kInvalidJson, arraysize(kInvalidJson) - 1));
171
skyostil054861d2015-04-30 19:06:15172 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
173 invalid_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17174 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
[email protected]9a8c4022011-01-25 14:25:33175 pref_store->ReadPrefs());
176 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45177
178 // The file should have been moved aside.
[email protected]7567484142013-07-11 17:36:07179 EXPECT_FALSE(PathExists(invalid_file));
[email protected]023ad6ab2013-02-17 05:07:23180 base::FilePath moved_aside = temp_dir_.path().AppendASCII("invalid.bad");
[email protected]7567484142013-07-11 17:36:07181 EXPECT_TRUE(PathExists(moved_aside));
brettw58cd1f12016-01-30 05:56:05182
183 std::string moved_aside_contents;
184 ASSERT_TRUE(base::ReadFileToString(moved_aside, &moved_aside_contents));
185 EXPECT_EQ(kInvalidJson, moved_aside_contents);
[email protected]277404c22010-04-22 13:09:45186}
187
brettw58cd1f12016-01-30 05:56:05188// This function is used to avoid code duplication while testing synchronous
189// and asynchronous version of the JsonPrefStore loading. It validates that the
190// given output file's contents matches kWriteGolden.
[email protected]0de615a2012-11-08 04:40:59191void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
brettw58cd1f12016-01-30 05:56:05192 const base::FilePath& output_file) {
[email protected]57ecc4b2010-08-11 03:02:51193 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
194 const char kMaxTabs[] = "tabs.max_tabs";
195 const char kLongIntPref[] = "long_int.pref";
[email protected]277404c22010-04-22 13:09:45196
[email protected]57ecc4b2010-08-11 03:02:51197 std::string cnn("http://www.cnn.com");
[email protected]277404c22010-04-22 13:09:45198
[email protected]68bf41a2011-03-25 16:38:31199 const Value* actual;
[email protected]5bfdcfd2012-11-22 22:08:24200 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
[email protected]57ecc4b2010-08-11 03:02:51201 std::string string_value;
[email protected]f2d1f612010-12-09 15:10:17202 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]277404c22010-04-22 13:09:45203 EXPECT_EQ(cnn, string_value);
204
[email protected]57ecc4b2010-08-11 03:02:51205 const char kSomeDirectory[] = "some_directory";
[email protected]277404c22010-04-22 13:09:45206
[email protected]892f1d62012-11-08 18:24:34207 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]023ad6ab2013-02-17 05:07:23208 base::FilePath::StringType path;
[email protected]f2d1f612010-12-09 15:10:17209 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]023ad6ab2013-02-17 05:07:23210 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
211 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
[email protected]f2d1f612010-12-09 15:10:17212
estade0bd407f2015-06-26 18:16:18213 pref_store->SetValue(kSomeDirectory,
214 make_scoped_ptr(new StringValue(some_path.value())),
raymes76de1af2015-05-06 03:22:21215 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34216 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]f2d1f612010-12-09 15:10:17217 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]277404c22010-04-22 13:09:45218 EXPECT_EQ(some_path.value(), path);
219
220 // Test reading some other data types from sub-dictionaries.
[email protected]892f1d62012-11-08 18:24:34221 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17222 bool boolean = false;
223 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45224 EXPECT_TRUE(boolean);
225
estade0bd407f2015-06-26 18:16:18226 pref_store->SetValue(kNewWindowsInTabs,
227 make_scoped_ptr(new FundamentalValue(false)),
raymes76de1af2015-05-06 03:22:21228 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34229 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17230 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45231 EXPECT_FALSE(boolean);
232
[email protected]892f1d62012-11-08 18:24:34233 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17234 int integer = 0;
235 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45236 EXPECT_EQ(20, integer);
estade0bd407f2015-06-26 18:16:18237 pref_store->SetValue(kMaxTabs, make_scoped_ptr(new FundamentalValue(10)),
raymes76de1af2015-05-06 03:22:21238 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34239 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17240 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45241 EXPECT_EQ(10, integer);
242
estade0bd407f2015-06-26 18:16:18243 pref_store->SetValue(
244 kLongIntPref,
245 make_scoped_ptr(new StringValue(base::Int64ToString(214748364842LL))),
246 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34247 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
[email protected]f2d1f612010-12-09 15:10:17248 EXPECT_TRUE(actual->GetAsString(&string_value));
avi9ef8bb02015-12-24 05:29:36249 int64_t value;
[email protected]57ecc4b2010-08-11 03:02:51250 base::StringToInt64(string_value, &value);
[email protected]e83326f2010-07-31 17:29:25251 EXPECT_EQ(214748364842LL, value);
[email protected]277404c22010-04-22 13:09:45252
253 // Serialize and compare to expected output.
[email protected]fbe17c8a2011-12-27 16:41:48254 pref_store->CommitPendingWrite();
[email protected]f7b98b32013-02-05 08:14:15255 RunLoop().RunUntilIdle();
brettw58cd1f12016-01-30 05:56:05256
257 std::string output_contents;
258 ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents));
259 EXPECT_EQ(kWriteGolden, output_contents);
[email protected]dd3aa792013-07-16 19:10:23260 ASSERT_TRUE(base::DeleteFile(output_file, false));
[email protected]277404c22010-04-22 13:09:45261}
[email protected]845b43a82011-05-11 10:14:43262
263TEST_F(JsonPrefStoreTest, Basic) {
brettw58cd1f12016-01-30 05:56:05264 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
265 ASSERT_LT(0, base::WriteFile(input_file,
266 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43267
268 // Test that the persistent value can be loaded.
[email protected]7567484142013-07-11 17:36:07269 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46270 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15271 input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43272 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
[email protected]e33c9512014-05-12 02:24:13273 EXPECT_FALSE(pref_store->ReadOnly());
274 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]845b43a82011-05-11 10:14:43275
276 // The JSON file looks like this:
277 // {
278 // "homepage": "http://www.cnn.com",
279 // "some_directory": "/usr/local/",
280 // "tabs": {
281 // "new_windows_in_tabs": true,
282 // "max_tabs": 20
283 // }
284 // }
285
brettw58cd1f12016-01-30 05:56:05286 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43287}
288
289TEST_F(JsonPrefStoreTest, BasicAsync) {
brettw58cd1f12016-01-30 05:56:05290 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
291 ASSERT_LT(0, base::WriteFile(input_file,
292 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43293
294 // Test that the persistent value can be loaded.
[email protected]56cbcb3a2013-12-23 21:24:46295 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15296 input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43297
[email protected]0de615a2012-11-08 04:40:59298 {
299 MockPrefStoreObserver mock_observer;
300 pref_store->AddObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43301
[email protected]0de615a2012-11-08 04:40:59302 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
303 pref_store->ReadPrefsAsync(mock_error_delegate);
[email protected]845b43a82011-05-11 10:14:43304
[email protected]0de615a2012-11-08 04:40:59305 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
306 EXPECT_CALL(*mock_error_delegate,
307 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
[email protected]7ff48ca2013-02-06 16:56:19308 RunLoop().RunUntilIdle();
[email protected]0de615a2012-11-08 04:40:59309 pref_store->RemoveObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43310
[email protected]e33c9512014-05-12 02:24:13311 EXPECT_FALSE(pref_store->ReadOnly());
312 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]0de615a2012-11-08 04:40:59313 }
[email protected]845b43a82011-05-11 10:14:43314
315 // The JSON file looks like this:
316 // {
317 // "homepage": "http://www.cnn.com",
318 // "some_directory": "/usr/local/",
319 // "tabs": {
320 // "new_windows_in_tabs": true,
321 // "max_tabs": 20
322 // }
323 // }
324
brettw58cd1f12016-01-30 05:56:05325 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43326}
327
[email protected]aa3283392013-11-27 01:38:24328TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
329 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
330
[email protected]56cbcb3a2013-12-23 21:24:46331 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15332 pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24333
334 // Set some keys with empty values.
estade0bd407f2015-06-26 18:16:18335 pref_store->SetValue("list", make_scoped_ptr(new base::ListValue),
raymes76de1af2015-05-06 03:22:21336 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
estade0bd407f2015-06-26 18:16:18337 pref_store->SetValue("dict", make_scoped_ptr(new base::DictionaryValue),
raymes76de1af2015-05-06 03:22:21338 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]aa3283392013-11-27 01:38:24339
340 // Write to file.
341 pref_store->CommitPendingWrite();
raymes4b6e14e2015-05-12 00:10:30342 RunLoop().RunUntilIdle();
[email protected]aa3283392013-11-27 01:38:24343
344 // Reload.
skyostil054861d2015-04-30 19:06:15345 pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
346 scoped_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24347 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
348 ASSERT_FALSE(pref_store->ReadOnly());
349
350 // Check values.
351 const Value* result = NULL;
352 EXPECT_TRUE(pref_store->GetValue("list", &result));
353 EXPECT_TRUE(ListValue().Equals(result));
354 EXPECT_TRUE(pref_store->GetValue("dict", &result));
355 EXPECT_TRUE(DictionaryValue().Equals(result));
356}
357
[email protected]eeedaa692014-01-30 09:22:27358// This test is just documenting some potentially non-obvious behavior. It
359// shouldn't be taken as normative.
360TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
361 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
362
363 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15364 pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]eeedaa692014-01-30 09:22:27365
estade0bd407f2015-06-26 18:16:18366 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
[email protected]eeedaa692014-01-30 09:22:27367 dict->SetString("key", "value");
danakj0c8d4aa2015-11-25 05:29:58368 pref_store->SetValue("dict", std::move(dict),
raymes76de1af2015-05-06 03:22:21369 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27370
raymes76de1af2015-05-06 03:22:21371 pref_store->RemoveValue("dict.key",
372 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27373
374 const base::Value* retrieved_dict = NULL;
375 bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
376 EXPECT_FALSE(has_dict);
377}
378
[email protected]845b43a82011-05-11 10:14:43379// Tests asynchronous reading of the file when there is no file.
380TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
raymes4b6e14e2015-05-12 00:10:30381 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07382 ASSERT_FALSE(PathExists(bogus_input_file));
[email protected]cadac622013-06-11 16:46:36383 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
skyostil054861d2015-04-30 19:06:15384 bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43385 MockPrefStoreObserver mock_observer;
386 pref_store->AddObserver(&mock_observer);
387
388 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
389 pref_store->ReadPrefsAsync(mock_error_delegate);
390
391 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
392 EXPECT_CALL(*mock_error_delegate,
393 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
[email protected]7ff48ca2013-02-06 16:56:19394 RunLoop().RunUntilIdle();
[email protected]845b43a82011-05-11 10:14:43395 pref_store->RemoveObserver(&mock_observer);
396
397 EXPECT_FALSE(pref_store->ReadOnly());
398}
[email protected]ea3e4972012-04-12 03:41:37399
[email protected]e33c9512014-05-12 02:24:13400TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
[email protected]e33c9512014-05-12 02:24:13401 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05402 ASSERT_LT(0, base::WriteFile(input_file,
403 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13404
405 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter(
406 new InterceptingPrefFilter());
407 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
408 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58409 scoped_refptr<JsonPrefStore> pref_store =
410 new JsonPrefStore(input_file, message_loop_.task_runner(),
411 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13412
413 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
414 pref_store->ReadPrefs());
415 EXPECT_FALSE(pref_store->ReadOnly());
416
417 // The store shouldn't be considered initialized until the interceptor
418 // returns.
419 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
420 EXPECT_FALSE(pref_store->IsInitializationComplete());
421 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
422
423 raw_intercepting_pref_filter_->ReleasePrefs();
424
425 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
426 EXPECT_TRUE(pref_store->IsInitializationComplete());
427 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
428
429 // The JSON file looks like this:
430 // {
431 // "homepage": "http://www.cnn.com",
432 // "some_directory": "/usr/local/",
433 // "tabs": {
434 // "new_windows_in_tabs": true,
435 // "max_tabs": 20
436 // }
437 // }
438
brettw58cd1f12016-01-30 05:56:05439 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13440}
441
442TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
[email protected]e33c9512014-05-12 02:24:13443 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05444 ASSERT_LT(0, base::WriteFile(input_file,
445 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13446
447 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter(
448 new InterceptingPrefFilter());
449 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
450 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58451 scoped_refptr<JsonPrefStore> pref_store =
452 new JsonPrefStore(input_file, message_loop_.task_runner(),
453 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13454
455 MockPrefStoreObserver mock_observer;
456 pref_store->AddObserver(&mock_observer);
457
458 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
459 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
460
461 {
462 pref_store->ReadPrefsAsync(mock_error_delegate);
463
464 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
465 // EXPECT_CALL(*mock_error_delegate,
466 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
467 RunLoop().RunUntilIdle();
468
469 EXPECT_FALSE(pref_store->ReadOnly());
470 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
471 EXPECT_FALSE(pref_store->IsInitializationComplete());
472 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
473 }
474
475 {
476 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
477 // EXPECT_CALL(*mock_error_delegate,
478 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
479
480 raw_intercepting_pref_filter_->ReleasePrefs();
481
482 EXPECT_FALSE(pref_store->ReadOnly());
483 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
484 EXPECT_TRUE(pref_store->IsInitializationComplete());
485 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
486 }
487
488 pref_store->RemoveObserver(&mock_observer);
489
490 // The JSON file looks like this:
491 // {
492 // "homepage": "http://www.cnn.com",
493 // "some_directory": "/usr/local/",
494 // "tabs": {
495 // "new_windows_in_tabs": true,
496 // "max_tabs": 20
497 // }
498 // }
499
brettw58cd1f12016-01-30 05:56:05500 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13501}
502
[email protected]cfcf0e52014-06-20 18:29:47503TEST_F(JsonPrefStoreTest, AlternateFile) {
brettw58cd1f12016-01-30 05:56:05504 base::FilePath alternate_input_file =
505 temp_dir_.path().AppendASCII("alternate.json");
506 ASSERT_LT(0, base::WriteFile(alternate_input_file,
507 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47508
509 // Test that the alternate file is moved to the main file and read as-is from
510 // there.
511 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
[email protected]cfcf0e52014-06-20 18:29:47512 ASSERT_FALSE(PathExists(input_file));
513 ASSERT_TRUE(PathExists(alternate_input_file));
skyostil054861d2015-04-30 19:06:15514 scoped_refptr<JsonPrefStore> pref_store =
515 new JsonPrefStore(input_file, alternate_input_file,
516 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47517
518 ASSERT_FALSE(PathExists(input_file));
519 ASSERT_TRUE(PathExists(alternate_input_file));
520 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
521
522 ASSERT_TRUE(PathExists(input_file));
523 ASSERT_FALSE(PathExists(alternate_input_file));
524
525 EXPECT_FALSE(pref_store->ReadOnly());
526 EXPECT_TRUE(pref_store->IsInitializationComplete());
527
528 // The JSON file looks like this:
529 // {
530 // "homepage": "http://www.cnn.com",
531 // "some_directory": "/usr/local/",
532 // "tabs": {
533 // "new_windows_in_tabs": true,
534 // "max_tabs": 20
535 // }
536 // }
537
brettw58cd1f12016-01-30 05:56:05538 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47539}
540
541TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
brettw58cd1f12016-01-30 05:56:05542 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
543 ASSERT_LT(0, base::WriteFile(input_file,
544 kReadJson, arraysize(kReadJson) - 1));
545
546 base::FilePath alternate_input_file =
547 temp_dir_.path().AppendASCII("alternate.json");
548 ASSERT_LT(0, base::WriteFile(alternate_input_file,
549 kInvalidJson, arraysize(kInvalidJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47550
551 // Test that the alternate file is ignored and that the read occurs from the
552 // existing main file. There is no attempt at even deleting the alternate
553 // file as this scenario should never happen in normal user-data-dirs.
skyostil054861d2015-04-30 19:06:15554 scoped_refptr<JsonPrefStore> pref_store =
555 new JsonPrefStore(input_file, alternate_input_file,
556 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47557
558 ASSERT_TRUE(PathExists(input_file));
559 ASSERT_TRUE(PathExists(alternate_input_file));
560 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
561
562 ASSERT_TRUE(PathExists(input_file));
563 ASSERT_TRUE(PathExists(alternate_input_file));
564
565 EXPECT_FALSE(pref_store->ReadOnly());
566 EXPECT_TRUE(pref_store->IsInitializationComplete());
567
568 // The JSON file looks like this:
569 // {
570 // "homepage": "http://www.cnn.com",
571 // "some_directory": "/usr/local/",
572 // "tabs": {
573 // "new_windows_in_tabs": true,
574 // "max_tabs": 20
575 // }
576 // }
577
brettw58cd1f12016-01-30 05:56:05578 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47579}
580
581TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
brettw58cd1f12016-01-30 05:56:05582 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
583 ASSERT_LT(0, base::WriteFile(input_file,
584 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47585
586 // Test that the basic read works fine when an alternate file is specified but
587 // does not exist.
[email protected]cfcf0e52014-06-20 18:29:47588 base::FilePath alternate_input_file =
589 temp_dir_.path().AppendASCII("alternate.json");
590 ASSERT_TRUE(PathExists(input_file));
591 ASSERT_FALSE(PathExists(alternate_input_file));
skyostil054861d2015-04-30 19:06:15592 scoped_refptr<JsonPrefStore> pref_store =
593 new JsonPrefStore(input_file, alternate_input_file,
594 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47595
596 ASSERT_TRUE(PathExists(input_file));
597 ASSERT_FALSE(PathExists(alternate_input_file));
598 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
599
600 ASSERT_TRUE(PathExists(input_file));
601 ASSERT_FALSE(PathExists(alternate_input_file));
602
603 EXPECT_FALSE(pref_store->ReadOnly());
604 EXPECT_TRUE(pref_store->IsInitializationComplete());
605
606 // The JSON file looks like this:
607 // {
608 // "homepage": "http://www.cnn.com",
609 // "some_directory": "/usr/local/",
610 // "tabs": {
611 // "new_windows_in_tabs": true,
612 // "max_tabs": 20
613 // }
614 // }
615
brettw58cd1f12016-01-30 05:56:05616 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47617}
618
619TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
brettw58cd1f12016-01-30 05:56:05620 base::FilePath alternate_input_file =
621 temp_dir_.path().AppendASCII("alternate.json");
622 ASSERT_LT(0, base::WriteFile(alternate_input_file,
623 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47624
625 // Test that the alternate file is moved to the main file and read as-is from
626 // there even when the read is made asynchronously.
627 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
skyostil054861d2015-04-30 19:06:15628 scoped_refptr<JsonPrefStore> pref_store =
629 new JsonPrefStore(input_file, alternate_input_file,
630 message_loop_.task_runner(), scoped_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47631
632 ASSERT_FALSE(PathExists(input_file));
633 ASSERT_TRUE(PathExists(alternate_input_file));
634
635 {
636 MockPrefStoreObserver mock_observer;
637 pref_store->AddObserver(&mock_observer);
638
639 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
640 pref_store->ReadPrefsAsync(mock_error_delegate);
641
642 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
643 EXPECT_CALL(*mock_error_delegate,
644 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
645 RunLoop().RunUntilIdle();
646 pref_store->RemoveObserver(&mock_observer);
647
648 EXPECT_FALSE(pref_store->ReadOnly());
649 EXPECT_TRUE(pref_store->IsInitializationComplete());
650 }
651
652 ASSERT_TRUE(PathExists(input_file));
653 ASSERT_FALSE(PathExists(alternate_input_file));
654
655 // The JSON file looks like this:
656 // {
657 // "homepage": "http://www.cnn.com",
658 // "some_directory": "/usr/local/",
659 // "tabs": {
660 // "new_windows_in_tabs": true,
661 // "max_tabs": 20
662 // }
663 // }
664
brettw58cd1f12016-01-30 05:56:05665 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47666}
667
raymesbfb910a2015-04-29 07:43:09668TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
brettw58cd1f12016-01-30 05:56:05669 base::HistogramTester histogram_tester;
670
raymesbfb910a2015-04-29 07:43:09671 SimpleTestClock* test_clock = new SimpleTestClock;
672 SetCurrentTimeInMinutes(0, test_clock);
673 JsonPrefStore::WriteCountHistogram histogram(
674 base::TimeDelta::FromSeconds(10),
675 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
676 scoped_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36677 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09678 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
679
680 histogram.RecordWriteOccured();
681
682 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
683 histogram.ReportOutstandingWrites();
684 scoped_ptr<HistogramSamples> samples =
685 histogram.GetHistogram()->SnapshotSamples();
brettw58cd1f12016-01-30 05:56:05686
687 std::string histogram_name = histogram.GetHistogram()->histogram_name();
688 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
689 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09690
691 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State",
692 histogram.GetHistogram()->histogram_name());
693 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31));
694}
695
696TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) {
brettw58cd1f12016-01-30 05:56:05697 base::HistogramTester histogram_tester;
698
raymesbfb910a2015-04-29 07:43:09699 SimpleTestClock* test_clock = new SimpleTestClock;
700 SetCurrentTimeInMinutes(0, test_clock);
701 JsonPrefStore::WriteCountHistogram histogram(
702 base::TimeDelta::FromSeconds(10),
703 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
704 scoped_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36705 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09706 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
707
708 histogram.RecordWriteOccured();
709 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
710 histogram.RecordWriteOccured();
711 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
712 histogram.RecordWriteOccured();
713
714 // Nothing should be recorded until the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05715 std::string histogram_name = histogram.GetHistogram()->histogram_name();
716 histogram_tester.ExpectTotalCount(histogram_name, 0);
raymesbfb910a2015-04-29 07:43:09717
718 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
719 histogram.RecordWriteOccured();
720
721 // Now the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05722 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
723 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09724
725 // The last write won't be recorded because the second count period hasn't
726 // fully elapsed.
727 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
728 histogram.ReportOutstandingWrites();
729
brettw58cd1f12016-01-30 05:56:05730 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
731 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09732}
733
734TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) {
brettw58cd1f12016-01-30 05:56:05735 base::HistogramTester histogram_tester;
736
raymesbfb910a2015-04-29 07:43:09737 SimpleTestClock* test_clock = new SimpleTestClock;
738 SetCurrentTimeInMinutes(0, test_clock);
739 JsonPrefStore::WriteCountHistogram histogram(
740 base::TimeDelta::FromSeconds(10),
741 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
742 scoped_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36743 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09744 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
745
746 histogram.RecordWriteOccured();
747 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
748 histogram.RecordWriteOccured();
749 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
750 histogram.RecordWriteOccured();
751 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
752 histogram.RecordWriteOccured();
753 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
754 histogram.RecordWriteOccured();
755 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock);
756 histogram.RecordWriteOccured();
757 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock);
758 histogram.RecordWriteOccured();
759 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock);
760 histogram.RecordWriteOccured();
761 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
762 histogram.RecordWriteOccured();
763
764 // The last write won't be recorded because the second count period hasn't
765 // fully elapsed
766 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock);
767 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05768 std::string histogram_name = histogram.GetHistogram()->histogram_name();
769 histogram_tester.ExpectBucketCount(histogram_name, 3, 2);
770 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
771 histogram_tester.ExpectTotalCount(histogram_name, 3);
raymesbfb910a2015-04-29 07:43:09772}
773
774TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) {
brettw58cd1f12016-01-30 05:56:05775 base::HistogramTester histogram_tester;
776
raymesbfb910a2015-04-29 07:43:09777 SimpleTestClock* test_clock = new SimpleTestClock;
778 SetCurrentTimeInMinutes(0, test_clock);
779 JsonPrefStore::WriteCountHistogram histogram(
780 base::TimeDelta::FromSeconds(10),
781 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
782 scoped_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36783 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09784 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
785
786 // 1 write in the first period.
787 histogram.RecordWriteOccured();
788
789 // No writes in the second and third periods.
790
791 // 2 writes in the fourth period.
792 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock);
793 histogram.RecordWriteOccured();
794 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
795 histogram.RecordWriteOccured();
796
797 // No writes in the fifth period.
798
799 // 3 writes in the sixth period.
800 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock);
801 histogram.RecordWriteOccured();
802 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock);
803 histogram.RecordWriteOccured();
804 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock);
805 histogram.RecordWriteOccured();
806
807 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock);
808 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05809 std::string histogram_name = histogram.GetHistogram()->histogram_name();
810 histogram_tester.ExpectBucketCount(histogram_name, 0, 3);
811 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
812 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
813 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
814 histogram_tester.ExpectTotalCount(histogram_name, 6);
raymesbfb910a2015-04-29 07:43:09815}
816
raymes4b6e14e2015-05-12 00:10:30817class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
818 protected:
819 void SetUp() override {
820 JsonPrefStoreTest::SetUp();
821 test_file_ = temp_dir_.path().AppendASCII("test.json");
822 }
823
824 // Creates a JsonPrefStore with the given |file_writer|.
825 scoped_refptr<JsonPrefStore> CreatePrefStore() {
826 return new JsonPrefStore(test_file_, message_loop_.task_runner(),
827 scoped_ptr<PrefFilter>());
828 }
829
830 // Return the ImportantFileWriter for a given JsonPrefStore.
831 ImportantFileWriter* GetImportantFileWriter(
832 scoped_refptr<JsonPrefStore> pref_store) {
833 return &(pref_store->writer_);
834 }
835
836 // Get the contents of kTestFile. Pumps the message loop before returning the
837 // result.
838 std::string GetTestFileContents() {
839 RunLoop().RunUntilIdle();
840 std::string file_contents;
841 ReadFileToString(test_file_, &file_contents);
842 return file_contents;
843 }
844
845 private:
846 base::FilePath test_file_;
847};
848
849TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) {
850 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
851 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
852
853 // Set a normal pref and check that it gets scheduled to be written.
854 ASSERT_FALSE(file_writer->HasPendingWrite());
estade0bd407f2015-06-26 18:16:18855 pref_store->SetValue("normal",
856 make_scoped_ptr(new base::StringValue("normal")),
raymes4b6e14e2015-05-12 00:10:30857 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
858 ASSERT_TRUE(file_writer->HasPendingWrite());
859 file_writer->DoScheduledWrite();
860 ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents());
861 ASSERT_FALSE(file_writer->HasPendingWrite());
862
863 // Set a lossy pref and check that it is not scheduled to be written.
864 // SetValue/RemoveValue.
estade0bd407f2015-06-26 18:16:18865 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30866 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
867 ASSERT_FALSE(file_writer->HasPendingWrite());
868 pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
869 ASSERT_FALSE(file_writer->HasPendingWrite());
870
871 // SetValueSilently/RemoveValueSilently.
estade0bd407f2015-06-26 18:16:18872 pref_store->SetValueSilently("lossy",
873 make_scoped_ptr(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30874 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
875 ASSERT_FALSE(file_writer->HasPendingWrite());
876 pref_store->RemoveValueSilently("lossy",
877 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
878 ASSERT_FALSE(file_writer->HasPendingWrite());
879
880 // ReportValueChanged.
estade0bd407f2015-06-26 18:16:18881 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30882 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
883 ASSERT_FALSE(file_writer->HasPendingWrite());
884 pref_store->ReportValueChanged("lossy",
885 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
886 ASSERT_FALSE(file_writer->HasPendingWrite());
887
888 // Call CommitPendingWrite and check that the lossy pref and the normal pref
889 // are there with the last values set above.
890 pref_store->CommitPendingWrite();
891 ASSERT_FALSE(file_writer->HasPendingWrite());
892 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
893 GetTestFileContents());
894}
895
896TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) {
897 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
898 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
899
900 // Set a lossy pref and check that it is not scheduled to be written.
901 ASSERT_FALSE(file_writer->HasPendingWrite());
estade0bd407f2015-06-26 18:16:18902 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30903 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
904 ASSERT_FALSE(file_writer->HasPendingWrite());
905
906 // Set a normal pref and check that it is scheduled to be written.
estade0bd407f2015-06-26 18:16:18907 pref_store->SetValue("normal",
908 make_scoped_ptr(new base::StringValue("normal")),
raymes4b6e14e2015-05-12 00:10:30909 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
910 ASSERT_TRUE(file_writer->HasPendingWrite());
911
912 // Call DoScheduledWrite and check both prefs get written.
913 file_writer->DoScheduledWrite();
914 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
915 GetTestFileContents());
916 ASSERT_FALSE(file_writer->HasPendingWrite());
917}
918
919TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) {
920 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
921 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
922
923 // Set a normal pref and check that it is scheduled to be written.
924 ASSERT_FALSE(file_writer->HasPendingWrite());
estade0bd407f2015-06-26 18:16:18925 pref_store->SetValue("normal",
926 make_scoped_ptr(new base::StringValue("normal")),
raymes4b6e14e2015-05-12 00:10:30927 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
928 ASSERT_TRUE(file_writer->HasPendingWrite());
929
930 // Set a lossy pref and check that the write is still scheduled.
estade0bd407f2015-06-26 18:16:18931 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30932 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
933 ASSERT_TRUE(file_writer->HasPendingWrite());
934
935 // Call DoScheduledWrite and check both prefs get written.
936 file_writer->DoScheduledWrite();
937 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
938 GetTestFileContents());
939 ASSERT_FALSE(file_writer->HasPendingWrite());
940}
941
benwells26730592015-05-28 13:08:08942TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) {
943 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
944 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
945
946 // Set a lossy pref and check that it is not scheduled to be written.
estade0bd407f2015-06-26 18:16:18947 pref_store->SetValue("lossy", make_scoped_ptr(new base::StringValue("lossy")),
benwells26730592015-05-28 13:08:08948 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
949 ASSERT_FALSE(file_writer->HasPendingWrite());
950
951 // Schedule pending lossy writes and check that it is scheduled.
952 pref_store->SchedulePendingLossyWrites();
953 ASSERT_TRUE(file_writer->HasPendingWrite());
954
955 // Call CommitPendingWrite and check that the lossy pref is there with the
956 // last value set above.
957 pref_store->CommitPendingWrite();
958 ASSERT_FALSE(file_writer->HasPendingWrite());
959 ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents());
960}
961
[email protected]7e3ec42c2012-12-16 05:13:21962} // namespace base