blob: 18299e24ddb6995820258a994ea7233f3272ba15 [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) {
raymes4b6e14e2015-05-12 00:10:30143 base::FilePath bogus_input_file = temp_dir_.path().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) {
raymes4b6e14e2015-05-12 00:10:30155 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]cfcf0e52014-06-20 18:29:47156 base::FilePath bogus_alternate_input_file =
raymes4b6e14e2015-05-12 00:10:30157 temp_dir_.path().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) {
[email protected]023ad6ab2013-02-17 05:07:23170 base::FilePath invalid_file = temp_dir_.path().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));
[email protected]023ad6ab2013-02-17 05:07:23182 base::FilePath moved_aside = temp_dir_.path().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,
dcheng5f043bc2016-04-22 19:09:06216 base::WrapUnique(new 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,
dcheng5f043bc2016-04-22 19:09:06229 base::WrapUnique(new 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);
dcheng5f043bc2016-04-22 19:09:06239 pref_store->SetValue(kMaxTabs, base::WrapUnique(new 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
estade0bd407f2015-06-26 18:16:18245 pref_store->SetValue(
246 kLongIntPref,
dcheng5f043bc2016-04-22 19:09:06247 base::WrapUnique(new StringValue(base::Int64ToString(214748364842LL))),
estade0bd407f2015-06-26 18:16:18248 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34249 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
[email protected]f2d1f612010-12-09 15:10:17250 EXPECT_TRUE(actual->GetAsString(&string_value));
avi9ef8bb02015-12-24 05:29:36251 int64_t value;
[email protected]57ecc4b2010-08-11 03:02:51252 base::StringToInt64(string_value, &value);
[email protected]e83326f2010-07-31 17:29:25253 EXPECT_EQ(214748364842LL, value);
[email protected]277404c22010-04-22 13:09:45254
255 // Serialize and compare to expected output.
[email protected]fbe17c8a2011-12-27 16:41:48256 pref_store->CommitPendingWrite();
[email protected]f7b98b32013-02-05 08:14:15257 RunLoop().RunUntilIdle();
brettw58cd1f12016-01-30 05:56:05258
259 std::string output_contents;
260 ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents));
261 EXPECT_EQ(kWriteGolden, output_contents);
[email protected]dd3aa792013-07-16 19:10:23262 ASSERT_TRUE(base::DeleteFile(output_file, false));
[email protected]277404c22010-04-22 13:09:45263}
[email protected]845b43a82011-05-11 10:14:43264
265TEST_F(JsonPrefStoreTest, Basic) {
brettw58cd1f12016-01-30 05:56:05266 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
267 ASSERT_LT(0, base::WriteFile(input_file,
268 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43269
270 // Test that the persistent value can be loaded.
[email protected]7567484142013-07-11 17:36:07271 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46272 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06273 input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43274 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
[email protected]e33c9512014-05-12 02:24:13275 EXPECT_FALSE(pref_store->ReadOnly());
276 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]845b43a82011-05-11 10:14:43277
278 // The JSON file looks like this:
279 // {
280 // "homepage": "http://www.cnn.com",
281 // "some_directory": "/usr/local/",
282 // "tabs": {
283 // "new_windows_in_tabs": true,
284 // "max_tabs": 20
285 // }
286 // }
287
brettw58cd1f12016-01-30 05:56:05288 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43289}
290
291TEST_F(JsonPrefStoreTest, BasicAsync) {
brettw58cd1f12016-01-30 05:56:05292 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
293 ASSERT_LT(0, base::WriteFile(input_file,
294 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43295
296 // Test that the persistent value can be loaded.
[email protected]56cbcb3a2013-12-23 21:24:46297 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06298 input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43299
[email protected]0de615a2012-11-08 04:40:59300 {
301 MockPrefStoreObserver mock_observer;
302 pref_store->AddObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43303
[email protected]0de615a2012-11-08 04:40:59304 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
305 pref_store->ReadPrefsAsync(mock_error_delegate);
[email protected]845b43a82011-05-11 10:14:43306
[email protected]0de615a2012-11-08 04:40:59307 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
308 EXPECT_CALL(*mock_error_delegate,
309 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
[email protected]7ff48ca2013-02-06 16:56:19310 RunLoop().RunUntilIdle();
[email protected]0de615a2012-11-08 04:40:59311 pref_store->RemoveObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43312
[email protected]e33c9512014-05-12 02:24:13313 EXPECT_FALSE(pref_store->ReadOnly());
314 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]0de615a2012-11-08 04:40:59315 }
[email protected]845b43a82011-05-11 10:14:43316
317 // The JSON file looks like this:
318 // {
319 // "homepage": "http://www.cnn.com",
320 // "some_directory": "/usr/local/",
321 // "tabs": {
322 // "new_windows_in_tabs": true,
323 // "max_tabs": 20
324 // }
325 // }
326
brettw58cd1f12016-01-30 05:56:05327 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43328}
329
[email protected]aa3283392013-11-27 01:38:24330TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
331 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
332
[email protected]56cbcb3a2013-12-23 21:24:46333 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06334 pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24335
336 // Set some keys with empty values.
dcheng5f043bc2016-04-22 19:09:06337 pref_store->SetValue("list", base::WrapUnique(new base::ListValue),
raymes76de1af2015-05-06 03:22:21338 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
dcheng5f043bc2016-04-22 19:09:06339 pref_store->SetValue("dict", base::WrapUnique(new base::DictionaryValue),
raymes76de1af2015-05-06 03:22:21340 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]aa3283392013-11-27 01:38:24341
342 // Write to file.
343 pref_store->CommitPendingWrite();
raymes4b6e14e2015-05-12 00:10:30344 RunLoop().RunUntilIdle();
[email protected]aa3283392013-11-27 01:38:24345
346 // Reload.
skyostil054861d2015-04-30 19:06:15347 pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
dcheng5f043bc2016-04-22 19:09:06348 std::unique_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24349 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
350 ASSERT_FALSE(pref_store->ReadOnly());
351
352 // Check values.
353 const Value* result = NULL;
354 EXPECT_TRUE(pref_store->GetValue("list", &result));
355 EXPECT_TRUE(ListValue().Equals(result));
356 EXPECT_TRUE(pref_store->GetValue("dict", &result));
357 EXPECT_TRUE(DictionaryValue().Equals(result));
358}
359
[email protected]eeedaa692014-01-30 09:22:27360// This test is just documenting some potentially non-obvious behavior. It
361// shouldn't be taken as normative.
362TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
363 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
364
365 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06366 pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]eeedaa692014-01-30 09:22:27367
dcheng5f043bc2016-04-22 19:09:06368 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
[email protected]eeedaa692014-01-30 09:22:27369 dict->SetString("key", "value");
danakj0c8d4aa2015-11-25 05:29:58370 pref_store->SetValue("dict", std::move(dict),
raymes76de1af2015-05-06 03:22:21371 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27372
raymes76de1af2015-05-06 03:22:21373 pref_store->RemoveValue("dict.key",
374 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27375
376 const base::Value* retrieved_dict = NULL;
377 bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
378 EXPECT_FALSE(has_dict);
379}
380
[email protected]845b43a82011-05-11 10:14:43381// Tests asynchronous reading of the file when there is no file.
382TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
raymes4b6e14e2015-05-12 00:10:30383 base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07384 ASSERT_FALSE(PathExists(bogus_input_file));
dcheng5f043bc2016-04-22 19:09:06385 scoped_refptr<JsonPrefStore> pref_store =
386 new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
387 std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43388 MockPrefStoreObserver mock_observer;
389 pref_store->AddObserver(&mock_observer);
390
391 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
392 pref_store->ReadPrefsAsync(mock_error_delegate);
393
394 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
395 EXPECT_CALL(*mock_error_delegate,
396 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
[email protected]7ff48ca2013-02-06 16:56:19397 RunLoop().RunUntilIdle();
[email protected]845b43a82011-05-11 10:14:43398 pref_store->RemoveObserver(&mock_observer);
399
400 EXPECT_FALSE(pref_store->ReadOnly());
401}
[email protected]ea3e4972012-04-12 03:41:37402
[email protected]e33c9512014-05-12 02:24:13403TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
[email protected]e33c9512014-05-12 02:24:13404 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05405 ASSERT_LT(0, base::WriteFile(input_file,
406 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13407
dcheng5f043bc2016-04-22 19:09:06408 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
[email protected]e33c9512014-05-12 02:24:13409 new InterceptingPrefFilter());
410 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
411 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58412 scoped_refptr<JsonPrefStore> pref_store =
413 new JsonPrefStore(input_file, message_loop_.task_runner(),
414 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13415
416 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
417 pref_store->ReadPrefs());
418 EXPECT_FALSE(pref_store->ReadOnly());
419
420 // The store shouldn't be considered initialized until the interceptor
421 // returns.
422 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
423 EXPECT_FALSE(pref_store->IsInitializationComplete());
424 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
425
426 raw_intercepting_pref_filter_->ReleasePrefs();
427
428 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
429 EXPECT_TRUE(pref_store->IsInitializationComplete());
430 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
431
432 // The JSON file looks like this:
433 // {
434 // "homepage": "http://www.cnn.com",
435 // "some_directory": "/usr/local/",
436 // "tabs": {
437 // "new_windows_in_tabs": true,
438 // "max_tabs": 20
439 // }
440 // }
441
brettw58cd1f12016-01-30 05:56:05442 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13443}
444
445TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
[email protected]e33c9512014-05-12 02:24:13446 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05447 ASSERT_LT(0, base::WriteFile(input_file,
448 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13449
dcheng5f043bc2016-04-22 19:09:06450 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
[email protected]e33c9512014-05-12 02:24:13451 new InterceptingPrefFilter());
452 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
453 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58454 scoped_refptr<JsonPrefStore> pref_store =
455 new JsonPrefStore(input_file, message_loop_.task_runner(),
456 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13457
458 MockPrefStoreObserver mock_observer;
459 pref_store->AddObserver(&mock_observer);
460
461 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
462 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
463
464 {
465 pref_store->ReadPrefsAsync(mock_error_delegate);
466
467 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
468 // EXPECT_CALL(*mock_error_delegate,
469 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
470 RunLoop().RunUntilIdle();
471
472 EXPECT_FALSE(pref_store->ReadOnly());
473 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
474 EXPECT_FALSE(pref_store->IsInitializationComplete());
475 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
476 }
477
478 {
479 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
480 // EXPECT_CALL(*mock_error_delegate,
481 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
482
483 raw_intercepting_pref_filter_->ReleasePrefs();
484
485 EXPECT_FALSE(pref_store->ReadOnly());
486 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
487 EXPECT_TRUE(pref_store->IsInitializationComplete());
488 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
489 }
490
491 pref_store->RemoveObserver(&mock_observer);
492
493 // The JSON file looks like this:
494 // {
495 // "homepage": "http://www.cnn.com",
496 // "some_directory": "/usr/local/",
497 // "tabs": {
498 // "new_windows_in_tabs": true,
499 // "max_tabs": 20
500 // }
501 // }
502
brettw58cd1f12016-01-30 05:56:05503 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13504}
505
[email protected]cfcf0e52014-06-20 18:29:47506TEST_F(JsonPrefStoreTest, AlternateFile) {
brettw58cd1f12016-01-30 05:56:05507 base::FilePath alternate_input_file =
508 temp_dir_.path().AppendASCII("alternate.json");
509 ASSERT_LT(0, base::WriteFile(alternate_input_file,
510 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47511
512 // Test that the alternate file is moved to the main file and read as-is from
513 // there.
514 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
[email protected]cfcf0e52014-06-20 18:29:47515 ASSERT_FALSE(PathExists(input_file));
516 ASSERT_TRUE(PathExists(alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06517 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
518 input_file, alternate_input_file, message_loop_.task_runner(),
519 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47520
521 ASSERT_FALSE(PathExists(input_file));
522 ASSERT_TRUE(PathExists(alternate_input_file));
523 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
524
525 ASSERT_TRUE(PathExists(input_file));
526 ASSERT_FALSE(PathExists(alternate_input_file));
527
528 EXPECT_FALSE(pref_store->ReadOnly());
529 EXPECT_TRUE(pref_store->IsInitializationComplete());
530
531 // The JSON file looks like this:
532 // {
533 // "homepage": "http://www.cnn.com",
534 // "some_directory": "/usr/local/",
535 // "tabs": {
536 // "new_windows_in_tabs": true,
537 // "max_tabs": 20
538 // }
539 // }
540
brettw58cd1f12016-01-30 05:56:05541 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47542}
543
544TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
brettw58cd1f12016-01-30 05:56:05545 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
546 ASSERT_LT(0, base::WriteFile(input_file,
547 kReadJson, arraysize(kReadJson) - 1));
548
549 base::FilePath alternate_input_file =
550 temp_dir_.path().AppendASCII("alternate.json");
551 ASSERT_LT(0, base::WriteFile(alternate_input_file,
552 kInvalidJson, arraysize(kInvalidJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47553
554 // Test that the alternate file is ignored and that the read occurs from the
555 // existing main file. There is no attempt at even deleting the alternate
556 // file as this scenario should never happen in normal user-data-dirs.
dcheng5f043bc2016-04-22 19:09:06557 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
558 input_file, alternate_input_file, message_loop_.task_runner(),
559 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47560
561 ASSERT_TRUE(PathExists(input_file));
562 ASSERT_TRUE(PathExists(alternate_input_file));
563 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
564
565 ASSERT_TRUE(PathExists(input_file));
566 ASSERT_TRUE(PathExists(alternate_input_file));
567
568 EXPECT_FALSE(pref_store->ReadOnly());
569 EXPECT_TRUE(pref_store->IsInitializationComplete());
570
571 // The JSON file looks like this:
572 // {
573 // "homepage": "http://www.cnn.com",
574 // "some_directory": "/usr/local/",
575 // "tabs": {
576 // "new_windows_in_tabs": true,
577 // "max_tabs": 20
578 // }
579 // }
580
brettw58cd1f12016-01-30 05:56:05581 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47582}
583
584TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
brettw58cd1f12016-01-30 05:56:05585 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
586 ASSERT_LT(0, base::WriteFile(input_file,
587 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47588
589 // Test that the basic read works fine when an alternate file is specified but
590 // does not exist.
[email protected]cfcf0e52014-06-20 18:29:47591 base::FilePath alternate_input_file =
592 temp_dir_.path().AppendASCII("alternate.json");
593 ASSERT_TRUE(PathExists(input_file));
594 ASSERT_FALSE(PathExists(alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06595 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
596 input_file, alternate_input_file, message_loop_.task_runner(),
597 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47598
599 ASSERT_TRUE(PathExists(input_file));
600 ASSERT_FALSE(PathExists(alternate_input_file));
601 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
602
603 ASSERT_TRUE(PathExists(input_file));
604 ASSERT_FALSE(PathExists(alternate_input_file));
605
606 EXPECT_FALSE(pref_store->ReadOnly());
607 EXPECT_TRUE(pref_store->IsInitializationComplete());
608
609 // The JSON file looks like this:
610 // {
611 // "homepage": "http://www.cnn.com",
612 // "some_directory": "/usr/local/",
613 // "tabs": {
614 // "new_windows_in_tabs": true,
615 // "max_tabs": 20
616 // }
617 // }
618
brettw58cd1f12016-01-30 05:56:05619 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47620}
621
622TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
brettw58cd1f12016-01-30 05:56:05623 base::FilePath alternate_input_file =
624 temp_dir_.path().AppendASCII("alternate.json");
625 ASSERT_LT(0, base::WriteFile(alternate_input_file,
626 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47627
628 // Test that the alternate file is moved to the main file and read as-is from
629 // there even when the read is made asynchronously.
630 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
dcheng5f043bc2016-04-22 19:09:06631 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
632 input_file, alternate_input_file, message_loop_.task_runner(),
633 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47634
635 ASSERT_FALSE(PathExists(input_file));
636 ASSERT_TRUE(PathExists(alternate_input_file));
637
638 {
639 MockPrefStoreObserver mock_observer;
640 pref_store->AddObserver(&mock_observer);
641
642 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
643 pref_store->ReadPrefsAsync(mock_error_delegate);
644
645 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
646 EXPECT_CALL(*mock_error_delegate,
647 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
648 RunLoop().RunUntilIdle();
649 pref_store->RemoveObserver(&mock_observer);
650
651 EXPECT_FALSE(pref_store->ReadOnly());
652 EXPECT_TRUE(pref_store->IsInitializationComplete());
653 }
654
655 ASSERT_TRUE(PathExists(input_file));
656 ASSERT_FALSE(PathExists(alternate_input_file));
657
658 // The JSON file looks like this:
659 // {
660 // "homepage": "http://www.cnn.com",
661 // "some_directory": "/usr/local/",
662 // "tabs": {
663 // "new_windows_in_tabs": true,
664 // "max_tabs": 20
665 // }
666 // }
667
brettw58cd1f12016-01-30 05:56:05668 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47669}
670
raymesbfb910a2015-04-29 07:43:09671TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
brettw58cd1f12016-01-30 05:56:05672 base::HistogramTester histogram_tester;
673
raymesbfb910a2015-04-29 07:43:09674 SimpleTestClock* test_clock = new SimpleTestClock;
675 SetCurrentTimeInMinutes(0, test_clock);
676 JsonPrefStore::WriteCountHistogram histogram(
677 base::TimeDelta::FromSeconds(10),
678 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06679 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36680 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09681 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
682
683 histogram.RecordWriteOccured();
684
685 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
686 histogram.ReportOutstandingWrites();
dcheng5f043bc2016-04-22 19:09:06687 std::unique_ptr<HistogramSamples> samples =
raymesbfb910a2015-04-29 07:43:09688 histogram.GetHistogram()->SnapshotSamples();
brettw58cd1f12016-01-30 05:56:05689
690 std::string histogram_name = histogram.GetHistogram()->histogram_name();
691 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
692 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09693
694 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State",
695 histogram.GetHistogram()->histogram_name());
696 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31));
697}
698
699TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) {
brettw58cd1f12016-01-30 05:56:05700 base::HistogramTester histogram_tester;
701
raymesbfb910a2015-04-29 07:43:09702 SimpleTestClock* test_clock = new SimpleTestClock;
703 SetCurrentTimeInMinutes(0, test_clock);
704 JsonPrefStore::WriteCountHistogram histogram(
705 base::TimeDelta::FromSeconds(10),
706 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06707 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36708 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09709 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
710
711 histogram.RecordWriteOccured();
712 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
713 histogram.RecordWriteOccured();
714 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
715 histogram.RecordWriteOccured();
716
717 // Nothing should be recorded until the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05718 std::string histogram_name = histogram.GetHistogram()->histogram_name();
719 histogram_tester.ExpectTotalCount(histogram_name, 0);
raymesbfb910a2015-04-29 07:43:09720
721 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
722 histogram.RecordWriteOccured();
723
724 // Now the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05725 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
726 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09727
728 // The last write won't be recorded because the second count period hasn't
729 // fully elapsed.
730 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
731 histogram.ReportOutstandingWrites();
732
brettw58cd1f12016-01-30 05:56:05733 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
734 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09735}
736
737TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) {
brettw58cd1f12016-01-30 05:56:05738 base::HistogramTester histogram_tester;
739
raymesbfb910a2015-04-29 07:43:09740 SimpleTestClock* test_clock = new SimpleTestClock;
741 SetCurrentTimeInMinutes(0, test_clock);
742 JsonPrefStore::WriteCountHistogram histogram(
743 base::TimeDelta::FromSeconds(10),
744 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06745 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36746 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09747 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
748
749 histogram.RecordWriteOccured();
750 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
751 histogram.RecordWriteOccured();
752 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
753 histogram.RecordWriteOccured();
754 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
755 histogram.RecordWriteOccured();
756 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
757 histogram.RecordWriteOccured();
758 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock);
759 histogram.RecordWriteOccured();
760 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock);
761 histogram.RecordWriteOccured();
762 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock);
763 histogram.RecordWriteOccured();
764 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
765 histogram.RecordWriteOccured();
766
767 // The last write won't be recorded because the second count period hasn't
768 // fully elapsed
769 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock);
770 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05771 std::string histogram_name = histogram.GetHistogram()->histogram_name();
772 histogram_tester.ExpectBucketCount(histogram_name, 3, 2);
773 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
774 histogram_tester.ExpectTotalCount(histogram_name, 3);
raymesbfb910a2015-04-29 07:43:09775}
776
777TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) {
brettw58cd1f12016-01-30 05:56:05778 base::HistogramTester histogram_tester;
779
raymesbfb910a2015-04-29 07:43:09780 SimpleTestClock* test_clock = new SimpleTestClock;
781 SetCurrentTimeInMinutes(0, test_clock);
782 JsonPrefStore::WriteCountHistogram histogram(
783 base::TimeDelta::FromSeconds(10),
784 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06785 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36786 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09787 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
788
789 // 1 write in the first period.
790 histogram.RecordWriteOccured();
791
792 // No writes in the second and third periods.
793
794 // 2 writes in the fourth period.
795 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock);
796 histogram.RecordWriteOccured();
797 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
798 histogram.RecordWriteOccured();
799
800 // No writes in the fifth period.
801
802 // 3 writes in the sixth period.
803 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock);
804 histogram.RecordWriteOccured();
805 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock);
806 histogram.RecordWriteOccured();
807 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock);
808 histogram.RecordWriteOccured();
809
810 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock);
811 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05812 std::string histogram_name = histogram.GetHistogram()->histogram_name();
813 histogram_tester.ExpectBucketCount(histogram_name, 0, 3);
814 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
815 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
816 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
817 histogram_tester.ExpectTotalCount(histogram_name, 6);
raymesbfb910a2015-04-29 07:43:09818}
819
raymes4b6e14e2015-05-12 00:10:30820class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
821 protected:
822 void SetUp() override {
823 JsonPrefStoreTest::SetUp();
824 test_file_ = temp_dir_.path().AppendASCII("test.json");
825 }
826
827 // Creates a JsonPrefStore with the given |file_writer|.
828 scoped_refptr<JsonPrefStore> CreatePrefStore() {
829 return new JsonPrefStore(test_file_, message_loop_.task_runner(),
dcheng5f043bc2016-04-22 19:09:06830 std::unique_ptr<PrefFilter>());
raymes4b6e14e2015-05-12 00:10:30831 }
832
833 // Return the ImportantFileWriter for a given JsonPrefStore.
834 ImportantFileWriter* GetImportantFileWriter(
835 scoped_refptr<JsonPrefStore> pref_store) {
836 return &(pref_store->writer_);
837 }
838
839 // Get the contents of kTestFile. Pumps the message loop before returning the
840 // result.
841 std::string GetTestFileContents() {
842 RunLoop().RunUntilIdle();
843 std::string file_contents;
844 ReadFileToString(test_file_, &file_contents);
845 return file_contents;
846 }
847
848 private:
849 base::FilePath test_file_;
850};
851
852TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) {
853 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
854 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
855
856 // Set a normal pref and check that it gets scheduled to be written.
857 ASSERT_FALSE(file_writer->HasPendingWrite());
estade0bd407f2015-06-26 18:16:18858 pref_store->SetValue("normal",
dcheng5f043bc2016-04-22 19:09:06859 base::WrapUnique(new base::StringValue("normal")),
raymes4b6e14e2015-05-12 00:10:30860 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
861 ASSERT_TRUE(file_writer->HasPendingWrite());
862 file_writer->DoScheduledWrite();
863 ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents());
864 ASSERT_FALSE(file_writer->HasPendingWrite());
865
866 // Set a lossy pref and check that it is not scheduled to be written.
867 // SetValue/RemoveValue.
dcheng5f043bc2016-04-22 19:09:06868 pref_store->SetValue("lossy",
869 base::WrapUnique(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30870 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
871 ASSERT_FALSE(file_writer->HasPendingWrite());
872 pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
873 ASSERT_FALSE(file_writer->HasPendingWrite());
874
875 // SetValueSilently/RemoveValueSilently.
estade0bd407f2015-06-26 18:16:18876 pref_store->SetValueSilently("lossy",
dcheng5f043bc2016-04-22 19:09:06877 base::WrapUnique(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30878 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
879 ASSERT_FALSE(file_writer->HasPendingWrite());
880 pref_store->RemoveValueSilently("lossy",
881 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
882 ASSERT_FALSE(file_writer->HasPendingWrite());
883
884 // ReportValueChanged.
dcheng5f043bc2016-04-22 19:09:06885 pref_store->SetValue("lossy",
886 base::WrapUnique(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30887 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
888 ASSERT_FALSE(file_writer->HasPendingWrite());
889 pref_store->ReportValueChanged("lossy",
890 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
891 ASSERT_FALSE(file_writer->HasPendingWrite());
892
893 // Call CommitPendingWrite and check that the lossy pref and the normal pref
894 // are there with the last values set above.
895 pref_store->CommitPendingWrite();
896 ASSERT_FALSE(file_writer->HasPendingWrite());
897 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
898 GetTestFileContents());
899}
900
901TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) {
902 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
903 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
904
905 // Set a lossy pref and check that it is not scheduled to be written.
906 ASSERT_FALSE(file_writer->HasPendingWrite());
dcheng5f043bc2016-04-22 19:09:06907 pref_store->SetValue("lossy",
908 base::WrapUnique(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30909 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
910 ASSERT_FALSE(file_writer->HasPendingWrite());
911
912 // Set a normal pref and check that it is scheduled to be written.
estade0bd407f2015-06-26 18:16:18913 pref_store->SetValue("normal",
dcheng5f043bc2016-04-22 19:09:06914 base::WrapUnique(new base::StringValue("normal")),
raymes4b6e14e2015-05-12 00:10:30915 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
916 ASSERT_TRUE(file_writer->HasPendingWrite());
917
918 // Call DoScheduledWrite and check both prefs get written.
919 file_writer->DoScheduledWrite();
920 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
921 GetTestFileContents());
922 ASSERT_FALSE(file_writer->HasPendingWrite());
923}
924
925TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) {
926 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
927 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
928
929 // Set a normal pref and check that it is scheduled to be written.
930 ASSERT_FALSE(file_writer->HasPendingWrite());
estade0bd407f2015-06-26 18:16:18931 pref_store->SetValue("normal",
dcheng5f043bc2016-04-22 19:09:06932 base::WrapUnique(new base::StringValue("normal")),
raymes4b6e14e2015-05-12 00:10:30933 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
934 ASSERT_TRUE(file_writer->HasPendingWrite());
935
936 // Set a lossy pref and check that the write is still scheduled.
dcheng5f043bc2016-04-22 19:09:06937 pref_store->SetValue("lossy",
938 base::WrapUnique(new base::StringValue("lossy")),
raymes4b6e14e2015-05-12 00:10:30939 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
940 ASSERT_TRUE(file_writer->HasPendingWrite());
941
942 // Call DoScheduledWrite and check both prefs get written.
943 file_writer->DoScheduledWrite();
944 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
945 GetTestFileContents());
946 ASSERT_FALSE(file_writer->HasPendingWrite());
947}
948
benwells26730592015-05-28 13:08:08949TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) {
950 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
951 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
952
953 // Set a lossy pref and check that it is not scheduled to be written.
dcheng5f043bc2016-04-22 19:09:06954 pref_store->SetValue("lossy",
955 base::WrapUnique(new base::StringValue("lossy")),
benwells26730592015-05-28 13:08:08956 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
957 ASSERT_FALSE(file_writer->HasPendingWrite());
958
959 // Schedule pending lossy writes and check that it is scheduled.
960 pref_store->SchedulePendingLossyWrites();
961 ASSERT_TRUE(file_writer->HasPendingWrite());
962
963 // Call CommitPendingWrite and check that the lossy pref is there with the
964 // last value set above.
965 pref_store->CommitPendingWrite();
966 ASSERT_FALSE(file_writer->HasPendingWrite());
967 ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents());
968}
969
[email protected]7e3ec42c2012-12-16 05:13:21970} // namespace base