blob: 2255c2e0971e68c7fe7207cb0ced61535f05375b [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
brettwf00b9b42016-02-01 22:11:385#include "components/prefs/json_pref_store.h"
[email protected]00c87822012-11-27 19:09:176
avi9ef8bb02015-12-24 05:29:367#include <stdint.h>
8
dcheng5f043bc2016-04-22 19:09:069#include <memory>
danakj0c8d4aa2015-11-25 05:29:5810#include <utility>
11
[email protected]e33c9512014-05-12 02:24:1312#include "base/bind.h"
[email protected]e3177dd52014-08-13 20:22:1413#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2314#include "base/files/scoped_temp_dir.h"
skyostil054861d2015-04-30 19:06:1515#include "base/location.h"
avi9ef8bb02015-12-24 05:29:3616#include "base/macros.h"
dcheng5f043bc2016-04-22 19:09:0617#include "base/memory/ptr_util.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/ref_counted.h"
[email protected]e33c9512014-05-12 02:24:1319#include "base/message_loop/message_loop.h"
raymesbfb910a2015-04-29 07:43:0920#include "base/metrics/histogram_samples.h"
[email protected]277404c22010-04-22 13:09:4521#include "base/path_service.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"
brettwf00b9b42016-02-01 22:11:3832#include "components/prefs/pref_filter.h"
[email protected]845b43a82011-05-11 10:14:4333#include "testing/gmock/include/gmock/gmock.h"
[email protected]277404c22010-04-22 13:09:4534#include "testing/gtest/include/gtest/gtest.h"
35
[email protected]7e3ec42c2012-12-16 05:13:2136namespace base {
[email protected]845b43a82011-05-11 10:14:4337namespace {
38
[email protected]5bfdcfd2012-11-22 22:08:2439const char kHomePage[] = "homepage";
40
brettw58cd1f12016-01-30 05:56:0541const char kReadJson[] =
42 "{\n"
43 " \"homepage\": \"http://www.cnn.com\",\n"
44 " \"some_directory\": \"/usr/local/\",\n"
45 " \"tabs\": {\n"
46 " \"new_windows_in_tabs\": true,\n"
47 " \"max_tabs\": 20\n"
48 " }\n"
49 "}";
50
51const char kInvalidJson[] = "!@#$%^&";
52
53// Expected output for tests using RunBasicJsonPrefStoreTest().
54const char kWriteGolden[] =
55 "{\"homepage\":\"http://www.cnn.com\","
56 "\"long_int\":{\"pref\":\"214748364842\"},"
57 "\"some_directory\":\"/usr/sbin/\","
58 "\"tabs\":{\"max_tabs\":10,\"new_windows_in_tabs\":false}}";
59
raymesbfb910a2015-04-29 07:43:0960// Set the time on the given SimpleTestClock to the given time in minutes.
61void SetCurrentTimeInMinutes(double minutes, base::SimpleTestClock* clock) {
62 const int32_t kBaseTimeMins = 100;
63 clock->SetNow(base::Time::FromDoubleT((kBaseTimeMins + minutes) * 60));
64}
65
[email protected]e33c9512014-05-12 02:24:1366// A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
67// to the |prefs| until explicitly asked to release them.
68class InterceptingPrefFilter : public PrefFilter {
69 public:
70 InterceptingPrefFilter();
dcheng56488182014-10-21 10:54:5171 ~InterceptingPrefFilter() override;
[email protected]e33c9512014-05-12 02:24:1372
73 // PrefFilter implementation:
dcheng56488182014-10-21 10:54:5174 void FilterOnLoad(
[email protected]e33c9512014-05-12 02:24:1375 const PostFilterOnLoadCallback& post_filter_on_load_callback,
dcheng5f043bc2016-04-22 19:09:0676 std::unique_ptr<base::DictionaryValue> pref_store_contents) override;
dcheng56488182014-10-21 10:54:5177 void FilterUpdate(const std::string& path) override {}
78 void FilterSerializeData(
mostynb9e096de2014-10-07 17:59:1179 base::DictionaryValue* pref_store_contents) override {}
[email protected]e33c9512014-05-12 02:24:1380
81 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
82
[email protected]cfcf0e52014-06-20 18:29:4783 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
[email protected]e33c9512014-05-12 02:24:1384 // JsonPrefStore.
85 void ReleasePrefs();
86
87 private:
88 PostFilterOnLoadCallback post_filter_on_load_callback_;
dcheng5f043bc2016-04-22 19:09:0689 std::unique_ptr<base::DictionaryValue> intercepted_prefs_;
[email protected]e33c9512014-05-12 02:24:1390
91 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter);
92};
93
94InterceptingPrefFilter::InterceptingPrefFilter() {}
95InterceptingPrefFilter::~InterceptingPrefFilter() {}
96
97void InterceptingPrefFilter::FilterOnLoad(
98 const PostFilterOnLoadCallback& post_filter_on_load_callback,
dcheng5f043bc2016-04-22 19:09:0699 std::unique_ptr<base::DictionaryValue> pref_store_contents) {
[email protected]e33c9512014-05-12 02:24:13100 post_filter_on_load_callback_ = post_filter_on_load_callback;
danakj0c8d4aa2015-11-25 05:29:58101 intercepted_prefs_ = std::move(pref_store_contents);
[email protected]e33c9512014-05-12 02:24:13102}
103
104void InterceptingPrefFilter::ReleasePrefs() {
105 EXPECT_FALSE(post_filter_on_load_callback_.is_null());
danakj0c8d4aa2015-11-25 05:29:58106 post_filter_on_load_callback_.Run(std::move(intercepted_prefs_), false);
[email protected]e33c9512014-05-12 02:24:13107 post_filter_on_load_callback_.Reset();
108}
109
[email protected]845b43a82011-05-11 10:14:43110class MockPrefStoreObserver : public PrefStore::Observer {
111 public:
112 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
113 MOCK_METHOD1(OnInitializationCompleted, void (bool));
114};
115
116class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
117 public:
118 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
119};
120
121} // namespace
122
[email protected]277404c22010-04-22 13:09:45123class JsonPrefStoreTest : public testing::Test {
124 protected:
dcheng8aef37612014-12-23 02:56:47125 void SetUp() override {
[email protected]3a305db2011-04-12 13:40:53126 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]277404c22010-04-22 13:09:45127 }
128
dcheng8aef37612014-12-23 02:56:47129 void TearDown() override {
[email protected]e33c9512014-05-12 02:24:13130 // Make sure all pending tasks have been processed (e.g., deleting the
131 // JsonPrefStore may post write tasks).
raymes4b6e14e2015-05-12 00:10:30132 RunLoop().RunUntilIdle();
[email protected]e33c9512014-05-12 02:24:13133 }
134
[email protected]3a305db2011-04-12 13:40:53135 // The path to temporary directory used to contain the test operations.
[email protected]ea1a3f62012-11-16 20:34:23136 base::ScopedTempDir temp_dir_;
[email protected]ea587b02010-05-21 15:01:35137 // A message loop that we can use as the file thread message loop.
138 MessageLoop message_loop_;
[email protected]277404c22010-04-22 13:09:45139};
140
141// Test fallback behavior for a nonexistent file.
142TEST_F(JsonPrefStoreTest, NonExistentFile) {
vabr8023d872016-09-15 08:12:22143 base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07144 ASSERT_FALSE(PathExists(bogus_input_file));
dcheng5f043bc2016-04-22 19:09:06145 scoped_refptr<JsonPrefStore> pref_store =
146 new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
147 std::unique_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17148 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
[email protected]9a8c4022011-01-25 14:25:33149 pref_store->ReadPrefs());
150 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45151}
152
[email protected]cfcf0e52014-06-20 18:29:47153// Test fallback behavior for a nonexistent file and alternate file.
154TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) {
vabr8023d872016-09-15 08:12:22155 base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
[email protected]cfcf0e52014-06-20 18:29:47156 base::FilePath bogus_alternate_input_file =
vabr8023d872016-09-15 08:12:22157 temp_dir_.GetPath().AppendASCII("read_alternate.txt");
[email protected]cfcf0e52014-06-20 18:29:47158 ASSERT_FALSE(PathExists(bogus_input_file));
159 ASSERT_FALSE(PathExists(bogus_alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06160 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
161 bogus_input_file, bogus_alternate_input_file, message_loop_.task_runner(),
162 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47163 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
164 pref_store->ReadPrefs());
165 EXPECT_FALSE(pref_store->ReadOnly());
166}
167
[email protected]277404c22010-04-22 13:09:45168// Test fallback behavior for an invalid file.
169TEST_F(JsonPrefStoreTest, InvalidFile) {
vabr8023d872016-09-15 08:12:22170 base::FilePath invalid_file = temp_dir_.GetPath().AppendASCII("invalid.json");
brettw58cd1f12016-01-30 05:56:05171 ASSERT_LT(0, base::WriteFile(invalid_file,
172 kInvalidJson, arraysize(kInvalidJson) - 1));
173
skyostil054861d2015-04-30 19:06:15174 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06175 invalid_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17176 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
[email protected]9a8c4022011-01-25 14:25:33177 pref_store->ReadPrefs());
178 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45179
180 // The file should have been moved aside.
[email protected]7567484142013-07-11 17:36:07181 EXPECT_FALSE(PathExists(invalid_file));
vabr8023d872016-09-15 08:12:22182 base::FilePath moved_aside = temp_dir_.GetPath().AppendASCII("invalid.bad");
[email protected]7567484142013-07-11 17:36:07183 EXPECT_TRUE(PathExists(moved_aside));
brettw58cd1f12016-01-30 05:56:05184
185 std::string moved_aside_contents;
186 ASSERT_TRUE(base::ReadFileToString(moved_aside, &moved_aside_contents));
187 EXPECT_EQ(kInvalidJson, moved_aside_contents);
[email protected]277404c22010-04-22 13:09:45188}
189
brettw58cd1f12016-01-30 05:56:05190// This function is used to avoid code duplication while testing synchronous
191// and asynchronous version of the JsonPrefStore loading. It validates that the
192// given output file's contents matches kWriteGolden.
[email protected]0de615a2012-11-08 04:40:59193void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
brettw58cd1f12016-01-30 05:56:05194 const base::FilePath& output_file) {
[email protected]57ecc4b2010-08-11 03:02:51195 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
196 const char kMaxTabs[] = "tabs.max_tabs";
197 const char kLongIntPref[] = "long_int.pref";
[email protected]277404c22010-04-22 13:09:45198
[email protected]57ecc4b2010-08-11 03:02:51199 std::string cnn("http://www.cnn.com");
[email protected]277404c22010-04-22 13:09:45200
[email protected]68bf41a2011-03-25 16:38:31201 const Value* actual;
[email protected]5bfdcfd2012-11-22 22:08:24202 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
[email protected]57ecc4b2010-08-11 03:02:51203 std::string string_value;
[email protected]f2d1f612010-12-09 15:10:17204 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]277404c22010-04-22 13:09:45205 EXPECT_EQ(cnn, string_value);
206
[email protected]57ecc4b2010-08-11 03:02:51207 const char kSomeDirectory[] = "some_directory";
[email protected]277404c22010-04-22 13:09:45208
[email protected]892f1d62012-11-08 18:24:34209 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]023ad6ab2013-02-17 05:07:23210 base::FilePath::StringType path;
[email protected]f2d1f612010-12-09 15:10:17211 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]023ad6ab2013-02-17 05:07:23212 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
213 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
[email protected]f2d1f612010-12-09 15:10:17214
estade0bd407f2015-06-26 18:16:18215 pref_store->SetValue(kSomeDirectory,
ricea85ec57952016-08-31 09:34:10216 base::MakeUnique<StringValue>(some_path.value()),
raymes76de1af2015-05-06 03:22:21217 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34218 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]f2d1f612010-12-09 15:10:17219 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]277404c22010-04-22 13:09:45220 EXPECT_EQ(some_path.value(), path);
221
222 // Test reading some other data types from sub-dictionaries.
[email protected]892f1d62012-11-08 18:24:34223 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17224 bool boolean = false;
225 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45226 EXPECT_TRUE(boolean);
227
estade0bd407f2015-06-26 18:16:18228 pref_store->SetValue(kNewWindowsInTabs,
ricea85ec57952016-08-31 09:34:10229 base::MakeUnique<FundamentalValue>(false),
raymes76de1af2015-05-06 03:22:21230 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34231 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17232 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45233 EXPECT_FALSE(boolean);
234
[email protected]892f1d62012-11-08 18:24:34235 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17236 int integer = 0;
237 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45238 EXPECT_EQ(20, integer);
ricea85ec57952016-08-31 09:34:10239 pref_store->SetValue(kMaxTabs, base::MakeUnique<FundamentalValue>(10),
raymes76de1af2015-05-06 03:22:21240 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34241 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17242 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45243 EXPECT_EQ(10, integer);
244
ricea85ec57952016-08-31 09:34:10245 pref_store->SetValue(kLongIntPref, base::MakeUnique<StringValue>(
246 base::Int64ToString(214748364842LL)),
247 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34248 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
[email protected]f2d1f612010-12-09 15:10:17249 EXPECT_TRUE(actual->GetAsString(&string_value));
avi9ef8bb02015-12-24 05:29:36250 int64_t value;
[email protected]57ecc4b2010-08-11 03:02:51251 base::StringToInt64(string_value, &value);
[email protected]e83326f2010-07-31 17:29:25252 EXPECT_EQ(214748364842LL, value);
[email protected]277404c22010-04-22 13:09:45253
254 // Serialize and compare to expected output.
[email protected]fbe17c8a2011-12-27 16:41:48255 pref_store->CommitPendingWrite();
[email protected]f7b98b32013-02-05 08:14:15256 RunLoop().RunUntilIdle();
brettw58cd1f12016-01-30 05:56:05257
258 std::string output_contents;
259 ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents));
260 EXPECT_EQ(kWriteGolden, output_contents);
[email protected]dd3aa792013-07-16 19:10:23261 ASSERT_TRUE(base::DeleteFile(output_file, false));
[email protected]277404c22010-04-22 13:09:45262}
[email protected]845b43a82011-05-11 10:14:43263
264TEST_F(JsonPrefStoreTest, Basic) {
vabr8023d872016-09-15 08:12:22265 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05266 ASSERT_LT(0, base::WriteFile(input_file,
267 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43268
269 // Test that the persistent value can be loaded.
[email protected]7567484142013-07-11 17:36:07270 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46271 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06272 input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43273 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
[email protected]e33c9512014-05-12 02:24:13274 EXPECT_FALSE(pref_store->ReadOnly());
275 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]845b43a82011-05-11 10:14:43276
277 // The JSON file looks like this:
278 // {
279 // "homepage": "http://www.cnn.com",
280 // "some_directory": "/usr/local/",
281 // "tabs": {
282 // "new_windows_in_tabs": true,
283 // "max_tabs": 20
284 // }
285 // }
286
brettw58cd1f12016-01-30 05:56:05287 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43288}
289
290TEST_F(JsonPrefStoreTest, BasicAsync) {
vabr8023d872016-09-15 08:12:22291 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05292 ASSERT_LT(0, base::WriteFile(input_file,
293 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43294
295 // Test that the persistent value can be loaded.
[email protected]56cbcb3a2013-12-23 21:24:46296 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06297 input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43298
[email protected]0de615a2012-11-08 04:40:59299 {
300 MockPrefStoreObserver mock_observer;
301 pref_store->AddObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43302
[email protected]0de615a2012-11-08 04:40:59303 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
304 pref_store->ReadPrefsAsync(mock_error_delegate);
[email protected]845b43a82011-05-11 10:14:43305
[email protected]0de615a2012-11-08 04:40:59306 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
307 EXPECT_CALL(*mock_error_delegate,
308 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
[email protected]7ff48ca2013-02-06 16:56:19309 RunLoop().RunUntilIdle();
[email protected]0de615a2012-11-08 04:40:59310 pref_store->RemoveObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43311
[email protected]e33c9512014-05-12 02:24:13312 EXPECT_FALSE(pref_store->ReadOnly());
313 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]0de615a2012-11-08 04:40:59314 }
[email protected]845b43a82011-05-11 10:14:43315
316 // The JSON file looks like this:
317 // {
318 // "homepage": "http://www.cnn.com",
319 // "some_directory": "/usr/local/",
320 // "tabs": {
321 // "new_windows_in_tabs": true,
322 // "max_tabs": 20
323 // }
324 // }
325
brettw58cd1f12016-01-30 05:56:05326 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43327}
328
[email protected]aa3283392013-11-27 01:38:24329TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
vabr8023d872016-09-15 08:12:22330 FilePath pref_file = temp_dir_.GetPath().AppendASCII("empty_values.json");
[email protected]aa3283392013-11-27 01:38:24331
[email protected]56cbcb3a2013-12-23 21:24:46332 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06333 pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24334
335 // Set some keys with empty values.
dcheng5f043bc2016-04-22 19:09:06336 pref_store->SetValue("list", base::WrapUnique(new base::ListValue),
raymes76de1af2015-05-06 03:22:21337 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
dcheng5f043bc2016-04-22 19:09:06338 pref_store->SetValue("dict", base::WrapUnique(new base::DictionaryValue),
raymes76de1af2015-05-06 03:22:21339 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]aa3283392013-11-27 01:38:24340
341 // Write to file.
342 pref_store->CommitPendingWrite();
raymes4b6e14e2015-05-12 00:10:30343 RunLoop().RunUntilIdle();
[email protected]aa3283392013-11-27 01:38:24344
345 // Reload.
skyostil054861d2015-04-30 19:06:15346 pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
dcheng5f043bc2016-04-22 19:09:06347 std::unique_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24348 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
349 ASSERT_FALSE(pref_store->ReadOnly());
350
351 // Check values.
352 const Value* result = NULL;
353 EXPECT_TRUE(pref_store->GetValue("list", &result));
354 EXPECT_TRUE(ListValue().Equals(result));
355 EXPECT_TRUE(pref_store->GetValue("dict", &result));
356 EXPECT_TRUE(DictionaryValue().Equals(result));
357}
358
[email protected]eeedaa692014-01-30 09:22:27359// This test is just documenting some potentially non-obvious behavior. It
360// shouldn't be taken as normative.
361TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
vabr8023d872016-09-15 08:12:22362 FilePath pref_file = temp_dir_.GetPath().AppendASCII("empty_values.json");
[email protected]eeedaa692014-01-30 09:22:27363
364 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06365 pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]eeedaa692014-01-30 09:22:27366
dcheng5f043bc2016-04-22 19:09:06367 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
[email protected]eeedaa692014-01-30 09:22:27368 dict->SetString("key", "value");
danakj0c8d4aa2015-11-25 05:29:58369 pref_store->SetValue("dict", std::move(dict),
raymes76de1af2015-05-06 03:22:21370 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27371
raymes76de1af2015-05-06 03:22:21372 pref_store->RemoveValue("dict.key",
373 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27374
375 const base::Value* retrieved_dict = NULL;
376 bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
377 EXPECT_FALSE(has_dict);
378}
379
[email protected]845b43a82011-05-11 10:14:43380// Tests asynchronous reading of the file when there is no file.
381TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
vabr8023d872016-09-15 08:12:22382 base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07383 ASSERT_FALSE(PathExists(bogus_input_file));
dcheng5f043bc2016-04-22 19:09:06384 scoped_refptr<JsonPrefStore> pref_store =
385 new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
386 std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43387 MockPrefStoreObserver mock_observer;
388 pref_store->AddObserver(&mock_observer);
389
390 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
391 pref_store->ReadPrefsAsync(mock_error_delegate);
392
393 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
394 EXPECT_CALL(*mock_error_delegate,
395 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
[email protected]7ff48ca2013-02-06 16:56:19396 RunLoop().RunUntilIdle();
[email protected]845b43a82011-05-11 10:14:43397 pref_store->RemoveObserver(&mock_observer);
398
399 EXPECT_FALSE(pref_store->ReadOnly());
400}
[email protected]ea3e4972012-04-12 03:41:37401
[email protected]e33c9512014-05-12 02:24:13402TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
vabr8023d872016-09-15 08:12:22403 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05404 ASSERT_LT(0, base::WriteFile(input_file,
405 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13406
dcheng5f043bc2016-04-22 19:09:06407 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
[email protected]e33c9512014-05-12 02:24:13408 new InterceptingPrefFilter());
409 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
410 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58411 scoped_refptr<JsonPrefStore> pref_store =
412 new JsonPrefStore(input_file, message_loop_.task_runner(),
413 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13414
415 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
416 pref_store->ReadPrefs());
417 EXPECT_FALSE(pref_store->ReadOnly());
418
419 // The store shouldn't be considered initialized until the interceptor
420 // returns.
421 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
422 EXPECT_FALSE(pref_store->IsInitializationComplete());
423 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
424
425 raw_intercepting_pref_filter_->ReleasePrefs();
426
427 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
428 EXPECT_TRUE(pref_store->IsInitializationComplete());
429 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
430
431 // The JSON file looks like this:
432 // {
433 // "homepage": "http://www.cnn.com",
434 // "some_directory": "/usr/local/",
435 // "tabs": {
436 // "new_windows_in_tabs": true,
437 // "max_tabs": 20
438 // }
439 // }
440
brettw58cd1f12016-01-30 05:56:05441 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13442}
443
444TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
vabr8023d872016-09-15 08:12:22445 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05446 ASSERT_LT(0, base::WriteFile(input_file,
447 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13448
dcheng5f043bc2016-04-22 19:09:06449 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
[email protected]e33c9512014-05-12 02:24:13450 new InterceptingPrefFilter());
451 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
452 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58453 scoped_refptr<JsonPrefStore> pref_store =
454 new JsonPrefStore(input_file, message_loop_.task_runner(),
455 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13456
457 MockPrefStoreObserver mock_observer;
458 pref_store->AddObserver(&mock_observer);
459
460 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
461 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
462
463 {
464 pref_store->ReadPrefsAsync(mock_error_delegate);
465
466 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
467 // EXPECT_CALL(*mock_error_delegate,
468 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
469 RunLoop().RunUntilIdle();
470
471 EXPECT_FALSE(pref_store->ReadOnly());
472 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
473 EXPECT_FALSE(pref_store->IsInitializationComplete());
474 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
475 }
476
477 {
478 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
479 // EXPECT_CALL(*mock_error_delegate,
480 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
481
482 raw_intercepting_pref_filter_->ReleasePrefs();
483
484 EXPECT_FALSE(pref_store->ReadOnly());
485 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
486 EXPECT_TRUE(pref_store->IsInitializationComplete());
487 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
488 }
489
490 pref_store->RemoveObserver(&mock_observer);
491
492 // The JSON file looks like this:
493 // {
494 // "homepage": "http://www.cnn.com",
495 // "some_directory": "/usr/local/",
496 // "tabs": {
497 // "new_windows_in_tabs": true,
498 // "max_tabs": 20
499 // }
500 // }
501
brettw58cd1f12016-01-30 05:56:05502 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13503}
504
[email protected]cfcf0e52014-06-20 18:29:47505TEST_F(JsonPrefStoreTest, AlternateFile) {
brettw58cd1f12016-01-30 05:56:05506 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22507 temp_dir_.GetPath().AppendASCII("alternate.json");
brettw58cd1f12016-01-30 05:56:05508 ASSERT_LT(0, base::WriteFile(alternate_input_file,
509 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47510
511 // Test that the alternate file is moved to the main file and read as-is from
512 // there.
vabr8023d872016-09-15 08:12:22513 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
[email protected]cfcf0e52014-06-20 18:29:47514 ASSERT_FALSE(PathExists(input_file));
515 ASSERT_TRUE(PathExists(alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06516 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
517 input_file, alternate_input_file, message_loop_.task_runner(),
518 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47519
520 ASSERT_FALSE(PathExists(input_file));
521 ASSERT_TRUE(PathExists(alternate_input_file));
522 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
523
524 ASSERT_TRUE(PathExists(input_file));
525 ASSERT_FALSE(PathExists(alternate_input_file));
526
527 EXPECT_FALSE(pref_store->ReadOnly());
528 EXPECT_TRUE(pref_store->IsInitializationComplete());
529
530 // The JSON file looks like this:
531 // {
532 // "homepage": "http://www.cnn.com",
533 // "some_directory": "/usr/local/",
534 // "tabs": {
535 // "new_windows_in_tabs": true,
536 // "max_tabs": 20
537 // }
538 // }
539
brettw58cd1f12016-01-30 05:56:05540 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47541}
542
543TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
vabr8023d872016-09-15 08:12:22544 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05545 ASSERT_LT(0, base::WriteFile(input_file,
546 kReadJson, arraysize(kReadJson) - 1));
547
548 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22549 temp_dir_.GetPath().AppendASCII("alternate.json");
brettw58cd1f12016-01-30 05:56:05550 ASSERT_LT(0, base::WriteFile(alternate_input_file,
551 kInvalidJson, arraysize(kInvalidJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47552
553 // Test that the alternate file is ignored and that the read occurs from the
554 // existing main file. There is no attempt at even deleting the alternate
555 // file as this scenario should never happen in normal user-data-dirs.
dcheng5f043bc2016-04-22 19:09:06556 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
557 input_file, alternate_input_file, message_loop_.task_runner(),
558 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47559
560 ASSERT_TRUE(PathExists(input_file));
561 ASSERT_TRUE(PathExists(alternate_input_file));
562 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
563
564 ASSERT_TRUE(PathExists(input_file));
565 ASSERT_TRUE(PathExists(alternate_input_file));
566
567 EXPECT_FALSE(pref_store->ReadOnly());
568 EXPECT_TRUE(pref_store->IsInitializationComplete());
569
570 // The JSON file looks like this:
571 // {
572 // "homepage": "http://www.cnn.com",
573 // "some_directory": "/usr/local/",
574 // "tabs": {
575 // "new_windows_in_tabs": true,
576 // "max_tabs": 20
577 // }
578 // }
579
brettw58cd1f12016-01-30 05:56:05580 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47581}
582
583TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
vabr8023d872016-09-15 08:12:22584 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05585 ASSERT_LT(0, base::WriteFile(input_file,
586 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47587
588 // Test that the basic read works fine when an alternate file is specified but
589 // does not exist.
[email protected]cfcf0e52014-06-20 18:29:47590 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22591 temp_dir_.GetPath().AppendASCII("alternate.json");
[email protected]cfcf0e52014-06-20 18:29:47592 ASSERT_TRUE(PathExists(input_file));
593 ASSERT_FALSE(PathExists(alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06594 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
595 input_file, alternate_input_file, message_loop_.task_runner(),
596 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47597
598 ASSERT_TRUE(PathExists(input_file));
599 ASSERT_FALSE(PathExists(alternate_input_file));
600 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
601
602 ASSERT_TRUE(PathExists(input_file));
603 ASSERT_FALSE(PathExists(alternate_input_file));
604
605 EXPECT_FALSE(pref_store->ReadOnly());
606 EXPECT_TRUE(pref_store->IsInitializationComplete());
607
608 // The JSON file looks like this:
609 // {
610 // "homepage": "http://www.cnn.com",
611 // "some_directory": "/usr/local/",
612 // "tabs": {
613 // "new_windows_in_tabs": true,
614 // "max_tabs": 20
615 // }
616 // }
617
brettw58cd1f12016-01-30 05:56:05618 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47619}
620
621TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
brettw58cd1f12016-01-30 05:56:05622 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22623 temp_dir_.GetPath().AppendASCII("alternate.json");
brettw58cd1f12016-01-30 05:56:05624 ASSERT_LT(0, base::WriteFile(alternate_input_file,
625 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47626
627 // Test that the alternate file is moved to the main file and read as-is from
628 // there even when the read is made asynchronously.
vabr8023d872016-09-15 08:12:22629 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
dcheng5f043bc2016-04-22 19:09:06630 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
631 input_file, alternate_input_file, message_loop_.task_runner(),
632 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47633
634 ASSERT_FALSE(PathExists(input_file));
635 ASSERT_TRUE(PathExists(alternate_input_file));
636
637 {
638 MockPrefStoreObserver mock_observer;
639 pref_store->AddObserver(&mock_observer);
640
641 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
642 pref_store->ReadPrefsAsync(mock_error_delegate);
643
644 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
645 EXPECT_CALL(*mock_error_delegate,
646 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
647 RunLoop().RunUntilIdle();
648 pref_store->RemoveObserver(&mock_observer);
649
650 EXPECT_FALSE(pref_store->ReadOnly());
651 EXPECT_TRUE(pref_store->IsInitializationComplete());
652 }
653
654 ASSERT_TRUE(PathExists(input_file));
655 ASSERT_FALSE(PathExists(alternate_input_file));
656
657 // The JSON file looks like this:
658 // {
659 // "homepage": "http://www.cnn.com",
660 // "some_directory": "/usr/local/",
661 // "tabs": {
662 // "new_windows_in_tabs": true,
663 // "max_tabs": 20
664 // }
665 // }
666
brettw58cd1f12016-01-30 05:56:05667 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47668}
669
raymesbfb910a2015-04-29 07:43:09670TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
brettw58cd1f12016-01-30 05:56:05671 base::HistogramTester histogram_tester;
672
raymesbfb910a2015-04-29 07:43:09673 SimpleTestClock* test_clock = new SimpleTestClock;
674 SetCurrentTimeInMinutes(0, test_clock);
675 JsonPrefStore::WriteCountHistogram histogram(
676 base::TimeDelta::FromSeconds(10),
677 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06678 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36679 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09680 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
681
682 histogram.RecordWriteOccured();
683
684 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
685 histogram.ReportOutstandingWrites();
dcheng5f043bc2016-04-22 19:09:06686 std::unique_ptr<HistogramSamples> samples =
raymesbfb910a2015-04-29 07:43:09687 histogram.GetHistogram()->SnapshotSamples();
brettw58cd1f12016-01-30 05:56:05688
689 std::string histogram_name = histogram.GetHistogram()->histogram_name();
690 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
691 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09692
693 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State",
694 histogram.GetHistogram()->histogram_name());
695 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31));
696}
697
698TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) {
brettw58cd1f12016-01-30 05:56:05699 base::HistogramTester histogram_tester;
700
raymesbfb910a2015-04-29 07:43:09701 SimpleTestClock* test_clock = new SimpleTestClock;
702 SetCurrentTimeInMinutes(0, test_clock);
703 JsonPrefStore::WriteCountHistogram histogram(
704 base::TimeDelta::FromSeconds(10),
705 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06706 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36707 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09708 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
709
710 histogram.RecordWriteOccured();
711 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
712 histogram.RecordWriteOccured();
713 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
714 histogram.RecordWriteOccured();
715
716 // Nothing should be recorded until the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05717 std::string histogram_name = histogram.GetHistogram()->histogram_name();
718 histogram_tester.ExpectTotalCount(histogram_name, 0);
raymesbfb910a2015-04-29 07:43:09719
720 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
721 histogram.RecordWriteOccured();
722
723 // Now the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05724 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
725 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09726
727 // The last write won't be recorded because the second count period hasn't
728 // fully elapsed.
729 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
730 histogram.ReportOutstandingWrites();
731
brettw58cd1f12016-01-30 05:56:05732 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
733 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09734}
735
736TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) {
brettw58cd1f12016-01-30 05:56:05737 base::HistogramTester histogram_tester;
738
raymesbfb910a2015-04-29 07:43:09739 SimpleTestClock* test_clock = new SimpleTestClock;
740 SetCurrentTimeInMinutes(0, test_clock);
741 JsonPrefStore::WriteCountHistogram histogram(
742 base::TimeDelta::FromSeconds(10),
743 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06744 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36745 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09746 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
747
748 histogram.RecordWriteOccured();
749 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
750 histogram.RecordWriteOccured();
751 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
752 histogram.RecordWriteOccured();
753 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
754 histogram.RecordWriteOccured();
755 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
756 histogram.RecordWriteOccured();
757 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock);
758 histogram.RecordWriteOccured();
759 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock);
760 histogram.RecordWriteOccured();
761 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock);
762 histogram.RecordWriteOccured();
763 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
764 histogram.RecordWriteOccured();
765
766 // The last write won't be recorded because the second count period hasn't
767 // fully elapsed
768 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock);
769 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05770 std::string histogram_name = histogram.GetHistogram()->histogram_name();
771 histogram_tester.ExpectBucketCount(histogram_name, 3, 2);
772 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
773 histogram_tester.ExpectTotalCount(histogram_name, 3);
raymesbfb910a2015-04-29 07:43:09774}
775
776TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) {
brettw58cd1f12016-01-30 05:56:05777 base::HistogramTester histogram_tester;
778
raymesbfb910a2015-04-29 07:43:09779 SimpleTestClock* test_clock = new SimpleTestClock;
780 SetCurrentTimeInMinutes(0, test_clock);
781 JsonPrefStore::WriteCountHistogram histogram(
782 base::TimeDelta::FromSeconds(10),
783 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06784 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36785 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09786 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
787
788 // 1 write in the first period.
789 histogram.RecordWriteOccured();
790
791 // No writes in the second and third periods.
792
793 // 2 writes in the fourth period.
794 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock);
795 histogram.RecordWriteOccured();
796 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
797 histogram.RecordWriteOccured();
798
799 // No writes in the fifth period.
800
801 // 3 writes in the sixth period.
802 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock);
803 histogram.RecordWriteOccured();
804 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock);
805 histogram.RecordWriteOccured();
806 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock);
807 histogram.RecordWriteOccured();
808
809 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock);
810 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05811 std::string histogram_name = histogram.GetHistogram()->histogram_name();
812 histogram_tester.ExpectBucketCount(histogram_name, 0, 3);
813 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
814 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
815 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
816 histogram_tester.ExpectTotalCount(histogram_name, 6);
raymesbfb910a2015-04-29 07:43:09817}
818
raymes4b6e14e2015-05-12 00:10:30819class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
820 protected:
821 void SetUp() override {
822 JsonPrefStoreTest::SetUp();
vabr8023d872016-09-15 08:12:22823 test_file_ = temp_dir_.GetPath().AppendASCII("test.json");
raymes4b6e14e2015-05-12 00:10:30824 }
825
826 // Creates a JsonPrefStore with the given |file_writer|.
827 scoped_refptr<JsonPrefStore> CreatePrefStore() {
828 return new JsonPrefStore(test_file_, message_loop_.task_runner(),
dcheng5f043bc2016-04-22 19:09:06829 std::unique_ptr<PrefFilter>());
raymes4b6e14e2015-05-12 00:10:30830 }
831
832 // Return the ImportantFileWriter for a given JsonPrefStore.
833 ImportantFileWriter* GetImportantFileWriter(
834 scoped_refptr<JsonPrefStore> pref_store) {
835 return &(pref_store->writer_);
836 }
837
838 // Get the contents of kTestFile. Pumps the message loop before returning the
839 // result.
840 std::string GetTestFileContents() {
841 RunLoop().RunUntilIdle();
842 std::string file_contents;
843 ReadFileToString(test_file_, &file_contents);
844 return file_contents;
845 }
846
847 private:
848 base::FilePath test_file_;
849};
850
851TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) {
852 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
853 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
854
855 // Set a normal pref and check that it gets scheduled to be written.
856 ASSERT_FALSE(file_writer->HasPendingWrite());
ricea85ec57952016-08-31 09:34:10857 pref_store->SetValue("normal", base::MakeUnique<base::StringValue>("normal"),
raymes4b6e14e2015-05-12 00:10:30858 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
859 ASSERT_TRUE(file_writer->HasPendingWrite());
860 file_writer->DoScheduledWrite();
861 ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents());
862 ASSERT_FALSE(file_writer->HasPendingWrite());
863
864 // Set a lossy pref and check that it is not scheduled to be written.
865 // SetValue/RemoveValue.
ricea85ec57952016-08-31 09:34:10866 pref_store->SetValue("lossy", base::MakeUnique<base::StringValue>("lossy"),
raymes4b6e14e2015-05-12 00:10:30867 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
868 ASSERT_FALSE(file_writer->HasPendingWrite());
869 pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
870 ASSERT_FALSE(file_writer->HasPendingWrite());
871
872 // SetValueSilently/RemoveValueSilently.
estade0bd407f2015-06-26 18:16:18873 pref_store->SetValueSilently("lossy",
ricea85ec57952016-08-31 09:34:10874 base::MakeUnique<base::StringValue>("lossy"),
raymes4b6e14e2015-05-12 00:10:30875 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
876 ASSERT_FALSE(file_writer->HasPendingWrite());
877 pref_store->RemoveValueSilently("lossy",
878 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
879 ASSERT_FALSE(file_writer->HasPendingWrite());
880
881 // ReportValueChanged.
ricea85ec57952016-08-31 09:34:10882 pref_store->SetValue("lossy", base::MakeUnique<base::StringValue>("lossy"),
raymes4b6e14e2015-05-12 00:10:30883 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
884 ASSERT_FALSE(file_writer->HasPendingWrite());
885 pref_store->ReportValueChanged("lossy",
886 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
887 ASSERT_FALSE(file_writer->HasPendingWrite());
888
889 // Call CommitPendingWrite and check that the lossy pref and the normal pref
890 // are there with the last values set above.
891 pref_store->CommitPendingWrite();
892 ASSERT_FALSE(file_writer->HasPendingWrite());
893 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
894 GetTestFileContents());
895}
896
897TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) {
898 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
899 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
900
901 // Set a lossy pref and check that it is not scheduled to be written.
902 ASSERT_FALSE(file_writer->HasPendingWrite());
ricea85ec57952016-08-31 09:34:10903 pref_store->SetValue("lossy", base::MakeUnique<base::StringValue>("lossy"),
raymes4b6e14e2015-05-12 00:10:30904 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
905 ASSERT_FALSE(file_writer->HasPendingWrite());
906
907 // Set a normal pref and check that it is scheduled to be written.
ricea85ec57952016-08-31 09:34:10908 pref_store->SetValue("normal", base::MakeUnique<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());
ricea85ec57952016-08-31 09:34:10925 pref_store->SetValue("normal", base::MakeUnique<base::StringValue>("normal"),
raymes4b6e14e2015-05-12 00:10:30926 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
927 ASSERT_TRUE(file_writer->HasPendingWrite());
928
929 // Set a lossy pref and check that the write is still scheduled.
ricea85ec57952016-08-31 09:34:10930 pref_store->SetValue("lossy", base::MakeUnique<base::StringValue>("lossy"),
raymes4b6e14e2015-05-12 00:10:30931 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
932 ASSERT_TRUE(file_writer->HasPendingWrite());
933
934 // Call DoScheduledWrite and check both prefs get written.
935 file_writer->DoScheduledWrite();
936 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
937 GetTestFileContents());
938 ASSERT_FALSE(file_writer->HasPendingWrite());
939}
940
benwells26730592015-05-28 13:08:08941TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) {
942 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
943 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
944
945 // Set a lossy pref and check that it is not scheduled to be written.
ricea85ec57952016-08-31 09:34:10946 pref_store->SetValue("lossy", base::MakeUnique<base::StringValue>("lossy"),
benwells26730592015-05-28 13:08:08947 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
948 ASSERT_FALSE(file_writer->HasPendingWrite());
949
950 // Schedule pending lossy writes and check that it is scheduled.
951 pref_store->SchedulePendingLossyWrites();
952 ASSERT_TRUE(file_writer->HasPendingWrite());
953
954 // Call CommitPendingWrite and check that the lossy pref is there with the
955 // last value set above.
956 pref_store->CommitPendingWrite();
957 ASSERT_FALSE(file_writer->HasPendingWrite());
958 ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents());
959}
960
[email protected]7e3ec42c2012-12-16 05:13:21961} // namespace base