blob: 0164ad65880df13c5f5386334213ead478ee043c [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"
probergefc46ac12016-09-21 18:03:0029#include "base/threading/sequenced_task_runner_handle.h"
[email protected]0de615a2012-11-08 04:40:5930#include "base/threading/sequenced_worker_pool.h"
[email protected]34b99632011-01-01 01:01:0631#include "base/threading/thread.h"
[email protected]277404c22010-04-22 13:09:4532#include "base/values.h"
brettwf00b9b42016-02-01 22:11:3833#include "components/prefs/pref_filter.h"
[email protected]845b43a82011-05-11 10:14:4334#include "testing/gmock/include/gmock/gmock.h"
[email protected]277404c22010-04-22 13:09:4535#include "testing/gtest/include/gtest/gtest.h"
36
[email protected]7e3ec42c2012-12-16 05:13:2137namespace base {
[email protected]845b43a82011-05-11 10:14:4338namespace {
39
[email protected]5bfdcfd2012-11-22 22:08:2440const char kHomePage[] = "homepage";
41
brettw58cd1f12016-01-30 05:56:0542const char kReadJson[] =
43 "{\n"
44 " \"homepage\": \"http://www.cnn.com\",\n"
45 " \"some_directory\": \"/usr/local/\",\n"
46 " \"tabs\": {\n"
47 " \"new_windows_in_tabs\": true,\n"
48 " \"max_tabs\": 20\n"
49 " }\n"
50 "}";
51
52const char kInvalidJson[] = "!@#$%^&";
53
54// Expected output for tests using RunBasicJsonPrefStoreTest().
55const char kWriteGolden[] =
56 "{\"homepage\":\"http://www.cnn.com\","
57 "\"long_int\":{\"pref\":\"214748364842\"},"
58 "\"some_directory\":\"/usr/sbin/\","
59 "\"tabs\":{\"max_tabs\":10,\"new_windows_in_tabs\":false}}";
60
raymesbfb910a2015-04-29 07:43:0961// Set the time on the given SimpleTestClock to the given time in minutes.
62void SetCurrentTimeInMinutes(double minutes, base::SimpleTestClock* clock) {
63 const int32_t kBaseTimeMins = 100;
64 clock->SetNow(base::Time::FromDoubleT((kBaseTimeMins + minutes) * 60));
65}
66
[email protected]e33c9512014-05-12 02:24:1367// A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
68// to the |prefs| until explicitly asked to release them.
69class InterceptingPrefFilter : public PrefFilter {
70 public:
71 InterceptingPrefFilter();
probergec503d692016-09-28 19:51:0572 InterceptingPrefFilter(OnWriteCallbackPair callback_pair);
dcheng56488182014-10-21 10:54:5173 ~InterceptingPrefFilter() override;
[email protected]e33c9512014-05-12 02:24:1374
75 // PrefFilter implementation:
dcheng56488182014-10-21 10:54:5176 void FilterOnLoad(
[email protected]e33c9512014-05-12 02:24:1377 const PostFilterOnLoadCallback& post_filter_on_load_callback,
dcheng5f043bc2016-04-22 19:09:0678 std::unique_ptr<base::DictionaryValue> pref_store_contents) override;
dcheng56488182014-10-21 10:54:5179 void FilterUpdate(const std::string& path) override {}
probergec503d692016-09-28 19:51:0580 OnWriteCallbackPair FilterSerializeData(
81 base::DictionaryValue* pref_store_contents) override {
82 return on_write_callback_pair_;
83 }
[email protected]e33c9512014-05-12 02:24:1384
85 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
86
[email protected]cfcf0e52014-06-20 18:29:4787 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
[email protected]e33c9512014-05-12 02:24:1388 // JsonPrefStore.
89 void ReleasePrefs();
90
91 private:
92 PostFilterOnLoadCallback post_filter_on_load_callback_;
dcheng5f043bc2016-04-22 19:09:0693 std::unique_ptr<base::DictionaryValue> intercepted_prefs_;
probergec503d692016-09-28 19:51:0594 OnWriteCallbackPair on_write_callback_pair_;
[email protected]e33c9512014-05-12 02:24:1395
96 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter);
97};
98
99InterceptingPrefFilter::InterceptingPrefFilter() {}
probergec503d692016-09-28 19:51:05100
101InterceptingPrefFilter::InterceptingPrefFilter(
102 OnWriteCallbackPair callback_pair) {
103 on_write_callback_pair_ = callback_pair;
104}
105
[email protected]e33c9512014-05-12 02:24:13106InterceptingPrefFilter::~InterceptingPrefFilter() {}
107
108void InterceptingPrefFilter::FilterOnLoad(
109 const PostFilterOnLoadCallback& post_filter_on_load_callback,
dcheng5f043bc2016-04-22 19:09:06110 std::unique_ptr<base::DictionaryValue> pref_store_contents) {
[email protected]e33c9512014-05-12 02:24:13111 post_filter_on_load_callback_ = post_filter_on_load_callback;
danakj0c8d4aa2015-11-25 05:29:58112 intercepted_prefs_ = std::move(pref_store_contents);
[email protected]e33c9512014-05-12 02:24:13113}
114
115void InterceptingPrefFilter::ReleasePrefs() {
116 EXPECT_FALSE(post_filter_on_load_callback_.is_null());
danakj0c8d4aa2015-11-25 05:29:58117 post_filter_on_load_callback_.Run(std::move(intercepted_prefs_), false);
[email protected]e33c9512014-05-12 02:24:13118 post_filter_on_load_callback_.Reset();
119}
120
[email protected]845b43a82011-05-11 10:14:43121class MockPrefStoreObserver : public PrefStore::Observer {
122 public:
123 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
124 MOCK_METHOD1(OnInitializationCompleted, void (bool));
125};
126
127class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
128 public:
129 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
130};
131
132} // namespace
133
[email protected]277404c22010-04-22 13:09:45134class JsonPrefStoreTest : public testing::Test {
probergefc46ac12016-09-21 18:03:00135 public:
136 JsonPrefStoreTest() = default;
137
[email protected]277404c22010-04-22 13:09:45138 protected:
dcheng8aef37612014-12-23 02:56:47139 void SetUp() override {
[email protected]3a305db2011-04-12 13:40:53140 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]277404c22010-04-22 13:09:45141 }
142
dcheng8aef37612014-12-23 02:56:47143 void TearDown() override {
[email protected]e33c9512014-05-12 02:24:13144 // Make sure all pending tasks have been processed (e.g., deleting the
145 // JsonPrefStore may post write tasks).
raymes4b6e14e2015-05-12 00:10:30146 RunLoop().RunUntilIdle();
[email protected]e33c9512014-05-12 02:24:13147 }
148
[email protected]3a305db2011-04-12 13:40:53149 // The path to temporary directory used to contain the test operations.
[email protected]ea1a3f62012-11-16 20:34:23150 base::ScopedTempDir temp_dir_;
[email protected]ea587b02010-05-21 15:01:35151 // A message loop that we can use as the file thread message loop.
152 MessageLoop message_loop_;
probergefc46ac12016-09-21 18:03:00153
154 DISALLOW_COPY_AND_ASSIGN(JsonPrefStoreTest);
[email protected]277404c22010-04-22 13:09:45155};
156
157// Test fallback behavior for a nonexistent file.
158TEST_F(JsonPrefStoreTest, NonExistentFile) {
vabr8023d872016-09-15 08:12:22159 base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07160 ASSERT_FALSE(PathExists(bogus_input_file));
dcheng5f043bc2016-04-22 19:09:06161 scoped_refptr<JsonPrefStore> pref_store =
162 new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
163 std::unique_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17164 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
[email protected]9a8c4022011-01-25 14:25:33165 pref_store->ReadPrefs());
166 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45167}
168
[email protected]cfcf0e52014-06-20 18:29:47169// Test fallback behavior for a nonexistent file and alternate file.
170TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) {
vabr8023d872016-09-15 08:12:22171 base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
[email protected]cfcf0e52014-06-20 18:29:47172 base::FilePath bogus_alternate_input_file =
vabr8023d872016-09-15 08:12:22173 temp_dir_.GetPath().AppendASCII("read_alternate.txt");
[email protected]cfcf0e52014-06-20 18:29:47174 ASSERT_FALSE(PathExists(bogus_input_file));
175 ASSERT_FALSE(PathExists(bogus_alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06176 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
177 bogus_input_file, bogus_alternate_input_file, message_loop_.task_runner(),
178 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47179 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
180 pref_store->ReadPrefs());
181 EXPECT_FALSE(pref_store->ReadOnly());
182}
183
[email protected]277404c22010-04-22 13:09:45184// Test fallback behavior for an invalid file.
185TEST_F(JsonPrefStoreTest, InvalidFile) {
vabr8023d872016-09-15 08:12:22186 base::FilePath invalid_file = temp_dir_.GetPath().AppendASCII("invalid.json");
brettw58cd1f12016-01-30 05:56:05187 ASSERT_LT(0, base::WriteFile(invalid_file,
188 kInvalidJson, arraysize(kInvalidJson) - 1));
189
skyostil054861d2015-04-30 19:06:15190 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06191 invalid_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]f2d1f612010-12-09 15:10:17192 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
[email protected]9a8c4022011-01-25 14:25:33193 pref_store->ReadPrefs());
194 EXPECT_FALSE(pref_store->ReadOnly());
[email protected]277404c22010-04-22 13:09:45195
196 // The file should have been moved aside.
[email protected]7567484142013-07-11 17:36:07197 EXPECT_FALSE(PathExists(invalid_file));
vabr8023d872016-09-15 08:12:22198 base::FilePath moved_aside = temp_dir_.GetPath().AppendASCII("invalid.bad");
[email protected]7567484142013-07-11 17:36:07199 EXPECT_TRUE(PathExists(moved_aside));
brettw58cd1f12016-01-30 05:56:05200
201 std::string moved_aside_contents;
202 ASSERT_TRUE(base::ReadFileToString(moved_aside, &moved_aside_contents));
203 EXPECT_EQ(kInvalidJson, moved_aside_contents);
[email protected]277404c22010-04-22 13:09:45204}
205
brettw58cd1f12016-01-30 05:56:05206// This function is used to avoid code duplication while testing synchronous
207// and asynchronous version of the JsonPrefStore loading. It validates that the
208// given output file's contents matches kWriteGolden.
[email protected]0de615a2012-11-08 04:40:59209void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
brettw58cd1f12016-01-30 05:56:05210 const base::FilePath& output_file) {
[email protected]57ecc4b2010-08-11 03:02:51211 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
212 const char kMaxTabs[] = "tabs.max_tabs";
213 const char kLongIntPref[] = "long_int.pref";
[email protected]277404c22010-04-22 13:09:45214
[email protected]57ecc4b2010-08-11 03:02:51215 std::string cnn("http://www.cnn.com");
[email protected]277404c22010-04-22 13:09:45216
[email protected]68bf41a2011-03-25 16:38:31217 const Value* actual;
[email protected]5bfdcfd2012-11-22 22:08:24218 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
[email protected]57ecc4b2010-08-11 03:02:51219 std::string string_value;
[email protected]f2d1f612010-12-09 15:10:17220 EXPECT_TRUE(actual->GetAsString(&string_value));
[email protected]277404c22010-04-22 13:09:45221 EXPECT_EQ(cnn, string_value);
222
[email protected]57ecc4b2010-08-11 03:02:51223 const char kSomeDirectory[] = "some_directory";
[email protected]277404c22010-04-22 13:09:45224
[email protected]892f1d62012-11-08 18:24:34225 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]023ad6ab2013-02-17 05:07:23226 base::FilePath::StringType path;
[email protected]f2d1f612010-12-09 15:10:17227 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]023ad6ab2013-02-17 05:07:23228 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
229 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
[email protected]f2d1f612010-12-09 15:10:17230
estade0bd407f2015-06-26 18:16:18231 pref_store->SetValue(kSomeDirectory,
jdoerrie122c4da2017-03-06 11:12:04232 base::MakeUnique<Value>(some_path.value()),
raymes76de1af2015-05-06 03:22:21233 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34234 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
[email protected]f2d1f612010-12-09 15:10:17235 EXPECT_TRUE(actual->GetAsString(&path));
[email protected]277404c22010-04-22 13:09:45236 EXPECT_EQ(some_path.value(), path);
237
238 // Test reading some other data types from sub-dictionaries.
[email protected]892f1d62012-11-08 18:24:34239 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17240 bool boolean = false;
241 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45242 EXPECT_TRUE(boolean);
243
jdoerrie239723572017-03-02 12:09:19244 pref_store->SetValue(kNewWindowsInTabs, base::MakeUnique<Value>(false),
raymes76de1af2015-05-06 03:22:21245 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34246 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17247 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
[email protected]277404c22010-04-22 13:09:45248 EXPECT_FALSE(boolean);
249
[email protected]892f1d62012-11-08 18:24:34250 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17251 int integer = 0;
252 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45253 EXPECT_EQ(20, integer);
jdoerrie239723572017-03-02 12:09:19254 pref_store->SetValue(kMaxTabs, base::MakeUnique<Value>(10),
raymes76de1af2015-05-06 03:22:21255 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34256 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
[email protected]f2d1f612010-12-09 15:10:17257 EXPECT_TRUE(actual->GetAsInteger(&integer));
[email protected]277404c22010-04-22 13:09:45258 EXPECT_EQ(10, integer);
259
jdoerrie122c4da2017-03-06 11:12:04260 pref_store->SetValue(
261 kLongIntPref,
262 base::MakeUnique<Value>(base::Int64ToString(214748364842LL)),
263 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]892f1d62012-11-08 18:24:34264 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
[email protected]f2d1f612010-12-09 15:10:17265 EXPECT_TRUE(actual->GetAsString(&string_value));
avi9ef8bb02015-12-24 05:29:36266 int64_t value;
[email protected]57ecc4b2010-08-11 03:02:51267 base::StringToInt64(string_value, &value);
[email protected]e83326f2010-07-31 17:29:25268 EXPECT_EQ(214748364842LL, value);
[email protected]277404c22010-04-22 13:09:45269
270 // Serialize and compare to expected output.
[email protected]fbe17c8a2011-12-27 16:41:48271 pref_store->CommitPendingWrite();
[email protected]f7b98b32013-02-05 08:14:15272 RunLoop().RunUntilIdle();
brettw58cd1f12016-01-30 05:56:05273
274 std::string output_contents;
275 ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents));
276 EXPECT_EQ(kWriteGolden, output_contents);
[email protected]dd3aa792013-07-16 19:10:23277 ASSERT_TRUE(base::DeleteFile(output_file, false));
[email protected]277404c22010-04-22 13:09:45278}
[email protected]845b43a82011-05-11 10:14:43279
280TEST_F(JsonPrefStoreTest, Basic) {
vabr8023d872016-09-15 08:12:22281 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05282 ASSERT_LT(0, base::WriteFile(input_file,
283 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43284
285 // Test that the persistent value can be loaded.
[email protected]7567484142013-07-11 17:36:07286 ASSERT_TRUE(PathExists(input_file));
[email protected]56cbcb3a2013-12-23 21:24:46287 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06288 input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43289 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
[email protected]e33c9512014-05-12 02:24:13290 EXPECT_FALSE(pref_store->ReadOnly());
291 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]845b43a82011-05-11 10:14:43292
293 // The JSON file looks like this:
294 // {
295 // "homepage": "http://www.cnn.com",
296 // "some_directory": "/usr/local/",
297 // "tabs": {
298 // "new_windows_in_tabs": true,
299 // "max_tabs": 20
300 // }
301 // }
302
brettw58cd1f12016-01-30 05:56:05303 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43304}
305
306TEST_F(JsonPrefStoreTest, BasicAsync) {
vabr8023d872016-09-15 08:12:22307 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05308 ASSERT_LT(0, base::WriteFile(input_file,
309 kReadJson, arraysize(kReadJson) - 1));
[email protected]845b43a82011-05-11 10:14:43310
311 // Test that the persistent value can be loaded.
[email protected]56cbcb3a2013-12-23 21:24:46312 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06313 input_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43314
[email protected]0de615a2012-11-08 04:40:59315 {
316 MockPrefStoreObserver mock_observer;
317 pref_store->AddObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43318
[email protected]0de615a2012-11-08 04:40:59319 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
320 pref_store->ReadPrefsAsync(mock_error_delegate);
[email protected]845b43a82011-05-11 10:14:43321
[email protected]0de615a2012-11-08 04:40:59322 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
323 EXPECT_CALL(*mock_error_delegate,
324 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
[email protected]7ff48ca2013-02-06 16:56:19325 RunLoop().RunUntilIdle();
[email protected]0de615a2012-11-08 04:40:59326 pref_store->RemoveObserver(&mock_observer);
[email protected]845b43a82011-05-11 10:14:43327
[email protected]e33c9512014-05-12 02:24:13328 EXPECT_FALSE(pref_store->ReadOnly());
329 EXPECT_TRUE(pref_store->IsInitializationComplete());
[email protected]0de615a2012-11-08 04:40:59330 }
[email protected]845b43a82011-05-11 10:14:43331
332 // The JSON file looks like this:
333 // {
334 // "homepage": "http://www.cnn.com",
335 // "some_directory": "/usr/local/",
336 // "tabs": {
337 // "new_windows_in_tabs": true,
338 // "max_tabs": 20
339 // }
340 // }
341
brettw58cd1f12016-01-30 05:56:05342 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]845b43a82011-05-11 10:14:43343}
344
[email protected]aa3283392013-11-27 01:38:24345TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
vabr8023d872016-09-15 08:12:22346 FilePath pref_file = temp_dir_.GetPath().AppendASCII("empty_values.json");
[email protected]aa3283392013-11-27 01:38:24347
[email protected]56cbcb3a2013-12-23 21:24:46348 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06349 pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24350
351 // Set some keys with empty values.
dcheng5f043bc2016-04-22 19:09:06352 pref_store->SetValue("list", base::WrapUnique(new base::ListValue),
raymes76de1af2015-05-06 03:22:21353 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
dcheng5f043bc2016-04-22 19:09:06354 pref_store->SetValue("dict", base::WrapUnique(new base::DictionaryValue),
raymes76de1af2015-05-06 03:22:21355 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]aa3283392013-11-27 01:38:24356
357 // Write to file.
358 pref_store->CommitPendingWrite();
raymes4b6e14e2015-05-12 00:10:30359 RunLoop().RunUntilIdle();
[email protected]aa3283392013-11-27 01:38:24360
361 // Reload.
skyostil054861d2015-04-30 19:06:15362 pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
dcheng5f043bc2016-04-22 19:09:06363 std::unique_ptr<PrefFilter>());
[email protected]aa3283392013-11-27 01:38:24364 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
365 ASSERT_FALSE(pref_store->ReadOnly());
366
367 // Check values.
368 const Value* result = NULL;
369 EXPECT_TRUE(pref_store->GetValue("list", &result));
370 EXPECT_TRUE(ListValue().Equals(result));
371 EXPECT_TRUE(pref_store->GetValue("dict", &result));
372 EXPECT_TRUE(DictionaryValue().Equals(result));
373}
374
[email protected]eeedaa692014-01-30 09:22:27375// This test is just documenting some potentially non-obvious behavior. It
376// shouldn't be taken as normative.
377TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
vabr8023d872016-09-15 08:12:22378 FilePath pref_file = temp_dir_.GetPath().AppendASCII("empty_values.json");
[email protected]eeedaa692014-01-30 09:22:27379
380 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
dcheng5f043bc2016-04-22 19:09:06381 pref_file, message_loop_.task_runner(), std::unique_ptr<PrefFilter>());
[email protected]eeedaa692014-01-30 09:22:27382
dcheng5f043bc2016-04-22 19:09:06383 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
[email protected]eeedaa692014-01-30 09:22:27384 dict->SetString("key", "value");
danakj0c8d4aa2015-11-25 05:29:58385 pref_store->SetValue("dict", std::move(dict),
raymes76de1af2015-05-06 03:22:21386 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27387
raymes76de1af2015-05-06 03:22:21388 pref_store->RemoveValue("dict.key",
389 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
[email protected]eeedaa692014-01-30 09:22:27390
391 const base::Value* retrieved_dict = NULL;
392 bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
393 EXPECT_FALSE(has_dict);
394}
395
[email protected]845b43a82011-05-11 10:14:43396// Tests asynchronous reading of the file when there is no file.
397TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
vabr8023d872016-09-15 08:12:22398 base::FilePath bogus_input_file = temp_dir_.GetPath().AppendASCII("read.txt");
[email protected]7567484142013-07-11 17:36:07399 ASSERT_FALSE(PathExists(bogus_input_file));
dcheng5f043bc2016-04-22 19:09:06400 scoped_refptr<JsonPrefStore> pref_store =
401 new JsonPrefStore(bogus_input_file, message_loop_.task_runner(),
402 std::unique_ptr<PrefFilter>());
[email protected]845b43a82011-05-11 10:14:43403 MockPrefStoreObserver mock_observer;
404 pref_store->AddObserver(&mock_observer);
405
406 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
407 pref_store->ReadPrefsAsync(mock_error_delegate);
408
409 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
410 EXPECT_CALL(*mock_error_delegate,
411 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
[email protected]7ff48ca2013-02-06 16:56:19412 RunLoop().RunUntilIdle();
[email protected]845b43a82011-05-11 10:14:43413 pref_store->RemoveObserver(&mock_observer);
414
415 EXPECT_FALSE(pref_store->ReadOnly());
416}
[email protected]ea3e4972012-04-12 03:41:37417
[email protected]e33c9512014-05-12 02:24:13418TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
vabr8023d872016-09-15 08:12:22419 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05420 ASSERT_LT(0, base::WriteFile(input_file,
421 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13422
dcheng5f043bc2016-04-22 19:09:06423 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
[email protected]e33c9512014-05-12 02:24:13424 new InterceptingPrefFilter());
425 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
426 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58427 scoped_refptr<JsonPrefStore> pref_store =
428 new JsonPrefStore(input_file, message_loop_.task_runner(),
429 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13430
431 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
432 pref_store->ReadPrefs());
433 EXPECT_FALSE(pref_store->ReadOnly());
434
435 // The store shouldn't be considered initialized until the interceptor
436 // returns.
437 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
438 EXPECT_FALSE(pref_store->IsInitializationComplete());
439 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
440
441 raw_intercepting_pref_filter_->ReleasePrefs();
442
443 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
444 EXPECT_TRUE(pref_store->IsInitializationComplete());
445 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
446
447 // The JSON file looks like this:
448 // {
449 // "homepage": "http://www.cnn.com",
450 // "some_directory": "/usr/local/",
451 // "tabs": {
452 // "new_windows_in_tabs": true,
453 // "max_tabs": 20
454 // }
455 // }
456
brettw58cd1f12016-01-30 05:56:05457 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13458}
459
460TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
vabr8023d872016-09-15 08:12:22461 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05462 ASSERT_LT(0, base::WriteFile(input_file,
463 kReadJson, arraysize(kReadJson) - 1));
[email protected]e33c9512014-05-12 02:24:13464
dcheng5f043bc2016-04-22 19:09:06465 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
[email protected]e33c9512014-05-12 02:24:13466 new InterceptingPrefFilter());
467 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
468 intercepting_pref_filter.get();
danakj0c8d4aa2015-11-25 05:29:58469 scoped_refptr<JsonPrefStore> pref_store =
470 new JsonPrefStore(input_file, message_loop_.task_runner(),
471 std::move(intercepting_pref_filter));
[email protected]e33c9512014-05-12 02:24:13472
473 MockPrefStoreObserver mock_observer;
474 pref_store->AddObserver(&mock_observer);
475
476 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
477 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
478
479 {
480 pref_store->ReadPrefsAsync(mock_error_delegate);
481
482 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
483 // EXPECT_CALL(*mock_error_delegate,
484 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
485 RunLoop().RunUntilIdle();
486
487 EXPECT_FALSE(pref_store->ReadOnly());
488 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
489 EXPECT_FALSE(pref_store->IsInitializationComplete());
490 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
491 }
492
493 {
494 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
495 // EXPECT_CALL(*mock_error_delegate,
496 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
497
498 raw_intercepting_pref_filter_->ReleasePrefs();
499
500 EXPECT_FALSE(pref_store->ReadOnly());
501 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
502 EXPECT_TRUE(pref_store->IsInitializationComplete());
503 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
504 }
505
506 pref_store->RemoveObserver(&mock_observer);
507
508 // The JSON file looks like this:
509 // {
510 // "homepage": "http://www.cnn.com",
511 // "some_directory": "/usr/local/",
512 // "tabs": {
513 // "new_windows_in_tabs": true,
514 // "max_tabs": 20
515 // }
516 // }
517
brettw58cd1f12016-01-30 05:56:05518 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]e33c9512014-05-12 02:24:13519}
520
[email protected]cfcf0e52014-06-20 18:29:47521TEST_F(JsonPrefStoreTest, AlternateFile) {
brettw58cd1f12016-01-30 05:56:05522 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22523 temp_dir_.GetPath().AppendASCII("alternate.json");
brettw58cd1f12016-01-30 05:56:05524 ASSERT_LT(0, base::WriteFile(alternate_input_file,
525 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47526
527 // Test that the alternate file is moved to the main file and read as-is from
528 // there.
vabr8023d872016-09-15 08:12:22529 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
[email protected]cfcf0e52014-06-20 18:29:47530 ASSERT_FALSE(PathExists(input_file));
531 ASSERT_TRUE(PathExists(alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06532 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
533 input_file, alternate_input_file, message_loop_.task_runner(),
534 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47535
536 ASSERT_FALSE(PathExists(input_file));
537 ASSERT_TRUE(PathExists(alternate_input_file));
538 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
539
540 ASSERT_TRUE(PathExists(input_file));
541 ASSERT_FALSE(PathExists(alternate_input_file));
542
543 EXPECT_FALSE(pref_store->ReadOnly());
544 EXPECT_TRUE(pref_store->IsInitializationComplete());
545
546 // The JSON file looks like this:
547 // {
548 // "homepage": "http://www.cnn.com",
549 // "some_directory": "/usr/local/",
550 // "tabs": {
551 // "new_windows_in_tabs": true,
552 // "max_tabs": 20
553 // }
554 // }
555
brettw58cd1f12016-01-30 05:56:05556 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47557}
558
559TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
vabr8023d872016-09-15 08:12:22560 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05561 ASSERT_LT(0, base::WriteFile(input_file,
562 kReadJson, arraysize(kReadJson) - 1));
563
564 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22565 temp_dir_.GetPath().AppendASCII("alternate.json");
brettw58cd1f12016-01-30 05:56:05566 ASSERT_LT(0, base::WriteFile(alternate_input_file,
567 kInvalidJson, arraysize(kInvalidJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47568
569 // Test that the alternate file is ignored and that the read occurs from the
570 // existing main file. There is no attempt at even deleting the alternate
571 // file as this scenario should never happen in normal user-data-dirs.
dcheng5f043bc2016-04-22 19:09:06572 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
573 input_file, alternate_input_file, message_loop_.task_runner(),
574 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47575
576 ASSERT_TRUE(PathExists(input_file));
577 ASSERT_TRUE(PathExists(alternate_input_file));
578 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
579
580 ASSERT_TRUE(PathExists(input_file));
581 ASSERT_TRUE(PathExists(alternate_input_file));
582
583 EXPECT_FALSE(pref_store->ReadOnly());
584 EXPECT_TRUE(pref_store->IsInitializationComplete());
585
586 // The JSON file looks like this:
587 // {
588 // "homepage": "http://www.cnn.com",
589 // "some_directory": "/usr/local/",
590 // "tabs": {
591 // "new_windows_in_tabs": true,
592 // "max_tabs": 20
593 // }
594 // }
595
brettw58cd1f12016-01-30 05:56:05596 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47597}
598
599TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
vabr8023d872016-09-15 08:12:22600 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
brettw58cd1f12016-01-30 05:56:05601 ASSERT_LT(0, base::WriteFile(input_file,
602 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47603
604 // Test that the basic read works fine when an alternate file is specified but
605 // does not exist.
[email protected]cfcf0e52014-06-20 18:29:47606 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22607 temp_dir_.GetPath().AppendASCII("alternate.json");
[email protected]cfcf0e52014-06-20 18:29:47608 ASSERT_TRUE(PathExists(input_file));
609 ASSERT_FALSE(PathExists(alternate_input_file));
dcheng5f043bc2016-04-22 19:09:06610 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
611 input_file, alternate_input_file, message_loop_.task_runner(),
612 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47613
614 ASSERT_TRUE(PathExists(input_file));
615 ASSERT_FALSE(PathExists(alternate_input_file));
616 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
617
618 ASSERT_TRUE(PathExists(input_file));
619 ASSERT_FALSE(PathExists(alternate_input_file));
620
621 EXPECT_FALSE(pref_store->ReadOnly());
622 EXPECT_TRUE(pref_store->IsInitializationComplete());
623
624 // The JSON file looks like this:
625 // {
626 // "homepage": "http://www.cnn.com",
627 // "some_directory": "/usr/local/",
628 // "tabs": {
629 // "new_windows_in_tabs": true,
630 // "max_tabs": 20
631 // }
632 // }
633
brettw58cd1f12016-01-30 05:56:05634 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47635}
636
637TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
brettw58cd1f12016-01-30 05:56:05638 base::FilePath alternate_input_file =
vabr8023d872016-09-15 08:12:22639 temp_dir_.GetPath().AppendASCII("alternate.json");
brettw58cd1f12016-01-30 05:56:05640 ASSERT_LT(0, base::WriteFile(alternate_input_file,
641 kReadJson, arraysize(kReadJson) - 1));
[email protected]cfcf0e52014-06-20 18:29:47642
643 // Test that the alternate file is moved to the main file and read as-is from
644 // there even when the read is made asynchronously.
vabr8023d872016-09-15 08:12:22645 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
dcheng5f043bc2016-04-22 19:09:06646 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
647 input_file, alternate_input_file, message_loop_.task_runner(),
648 std::unique_ptr<PrefFilter>());
[email protected]cfcf0e52014-06-20 18:29:47649
650 ASSERT_FALSE(PathExists(input_file));
651 ASSERT_TRUE(PathExists(alternate_input_file));
652
653 {
654 MockPrefStoreObserver mock_observer;
655 pref_store->AddObserver(&mock_observer);
656
657 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
658 pref_store->ReadPrefsAsync(mock_error_delegate);
659
660 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
661 EXPECT_CALL(*mock_error_delegate,
662 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
663 RunLoop().RunUntilIdle();
664 pref_store->RemoveObserver(&mock_observer);
665
666 EXPECT_FALSE(pref_store->ReadOnly());
667 EXPECT_TRUE(pref_store->IsInitializationComplete());
668 }
669
670 ASSERT_TRUE(PathExists(input_file));
671 ASSERT_FALSE(PathExists(alternate_input_file));
672
673 // The JSON file looks like this:
674 // {
675 // "homepage": "http://www.cnn.com",
676 // "some_directory": "/usr/local/",
677 // "tabs": {
678 // "new_windows_in_tabs": true,
679 // "max_tabs": 20
680 // }
681 // }
682
brettw58cd1f12016-01-30 05:56:05683 RunBasicJsonPrefStoreTest(pref_store.get(), input_file);
[email protected]cfcf0e52014-06-20 18:29:47684}
685
raymesbfb910a2015-04-29 07:43:09686TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
brettw58cd1f12016-01-30 05:56:05687 base::HistogramTester histogram_tester;
688
raymesbfb910a2015-04-29 07:43:09689 SimpleTestClock* test_clock = new SimpleTestClock;
690 SetCurrentTimeInMinutes(0, test_clock);
691 JsonPrefStore::WriteCountHistogram histogram(
692 base::TimeDelta::FromSeconds(10),
693 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06694 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36695 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09696 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
697
698 histogram.RecordWriteOccured();
699
700 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
701 histogram.ReportOutstandingWrites();
dcheng5f043bc2016-04-22 19:09:06702 std::unique_ptr<HistogramSamples> samples =
raymesbfb910a2015-04-29 07:43:09703 histogram.GetHistogram()->SnapshotSamples();
brettw58cd1f12016-01-30 05:56:05704
705 std::string histogram_name = histogram.GetHistogram()->histogram_name();
706 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
707 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09708
709 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State",
710 histogram.GetHistogram()->histogram_name());
711 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31));
712}
713
714TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) {
brettw58cd1f12016-01-30 05:56:05715 base::HistogramTester histogram_tester;
716
raymesbfb910a2015-04-29 07:43:09717 SimpleTestClock* test_clock = new SimpleTestClock;
718 SetCurrentTimeInMinutes(0, test_clock);
719 JsonPrefStore::WriteCountHistogram histogram(
720 base::TimeDelta::FromSeconds(10),
721 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06722 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36723 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09724 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
725
726 histogram.RecordWriteOccured();
727 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
728 histogram.RecordWriteOccured();
729 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
730 histogram.RecordWriteOccured();
731
732 // Nothing should be recorded until the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05733 std::string histogram_name = histogram.GetHistogram()->histogram_name();
734 histogram_tester.ExpectTotalCount(histogram_name, 0);
raymesbfb910a2015-04-29 07:43:09735
736 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
737 histogram.RecordWriteOccured();
738
739 // Now the report period has elapsed.
brettw58cd1f12016-01-30 05:56:05740 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
741 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09742
743 // The last write won't be recorded because the second count period hasn't
744 // fully elapsed.
745 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
746 histogram.ReportOutstandingWrites();
747
brettw58cd1f12016-01-30 05:56:05748 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
749 histogram_tester.ExpectTotalCount(histogram_name, 1);
raymesbfb910a2015-04-29 07:43:09750}
751
752TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) {
brettw58cd1f12016-01-30 05:56:05753 base::HistogramTester histogram_tester;
754
raymesbfb910a2015-04-29 07:43:09755 SimpleTestClock* test_clock = new SimpleTestClock;
756 SetCurrentTimeInMinutes(0, test_clock);
757 JsonPrefStore::WriteCountHistogram histogram(
758 base::TimeDelta::FromSeconds(10),
759 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06760 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36761 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09762 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
763
764 histogram.RecordWriteOccured();
765 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
766 histogram.RecordWriteOccured();
767 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
768 histogram.RecordWriteOccured();
769 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
770 histogram.RecordWriteOccured();
771 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
772 histogram.RecordWriteOccured();
773 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock);
774 histogram.RecordWriteOccured();
775 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock);
776 histogram.RecordWriteOccured();
777 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock);
778 histogram.RecordWriteOccured();
779 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
780 histogram.RecordWriteOccured();
781
782 // The last write won't be recorded because the second count period hasn't
783 // fully elapsed
784 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock);
785 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05786 std::string histogram_name = histogram.GetHistogram()->histogram_name();
787 histogram_tester.ExpectBucketCount(histogram_name, 3, 2);
788 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
789 histogram_tester.ExpectTotalCount(histogram_name, 3);
raymesbfb910a2015-04-29 07:43:09790}
791
792TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) {
brettw58cd1f12016-01-30 05:56:05793 base::HistogramTester histogram_tester;
794
raymesbfb910a2015-04-29 07:43:09795 SimpleTestClock* test_clock = new SimpleTestClock;
796 SetCurrentTimeInMinutes(0, test_clock);
797 JsonPrefStore::WriteCountHistogram histogram(
798 base::TimeDelta::FromSeconds(10),
799 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
dcheng5f043bc2016-04-22 19:09:06800 std::unique_ptr<base::Clock>(test_clock));
avi9ef8bb02015-12-24 05:29:36801 int32_t report_interval =
raymesbfb910a2015-04-29 07:43:09802 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
803
804 // 1 write in the first period.
805 histogram.RecordWriteOccured();
806
807 // No writes in the second and third periods.
808
809 // 2 writes in the fourth period.
810 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock);
811 histogram.RecordWriteOccured();
812 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
813 histogram.RecordWriteOccured();
814
815 // No writes in the fifth period.
816
817 // 3 writes in the sixth period.
818 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock);
819 histogram.RecordWriteOccured();
820 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock);
821 histogram.RecordWriteOccured();
822 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock);
823 histogram.RecordWriteOccured();
824
825 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock);
826 histogram.ReportOutstandingWrites();
brettw58cd1f12016-01-30 05:56:05827 std::string histogram_name = histogram.GetHistogram()->histogram_name();
828 histogram_tester.ExpectBucketCount(histogram_name, 0, 3);
829 histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
830 histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
831 histogram_tester.ExpectBucketCount(histogram_name, 3, 1);
832 histogram_tester.ExpectTotalCount(histogram_name, 6);
raymesbfb910a2015-04-29 07:43:09833}
834
raymes4b6e14e2015-05-12 00:10:30835class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
probergefc46ac12016-09-21 18:03:00836 public:
837 JsonPrefStoreLossyWriteTest() = default;
838
raymes4b6e14e2015-05-12 00:10:30839 protected:
840 void SetUp() override {
841 JsonPrefStoreTest::SetUp();
vabr8023d872016-09-15 08:12:22842 test_file_ = temp_dir_.GetPath().AppendASCII("test.json");
raymes4b6e14e2015-05-12 00:10:30843 }
844
raymes4b6e14e2015-05-12 00:10:30845 scoped_refptr<JsonPrefStore> CreatePrefStore() {
846 return new JsonPrefStore(test_file_, message_loop_.task_runner(),
dcheng5f043bc2016-04-22 19:09:06847 std::unique_ptr<PrefFilter>());
raymes4b6e14e2015-05-12 00:10:30848 }
849
850 // Return the ImportantFileWriter for a given JsonPrefStore.
probergefc46ac12016-09-21 18:03:00851 ImportantFileWriter* GetImportantFileWriter(JsonPrefStore* pref_store) {
raymes4b6e14e2015-05-12 00:10:30852 return &(pref_store->writer_);
853 }
854
855 // Get the contents of kTestFile. Pumps the message loop before returning the
856 // result.
857 std::string GetTestFileContents() {
858 RunLoop().RunUntilIdle();
859 std::string file_contents;
860 ReadFileToString(test_file_, &file_contents);
861 return file_contents;
862 }
863
864 private:
865 base::FilePath test_file_;
probergefc46ac12016-09-21 18:03:00866
867 DISALLOW_COPY_AND_ASSIGN(JsonPrefStoreLossyWriteTest);
raymes4b6e14e2015-05-12 00:10:30868};
869
870TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) {
871 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
probergefc46ac12016-09-21 18:03:00872 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
raymes4b6e14e2015-05-12 00:10:30873
874 // Set a normal pref and check that it gets scheduled to be written.
875 ASSERT_FALSE(file_writer->HasPendingWrite());
jdoerrie122c4da2017-03-06 11:12:04876 pref_store->SetValue("normal", base::MakeUnique<base::Value>("normal"),
raymes4b6e14e2015-05-12 00:10:30877 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
878 ASSERT_TRUE(file_writer->HasPendingWrite());
879 file_writer->DoScheduledWrite();
880 ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents());
881 ASSERT_FALSE(file_writer->HasPendingWrite());
882
883 // Set a lossy pref and check that it is not scheduled to be written.
884 // SetValue/RemoveValue.
jdoerrie122c4da2017-03-06 11:12:04885 pref_store->SetValue("lossy", base::MakeUnique<base::Value>("lossy"),
raymes4b6e14e2015-05-12 00:10:30886 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
887 ASSERT_FALSE(file_writer->HasPendingWrite());
888 pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
889 ASSERT_FALSE(file_writer->HasPendingWrite());
890
891 // SetValueSilently/RemoveValueSilently.
jdoerrie122c4da2017-03-06 11:12:04892 pref_store->SetValueSilently("lossy", base::MakeUnique<base::Value>("lossy"),
raymes4b6e14e2015-05-12 00:10:30893 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
894 ASSERT_FALSE(file_writer->HasPendingWrite());
895 pref_store->RemoveValueSilently("lossy",
896 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
897 ASSERT_FALSE(file_writer->HasPendingWrite());
898
899 // ReportValueChanged.
jdoerrie122c4da2017-03-06 11:12:04900 pref_store->SetValue("lossy", base::MakeUnique<base::Value>("lossy"),
raymes4b6e14e2015-05-12 00:10:30901 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
902 ASSERT_FALSE(file_writer->HasPendingWrite());
903 pref_store->ReportValueChanged("lossy",
904 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
905 ASSERT_FALSE(file_writer->HasPendingWrite());
906
907 // Call CommitPendingWrite and check that the lossy pref and the normal pref
908 // are there with the last values set above.
909 pref_store->CommitPendingWrite();
910 ASSERT_FALSE(file_writer->HasPendingWrite());
911 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
912 GetTestFileContents());
913}
914
915TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) {
916 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
probergefc46ac12016-09-21 18:03:00917 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
raymes4b6e14e2015-05-12 00:10:30918
919 // Set a lossy pref and check that it is not scheduled to be written.
920 ASSERT_FALSE(file_writer->HasPendingWrite());
jdoerrie122c4da2017-03-06 11:12:04921 pref_store->SetValue("lossy", base::MakeUnique<base::Value>("lossy"),
raymes4b6e14e2015-05-12 00:10:30922 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
923 ASSERT_FALSE(file_writer->HasPendingWrite());
924
925 // Set a normal pref and check that it is scheduled to be written.
jdoerrie122c4da2017-03-06 11:12:04926 pref_store->SetValue("normal", base::MakeUnique<base::Value>("normal"),
raymes4b6e14e2015-05-12 00:10:30927 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
928 ASSERT_TRUE(file_writer->HasPendingWrite());
929
930 // Call DoScheduledWrite and check both prefs get written.
931 file_writer->DoScheduledWrite();
932 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
933 GetTestFileContents());
934 ASSERT_FALSE(file_writer->HasPendingWrite());
935}
936
937TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) {
938 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
probergefc46ac12016-09-21 18:03:00939 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
raymes4b6e14e2015-05-12 00:10:30940
941 // Set a normal pref and check that it is scheduled to be written.
942 ASSERT_FALSE(file_writer->HasPendingWrite());
jdoerrie122c4da2017-03-06 11:12:04943 pref_store->SetValue("normal", base::MakeUnique<base::Value>("normal"),
raymes4b6e14e2015-05-12 00:10:30944 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
945 ASSERT_TRUE(file_writer->HasPendingWrite());
946
947 // Set a lossy pref and check that the write is still scheduled.
jdoerrie122c4da2017-03-06 11:12:04948 pref_store->SetValue("lossy", base::MakeUnique<base::Value>("lossy"),
raymes4b6e14e2015-05-12 00:10:30949 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
950 ASSERT_TRUE(file_writer->HasPendingWrite());
951
952 // Call DoScheduledWrite and check both prefs get written.
953 file_writer->DoScheduledWrite();
954 ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
955 GetTestFileContents());
956 ASSERT_FALSE(file_writer->HasPendingWrite());
957}
958
benwells26730592015-05-28 13:08:08959TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) {
960 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
probergefc46ac12016-09-21 18:03:00961 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
benwells26730592015-05-28 13:08:08962
963 // Set a lossy pref and check that it is not scheduled to be written.
jdoerrie122c4da2017-03-06 11:12:04964 pref_store->SetValue("lossy", base::MakeUnique<base::Value>("lossy"),
benwells26730592015-05-28 13:08:08965 WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
966 ASSERT_FALSE(file_writer->HasPendingWrite());
967
968 // Schedule pending lossy writes and check that it is scheduled.
969 pref_store->SchedulePendingLossyWrites();
970 ASSERT_TRUE(file_writer->HasPendingWrite());
971
972 // Call CommitPendingWrite and check that the lossy pref is there with the
973 // last value set above.
974 pref_store->CommitPendingWrite();
975 ASSERT_FALSE(file_writer->HasPendingWrite());
976 ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents());
977}
978
probergefc46ac12016-09-21 18:03:00979class SuccessfulWriteReplyObserver {
980 public:
981 SuccessfulWriteReplyObserver() = default;
982
983 // Returns true if a successful write was observed via on_successful_write()
984 // and resets the observation state to false regardless.
985 bool GetAndResetObservationState() {
986 bool was_successful_write_observed = successful_write_reply_observed_;
987 successful_write_reply_observed_ = false;
988 return was_successful_write_observed;
989 }
990
991 // Register OnWrite() to be called on the next write of |json_pref_store|.
992 void ObserveNextWriteCallback(JsonPrefStore* json_pref_store);
993
994 void OnSuccessfulWrite() {
995 EXPECT_FALSE(successful_write_reply_observed_);
996 successful_write_reply_observed_ = true;
997 }
998
999 private:
1000 bool successful_write_reply_observed_ = false;
1001
1002 DISALLOW_COPY_AND_ASSIGN(SuccessfulWriteReplyObserver);
1003};
1004
1005void SuccessfulWriteReplyObserver::ObserveNextWriteCallback(
1006 JsonPrefStore* json_pref_store) {
1007 json_pref_store->RegisterOnNextSuccessfulWriteReply(
1008 base::Bind(&SuccessfulWriteReplyObserver::OnSuccessfulWrite,
1009 base::Unretained(this)));
1010}
1011
1012enum WriteCallbackObservationState {
1013 NOT_CALLED,
1014 CALLED_WITH_ERROR,
1015 CALLED_WITH_SUCCESS,
1016};
1017
probergec503d692016-09-28 19:51:051018class WriteCallbacksObserver {
probergefc46ac12016-09-21 18:03:001019 public:
probergec503d692016-09-28 19:51:051020 WriteCallbacksObserver() = default;
probergefc46ac12016-09-21 18:03:001021
1022 // Register OnWrite() to be called on the next write of |json_pref_store|.
1023 void ObserveNextWriteCallback(JsonPrefStore* json_pref_store);
1024
probergec503d692016-09-28 19:51:051025 // Returns whether OnPreWrite() was called, and resets the observation state
1026 // to false.
1027 bool GetAndResetPreWriteObservationState();
probergefc46ac12016-09-21 18:03:001028
probergec503d692016-09-28 19:51:051029 // Returns the |WriteCallbackObservationState| which was observed, then resets
1030 // it to |NOT_CALLED|.
1031 WriteCallbackObservationState GetAndResetPostWriteObservationState();
1032
1033 JsonPrefStore::OnWriteCallbackPair GetCallbackPair() {
1034 return std::make_pair(
1035 base::Bind(&WriteCallbacksObserver::OnPreWrite, base::Unretained(this)),
1036 base::Bind(&WriteCallbacksObserver::OnPostWrite,
1037 base::Unretained(this)));
1038 }
1039
1040 void OnPreWrite() {
1041 EXPECT_FALSE(pre_write_called_);
1042 pre_write_called_ = true;
1043 }
1044
1045 void OnPostWrite(bool success) {
1046 EXPECT_EQ(NOT_CALLED, post_write_observation_state_);
1047 post_write_observation_state_ =
1048 success ? CALLED_WITH_SUCCESS : CALLED_WITH_ERROR;
probergefc46ac12016-09-21 18:03:001049 }
1050
1051 private:
probergec503d692016-09-28 19:51:051052 bool pre_write_called_ = false;
1053 WriteCallbackObservationState post_write_observation_state_ = NOT_CALLED;
probergefc46ac12016-09-21 18:03:001054
probergec503d692016-09-28 19:51:051055 DISALLOW_COPY_AND_ASSIGN(WriteCallbacksObserver);
probergefc46ac12016-09-21 18:03:001056};
1057
probergec503d692016-09-28 19:51:051058void WriteCallbacksObserver::ObserveNextWriteCallback(JsonPrefStore* writer) {
1059 writer->RegisterOnNextWriteSynchronousCallbacks(GetCallbackPair());
1060}
1061
1062bool WriteCallbacksObserver::GetAndResetPreWriteObservationState() {
1063 bool observation_state = pre_write_called_;
1064 pre_write_called_ = false;
1065 return observation_state;
probergefc46ac12016-09-21 18:03:001066}
1067
1068WriteCallbackObservationState
probergec503d692016-09-28 19:51:051069WriteCallbacksObserver::GetAndResetPostWriteObservationState() {
1070 WriteCallbackObservationState state = post_write_observation_state_;
1071 pre_write_called_ = false;
1072 post_write_observation_state_ = NOT_CALLED;
probergefc46ac12016-09-21 18:03:001073 return state;
1074}
1075
1076class JsonPrefStoreCallbackTest : public JsonPrefStoreTest {
1077 public:
1078 JsonPrefStoreCallbackTest() = default;
1079
1080 protected:
1081 void SetUp() override {
1082 JsonPrefStoreTest::SetUp();
vabr5d919d62016-09-30 08:55:361083 test_file_ = temp_dir_.GetPath().AppendASCII("test.json");
probergefc46ac12016-09-21 18:03:001084 }
1085
1086 scoped_refptr<JsonPrefStore> CreatePrefStore() {
1087 return new JsonPrefStore(test_file_, message_loop_.task_runner(),
1088 std::unique_ptr<PrefFilter>());
1089 }
1090
1091 // Return the ImportantFileWriter for a given JsonPrefStore.
1092 ImportantFileWriter* GetImportantFileWriter(JsonPrefStore* pref_store) {
1093 return &(pref_store->writer_);
1094 }
1095
1096 void TriggerFakeWriteForCallback(JsonPrefStore* pref_store, bool success) {
1097 JsonPrefStore::PostWriteCallback(
1098 base::Bind(&JsonPrefStore::RunOrScheduleNextSuccessfulWriteCallback,
1099 pref_store->AsWeakPtr()),
probergec503d692016-09-28 19:51:051100 base::Bind(&WriteCallbacksObserver::OnPostWrite,
probergefc46ac12016-09-21 18:03:001101 base::Unretained(&write_callback_observer_)),
1102 base::SequencedTaskRunnerHandle::Get(), success);
1103 }
1104
1105 SuccessfulWriteReplyObserver successful_write_reply_observer_;
probergec503d692016-09-28 19:51:051106 WriteCallbacksObserver write_callback_observer_;
probergefc46ac12016-09-21 18:03:001107
1108 private:
1109 base::FilePath test_file_;
1110
1111 DISALLOW_COPY_AND_ASSIGN(JsonPrefStoreCallbackTest);
1112};
1113
probergec503d692016-09-28 19:51:051114TEST_F(JsonPrefStoreCallbackTest, TestSerializeDataCallbacks) {
1115 base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json");
1116 ASSERT_LT(0,
1117 base::WriteFile(input_file, kReadJson, arraysize(kReadJson) - 1));
1118
1119 std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter(
1120 new InterceptingPrefFilter(write_callback_observer_.GetCallbackPair()));
1121 scoped_refptr<JsonPrefStore> pref_store =
1122 new JsonPrefStore(input_file, message_loop_.task_runner(),
1123 std::move(intercepting_pref_filter));
1124 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
1125
1126 EXPECT_EQ(NOT_CALLED,
1127 write_callback_observer_.GetAndResetPostWriteObservationState());
jdoerrie122c4da2017-03-06 11:12:041128 pref_store->SetValue("normal", base::MakeUnique<base::Value>("normal"),
probergec503d692016-09-28 19:51:051129 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
1130 file_writer->DoScheduledWrite();
1131
1132 // The observer should not be invoked right away.
1133 EXPECT_FALSE(write_callback_observer_.GetAndResetPreWriteObservationState());
1134 EXPECT_EQ(NOT_CALLED,
1135 write_callback_observer_.GetAndResetPostWriteObservationState());
1136
1137 RunLoop().RunUntilIdle();
1138
1139 EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
1140 EXPECT_EQ(CALLED_WITH_SUCCESS,
1141 write_callback_observer_.GetAndResetPostWriteObservationState());
1142}
1143
1144TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacks) {
probergefc46ac12016-09-21 18:03:001145 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
1146 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
1147
probergec503d692016-09-28 19:51:051148 // Test RegisterOnNextWriteSynchronousCallbacks after
probergefc46ac12016-09-21 18:03:001149 // RegisterOnNextSuccessfulWriteReply.
1150 successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
1151 write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
1152 file_writer->WriteNow(MakeUnique<std::string>("foo"));
1153 RunLoop().RunUntilIdle();
1154 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051155 EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
1156 EXPECT_EQ(CALLED_WITH_SUCCESS,
1157 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001158
1159 // Test RegisterOnNextSuccessfulWriteReply after
probergec503d692016-09-28 19:51:051160 // RegisterOnNextWriteSynchronousCallbacks.
probergefc46ac12016-09-21 18:03:001161 successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
1162 write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
1163 file_writer->WriteNow(MakeUnique<std::string>("foo"));
1164 RunLoop().RunUntilIdle();
1165 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051166 EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
1167 EXPECT_EQ(CALLED_WITH_SUCCESS,
1168 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001169
1170 // Test RegisterOnNextSuccessfulWriteReply only.
1171 successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
1172 file_writer->WriteNow(MakeUnique<std::string>("foo"));
1173 RunLoop().RunUntilIdle();
1174 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051175 EXPECT_FALSE(write_callback_observer_.GetAndResetPreWriteObservationState());
1176 EXPECT_EQ(NOT_CALLED,
1177 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001178
probergec503d692016-09-28 19:51:051179 // Test RegisterOnNextWriteSynchronousCallbacks only.
probergefc46ac12016-09-21 18:03:001180 write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
1181 file_writer->WriteNow(MakeUnique<std::string>("foo"));
1182 RunLoop().RunUntilIdle();
1183 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051184 EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
1185 EXPECT_EQ(CALLED_WITH_SUCCESS,
1186 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001187}
1188
probergec503d692016-09-28 19:51:051189TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksWithFakeFailure) {
probergefc46ac12016-09-21 18:03:001190 scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
1191
1192 // Confirm that the observers are invoked.
1193 successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
1194 TriggerFakeWriteForCallback(pref_store.get(), true);
1195 RunLoop().RunUntilIdle();
1196 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
1197 EXPECT_EQ(CALLED_WITH_SUCCESS,
probergec503d692016-09-28 19:51:051198 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001199
1200 // Confirm that the observation states were reset.
1201 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051202 EXPECT_EQ(NOT_CALLED,
1203 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001204
1205 // Confirm that re-installing the observers works for another write.
1206 successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
1207 TriggerFakeWriteForCallback(pref_store.get(), true);
1208 RunLoop().RunUntilIdle();
1209 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
1210 EXPECT_EQ(CALLED_WITH_SUCCESS,
probergec503d692016-09-28 19:51:051211 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001212
1213 // Confirm that the successful observer is not invoked by an unsuccessful
1214 // write, and that the synchronous observer is invoked.
1215 successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
1216 TriggerFakeWriteForCallback(pref_store.get(), false);
1217 RunLoop().RunUntilIdle();
1218 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
1219 EXPECT_EQ(CALLED_WITH_ERROR,
probergec503d692016-09-28 19:51:051220 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001221
1222 // Do a real write, and confirm that the successful observer was invoked after
1223 // being set by |PostWriteCallback| by the last TriggerFakeWriteCallback.
1224 ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
1225 file_writer->WriteNow(MakeUnique<std::string>("foo"));
1226 RunLoop().RunUntilIdle();
1227 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051228 EXPECT_EQ(NOT_CALLED,
1229 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001230}
1231
probergec503d692016-09-28 19:51:051232TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksDuringProfileDeath) {
probergefc46ac12016-09-21 18:03:001233 // Create a JsonPrefStore and attach observers to it, then delete it by making
1234 // it go out of scope to simulate profile switch or Chrome shutdown.
1235 {
1236 scoped_refptr<JsonPrefStore> soon_out_of_scope_pref_store =
1237 CreatePrefStore();
1238 ImportantFileWriter* file_writer =
1239 GetImportantFileWriter(soon_out_of_scope_pref_store.get());
1240 successful_write_reply_observer_.ObserveNextWriteCallback(
1241 soon_out_of_scope_pref_store.get());
1242 write_callback_observer_.ObserveNextWriteCallback(
1243 soon_out_of_scope_pref_store.get());
1244 file_writer->WriteNow(MakeUnique<std::string>("foo"));
1245 }
1246 RunLoop().RunUntilIdle();
1247 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
probergec503d692016-09-28 19:51:051248 EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
probergefc46ac12016-09-21 18:03:001249 EXPECT_EQ(CALLED_WITH_SUCCESS,
probergec503d692016-09-28 19:51:051250 write_callback_observer_.GetAndResetPostWriteObservationState());
probergefc46ac12016-09-21 18:03:001251}
1252
vabr5d919d62016-09-30 08:55:361253} // namespace base