Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / base / prefs / json_pref_store_unittest.cc
blob746c72bda8a51ea46a196a9330405c60cdc455cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/prefs/json_pref_store.h"
7 #include "base/bind.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram_samples.h"
14 #include "base/metrics/statistics_recorder.h"
15 #include "base/path_service.h"
16 #include "base/prefs/pref_filter.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/simple_test_clock.h"
22 #include "base/threading/sequenced_worker_pool.h"
23 #include "base/threading/thread.h"
24 #include "base/values.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace base {
29 namespace {
31 const char kHomePage[] = "homepage";
33 // Set the time on the given SimpleTestClock to the given time in minutes.
34 void SetCurrentTimeInMinutes(double minutes, base::SimpleTestClock* clock) {
35 const int32_t kBaseTimeMins = 100;
36 clock->SetNow(base::Time::FromDoubleT((kBaseTimeMins + minutes) * 60));
39 // A PrefFilter that will intercept all calls to FilterOnLoad() and hold on
40 // to the |prefs| until explicitly asked to release them.
41 class InterceptingPrefFilter : public PrefFilter {
42 public:
43 InterceptingPrefFilter();
44 ~InterceptingPrefFilter() override;
46 // PrefFilter implementation:
47 void FilterOnLoad(
48 const PostFilterOnLoadCallback& post_filter_on_load_callback,
49 scoped_ptr<base::DictionaryValue> pref_store_contents) override;
50 void FilterUpdate(const std::string& path) override {}
51 void FilterSerializeData(
52 base::DictionaryValue* pref_store_contents) override {}
54 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
56 // Finalize an intercepted read, handing |intercepted_prefs_| back to its
57 // JsonPrefStore.
58 void ReleasePrefs();
60 private:
61 PostFilterOnLoadCallback post_filter_on_load_callback_;
62 scoped_ptr<base::DictionaryValue> intercepted_prefs_;
64 DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter);
67 InterceptingPrefFilter::InterceptingPrefFilter() {}
68 InterceptingPrefFilter::~InterceptingPrefFilter() {}
70 void InterceptingPrefFilter::FilterOnLoad(
71 const PostFilterOnLoadCallback& post_filter_on_load_callback,
72 scoped_ptr<base::DictionaryValue> pref_store_contents) {
73 post_filter_on_load_callback_ = post_filter_on_load_callback;
74 intercepted_prefs_ = pref_store_contents.Pass();
77 void InterceptingPrefFilter::ReleasePrefs() {
78 EXPECT_FALSE(post_filter_on_load_callback_.is_null());
79 post_filter_on_load_callback_.Run(intercepted_prefs_.Pass(), false);
80 post_filter_on_load_callback_.Reset();
83 class MockPrefStoreObserver : public PrefStore::Observer {
84 public:
85 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
86 MOCK_METHOD1(OnInitializationCompleted, void (bool));
89 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
90 public:
91 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
94 } // namespace
96 class JsonPrefStoreTest : public testing::Test {
97 protected:
98 void SetUp() override {
99 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
101 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_));
102 data_dir_ = data_dir_.AppendASCII("prefs");
103 ASSERT_TRUE(PathExists(data_dir_));
106 void TearDown() override {
107 // Make sure all pending tasks have been processed (e.g., deleting the
108 // JsonPrefStore may post write tasks).
109 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure());
110 message_loop_.Run();
113 // The path to temporary directory used to contain the test operations.
114 base::ScopedTempDir temp_dir_;
115 // The path to the directory where the test data is stored.
116 base::FilePath data_dir_;
117 // A message loop that we can use as the file thread message loop.
118 MessageLoop message_loop_;
120 private:
121 // Ensure histograms are reset for each test.
122 StatisticsRecorder statistics_recorder_;
125 // Test fallback behavior for a nonexistent file.
126 TEST_F(JsonPrefStoreTest, NonExistentFile) {
127 base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
128 ASSERT_FALSE(PathExists(bogus_input_file));
129 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
130 bogus_input_file,
131 message_loop_.message_loop_proxy().get(),
132 scoped_ptr<PrefFilter>());
133 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
134 pref_store->ReadPrefs());
135 EXPECT_FALSE(pref_store->ReadOnly());
138 // Test fallback behavior for a nonexistent file and alternate file.
139 TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) {
140 base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
141 base::FilePath bogus_alternate_input_file =
142 data_dir_.AppendASCII("read_alternate.txt");
143 ASSERT_FALSE(PathExists(bogus_input_file));
144 ASSERT_FALSE(PathExists(bogus_alternate_input_file));
145 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
146 bogus_input_file,
147 bogus_alternate_input_file,
148 message_loop_.message_loop_proxy().get(),
149 scoped_ptr<PrefFilter>());
150 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
151 pref_store->ReadPrefs());
152 EXPECT_FALSE(pref_store->ReadOnly());
155 // Test fallback behavior for an invalid file.
156 TEST_F(JsonPrefStoreTest, InvalidFile) {
157 base::FilePath invalid_file_original = data_dir_.AppendASCII("invalid.json");
158 base::FilePath invalid_file = temp_dir_.path().AppendASCII("invalid.json");
159 ASSERT_TRUE(base::CopyFile(invalid_file_original, invalid_file));
160 scoped_refptr<JsonPrefStore> pref_store =
161 new JsonPrefStore(invalid_file,
162 message_loop_.message_loop_proxy().get(),
163 scoped_ptr<PrefFilter>());
164 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
165 pref_store->ReadPrefs());
166 EXPECT_FALSE(pref_store->ReadOnly());
168 // The file should have been moved aside.
169 EXPECT_FALSE(PathExists(invalid_file));
170 base::FilePath moved_aside = temp_dir_.path().AppendASCII("invalid.bad");
171 EXPECT_TRUE(PathExists(moved_aside));
172 EXPECT_TRUE(TextContentsEqual(invalid_file_original, moved_aside));
175 // This function is used to avoid code duplication while testing synchronous and
176 // asynchronous version of the JsonPrefStore loading.
177 void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
178 const base::FilePath& output_file,
179 const base::FilePath& golden_output_file) {
180 const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
181 const char kMaxTabs[] = "tabs.max_tabs";
182 const char kLongIntPref[] = "long_int.pref";
184 std::string cnn("http://www.cnn.com");
186 const Value* actual;
187 EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
188 std::string string_value;
189 EXPECT_TRUE(actual->GetAsString(&string_value));
190 EXPECT_EQ(cnn, string_value);
192 const char kSomeDirectory[] = "some_directory";
194 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
195 base::FilePath::StringType path;
196 EXPECT_TRUE(actual->GetAsString(&path));
197 EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
198 base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
200 pref_store->SetValue(kSomeDirectory, new StringValue(some_path.value()));
201 EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
202 EXPECT_TRUE(actual->GetAsString(&path));
203 EXPECT_EQ(some_path.value(), path);
205 // Test reading some other data types from sub-dictionaries.
206 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
207 bool boolean = false;
208 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
209 EXPECT_TRUE(boolean);
211 pref_store->SetValue(kNewWindowsInTabs, new FundamentalValue(false));
212 EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
213 EXPECT_TRUE(actual->GetAsBoolean(&boolean));
214 EXPECT_FALSE(boolean);
216 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
217 int integer = 0;
218 EXPECT_TRUE(actual->GetAsInteger(&integer));
219 EXPECT_EQ(20, integer);
220 pref_store->SetValue(kMaxTabs, new FundamentalValue(10));
221 EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
222 EXPECT_TRUE(actual->GetAsInteger(&integer));
223 EXPECT_EQ(10, integer);
225 pref_store->SetValue(kLongIntPref,
226 new StringValue(base::Int64ToString(214748364842LL)));
227 EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
228 EXPECT_TRUE(actual->GetAsString(&string_value));
229 int64 value;
230 base::StringToInt64(string_value, &value);
231 EXPECT_EQ(214748364842LL, value);
233 // Serialize and compare to expected output.
234 ASSERT_TRUE(PathExists(golden_output_file));
235 pref_store->CommitPendingWrite();
236 RunLoop().RunUntilIdle();
237 EXPECT_TRUE(TextContentsEqual(golden_output_file, output_file));
238 ASSERT_TRUE(base::DeleteFile(output_file, false));
241 TEST_F(JsonPrefStoreTest, Basic) {
242 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
243 temp_dir_.path().AppendASCII("write.json")));
245 // Test that the persistent value can be loaded.
246 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
247 ASSERT_TRUE(PathExists(input_file));
248 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
249 input_file,
250 message_loop_.message_loop_proxy().get(),
251 scoped_ptr<PrefFilter>());
252 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
253 EXPECT_FALSE(pref_store->ReadOnly());
254 EXPECT_TRUE(pref_store->IsInitializationComplete());
256 // The JSON file looks like this:
257 // {
258 // "homepage": "http://www.cnn.com",
259 // "some_directory": "/usr/local/",
260 // "tabs": {
261 // "new_windows_in_tabs": true,
262 // "max_tabs": 20
263 // }
264 // }
266 RunBasicJsonPrefStoreTest(
267 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
270 TEST_F(JsonPrefStoreTest, BasicAsync) {
271 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
272 temp_dir_.path().AppendASCII("write.json")));
274 // Test that the persistent value can be loaded.
275 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
276 ASSERT_TRUE(PathExists(input_file));
277 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
278 input_file,
279 message_loop_.message_loop_proxy().get(),
280 scoped_ptr<PrefFilter>());
283 MockPrefStoreObserver mock_observer;
284 pref_store->AddObserver(&mock_observer);
286 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
287 pref_store->ReadPrefsAsync(mock_error_delegate);
289 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
290 EXPECT_CALL(*mock_error_delegate,
291 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
292 RunLoop().RunUntilIdle();
293 pref_store->RemoveObserver(&mock_observer);
295 EXPECT_FALSE(pref_store->ReadOnly());
296 EXPECT_TRUE(pref_store->IsInitializationComplete());
299 // The JSON file looks like this:
300 // {
301 // "homepage": "http://www.cnn.com",
302 // "some_directory": "/usr/local/",
303 // "tabs": {
304 // "new_windows_in_tabs": true,
305 // "max_tabs": 20
306 // }
307 // }
309 RunBasicJsonPrefStoreTest(
310 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
313 TEST_F(JsonPrefStoreTest, PreserveEmptyValues) {
314 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
316 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
317 pref_file,
318 message_loop_.message_loop_proxy(),
319 scoped_ptr<PrefFilter>());
321 // Set some keys with empty values.
322 pref_store->SetValue("list", new base::ListValue);
323 pref_store->SetValue("dict", new base::DictionaryValue);
325 // Write to file.
326 pref_store->CommitPendingWrite();
327 MessageLoop::current()->RunUntilIdle();
329 // Reload.
330 pref_store = new JsonPrefStore(
331 pref_file,
332 message_loop_.message_loop_proxy(),
333 scoped_ptr<PrefFilter>());
334 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
335 ASSERT_FALSE(pref_store->ReadOnly());
337 // Check values.
338 const Value* result = NULL;
339 EXPECT_TRUE(pref_store->GetValue("list", &result));
340 EXPECT_TRUE(ListValue().Equals(result));
341 EXPECT_TRUE(pref_store->GetValue("dict", &result));
342 EXPECT_TRUE(DictionaryValue().Equals(result));
345 // This test is just documenting some potentially non-obvious behavior. It
346 // shouldn't be taken as normative.
347 TEST_F(JsonPrefStoreTest, RemoveClearsEmptyParent) {
348 FilePath pref_file = temp_dir_.path().AppendASCII("empty_values.json");
350 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
351 pref_file,
352 message_loop_.message_loop_proxy(),
353 scoped_ptr<PrefFilter>());
355 base::DictionaryValue* dict = new base::DictionaryValue;
356 dict->SetString("key", "value");
357 pref_store->SetValue("dict", dict);
359 pref_store->RemoveValue("dict.key");
361 const base::Value* retrieved_dict = NULL;
362 bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
363 EXPECT_FALSE(has_dict);
366 // Tests asynchronous reading of the file when there is no file.
367 TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
368 base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
369 ASSERT_FALSE(PathExists(bogus_input_file));
370 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
371 bogus_input_file,
372 message_loop_.message_loop_proxy().get(),
373 scoped_ptr<PrefFilter>());
374 MockPrefStoreObserver mock_observer;
375 pref_store->AddObserver(&mock_observer);
377 MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
378 pref_store->ReadPrefsAsync(mock_error_delegate);
380 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
381 EXPECT_CALL(*mock_error_delegate,
382 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
383 RunLoop().RunUntilIdle();
384 pref_store->RemoveObserver(&mock_observer);
386 EXPECT_FALSE(pref_store->ReadOnly());
389 TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
390 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
391 temp_dir_.path().AppendASCII("write.json")));
393 // Test that the persistent value can be loaded.
394 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
395 ASSERT_TRUE(PathExists(input_file));
397 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter(
398 new InterceptingPrefFilter());
399 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
400 intercepting_pref_filter.get();
401 scoped_refptr<JsonPrefStore> pref_store =
402 new JsonPrefStore(input_file,
403 message_loop_.message_loop_proxy().get(),
404 intercepting_pref_filter.Pass());
406 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
407 pref_store->ReadPrefs());
408 EXPECT_FALSE(pref_store->ReadOnly());
410 // The store shouldn't be considered initialized until the interceptor
411 // returns.
412 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
413 EXPECT_FALSE(pref_store->IsInitializationComplete());
414 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
416 raw_intercepting_pref_filter_->ReleasePrefs();
418 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
419 EXPECT_TRUE(pref_store->IsInitializationComplete());
420 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
422 // The JSON file looks like this:
423 // {
424 // "homepage": "http://www.cnn.com",
425 // "some_directory": "/usr/local/",
426 // "tabs": {
427 // "new_windows_in_tabs": true,
428 // "max_tabs": 20
429 // }
430 // }
432 RunBasicJsonPrefStoreTest(
433 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
436 TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
437 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
438 temp_dir_.path().AppendASCII("write.json")));
440 // Test that the persistent value can be loaded.
441 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
442 ASSERT_TRUE(PathExists(input_file));
444 scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter(
445 new InterceptingPrefFilter());
446 InterceptingPrefFilter* raw_intercepting_pref_filter_ =
447 intercepting_pref_filter.get();
448 scoped_refptr<JsonPrefStore> pref_store =
449 new JsonPrefStore(input_file,
450 message_loop_.message_loop_proxy().get(),
451 intercepting_pref_filter.Pass());
453 MockPrefStoreObserver mock_observer;
454 pref_store->AddObserver(&mock_observer);
456 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
457 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
460 pref_store->ReadPrefsAsync(mock_error_delegate);
462 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
463 // EXPECT_CALL(*mock_error_delegate,
464 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
465 RunLoop().RunUntilIdle();
467 EXPECT_FALSE(pref_store->ReadOnly());
468 EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
469 EXPECT_FALSE(pref_store->IsInitializationComplete());
470 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
474 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
475 // EXPECT_CALL(*mock_error_delegate,
476 // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
478 raw_intercepting_pref_filter_->ReleasePrefs();
480 EXPECT_FALSE(pref_store->ReadOnly());
481 EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs());
482 EXPECT_TRUE(pref_store->IsInitializationComplete());
483 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
486 pref_store->RemoveObserver(&mock_observer);
488 // The JSON file looks like this:
489 // {
490 // "homepage": "http://www.cnn.com",
491 // "some_directory": "/usr/local/",
492 // "tabs": {
493 // "new_windows_in_tabs": true,
494 // "max_tabs": 20
495 // }
496 // }
498 RunBasicJsonPrefStoreTest(
499 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
502 TEST_F(JsonPrefStoreTest, AlternateFile) {
503 ASSERT_TRUE(
504 base::CopyFile(data_dir_.AppendASCII("read.json"),
505 temp_dir_.path().AppendASCII("alternate.json")));
507 // Test that the alternate file is moved to the main file and read as-is from
508 // there.
509 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
510 base::FilePath alternate_input_file =
511 temp_dir_.path().AppendASCII("alternate.json");
512 ASSERT_FALSE(PathExists(input_file));
513 ASSERT_TRUE(PathExists(alternate_input_file));
514 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
515 input_file,
516 alternate_input_file,
517 message_loop_.message_loop_proxy().get(),
518 scoped_ptr<PrefFilter>());
520 ASSERT_FALSE(PathExists(input_file));
521 ASSERT_TRUE(PathExists(alternate_input_file));
522 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
524 ASSERT_TRUE(PathExists(input_file));
525 ASSERT_FALSE(PathExists(alternate_input_file));
527 EXPECT_FALSE(pref_store->ReadOnly());
528 EXPECT_TRUE(pref_store->IsInitializationComplete());
530 // The JSON file looks like this:
531 // {
532 // "homepage": "http://www.cnn.com",
533 // "some_directory": "/usr/local/",
534 // "tabs": {
535 // "new_windows_in_tabs": true,
536 // "max_tabs": 20
537 // }
538 // }
540 RunBasicJsonPrefStoreTest(
541 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
544 TEST_F(JsonPrefStoreTest, AlternateFileIgnoredWhenMainFileExists) {
545 ASSERT_TRUE(
546 base::CopyFile(data_dir_.AppendASCII("read.json"),
547 temp_dir_.path().AppendASCII("write.json")));
548 ASSERT_TRUE(
549 base::CopyFile(data_dir_.AppendASCII("invalid.json"),
550 temp_dir_.path().AppendASCII("alternate.json")));
552 // Test that the alternate file is ignored and that the read occurs from the
553 // existing main file. There is no attempt at even deleting the alternate
554 // file as this scenario should never happen in normal user-data-dirs.
555 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
556 base::FilePath alternate_input_file =
557 temp_dir_.path().AppendASCII("alternate.json");
558 ASSERT_TRUE(PathExists(input_file));
559 ASSERT_TRUE(PathExists(alternate_input_file));
560 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
561 input_file,
562 alternate_input_file,
563 message_loop_.message_loop_proxy().get(),
564 scoped_ptr<PrefFilter>());
566 ASSERT_TRUE(PathExists(input_file));
567 ASSERT_TRUE(PathExists(alternate_input_file));
568 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
570 ASSERT_TRUE(PathExists(input_file));
571 ASSERT_TRUE(PathExists(alternate_input_file));
573 EXPECT_FALSE(pref_store->ReadOnly());
574 EXPECT_TRUE(pref_store->IsInitializationComplete());
576 // The JSON file looks like this:
577 // {
578 // "homepage": "http://www.cnn.com",
579 // "some_directory": "/usr/local/",
580 // "tabs": {
581 // "new_windows_in_tabs": true,
582 // "max_tabs": 20
583 // }
584 // }
586 RunBasicJsonPrefStoreTest(
587 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
590 TEST_F(JsonPrefStoreTest, AlternateFileDNE) {
591 ASSERT_TRUE(
592 base::CopyFile(data_dir_.AppendASCII("read.json"),
593 temp_dir_.path().AppendASCII("write.json")));
595 // Test that the basic read works fine when an alternate file is specified but
596 // does not exist.
597 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
598 base::FilePath alternate_input_file =
599 temp_dir_.path().AppendASCII("alternate.json");
600 ASSERT_TRUE(PathExists(input_file));
601 ASSERT_FALSE(PathExists(alternate_input_file));
602 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
603 input_file,
604 alternate_input_file,
605 message_loop_.message_loop_proxy().get(),
606 scoped_ptr<PrefFilter>());
608 ASSERT_TRUE(PathExists(input_file));
609 ASSERT_FALSE(PathExists(alternate_input_file));
610 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
612 ASSERT_TRUE(PathExists(input_file));
613 ASSERT_FALSE(PathExists(alternate_input_file));
615 EXPECT_FALSE(pref_store->ReadOnly());
616 EXPECT_TRUE(pref_store->IsInitializationComplete());
618 // The JSON file looks like this:
619 // {
620 // "homepage": "http://www.cnn.com",
621 // "some_directory": "/usr/local/",
622 // "tabs": {
623 // "new_windows_in_tabs": true,
624 // "max_tabs": 20
625 // }
626 // }
628 RunBasicJsonPrefStoreTest(
629 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
632 TEST_F(JsonPrefStoreTest, BasicAsyncWithAlternateFile) {
633 ASSERT_TRUE(
634 base::CopyFile(data_dir_.AppendASCII("read.json"),
635 temp_dir_.path().AppendASCII("alternate.json")));
637 // Test that the alternate file is moved to the main file and read as-is from
638 // there even when the read is made asynchronously.
639 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
640 base::FilePath alternate_input_file =
641 temp_dir_.path().AppendASCII("alternate.json");
642 ASSERT_FALSE(PathExists(input_file));
643 ASSERT_TRUE(PathExists(alternate_input_file));
644 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
645 input_file,
646 alternate_input_file,
647 message_loop_.message_loop_proxy().get(),
648 scoped_ptr<PrefFilter>());
650 ASSERT_FALSE(PathExists(input_file));
651 ASSERT_TRUE(PathExists(alternate_input_file));
654 MockPrefStoreObserver mock_observer;
655 pref_store->AddObserver(&mock_observer);
657 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
658 pref_store->ReadPrefsAsync(mock_error_delegate);
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);
666 EXPECT_FALSE(pref_store->ReadOnly());
667 EXPECT_TRUE(pref_store->IsInitializationComplete());
670 ASSERT_TRUE(PathExists(input_file));
671 ASSERT_FALSE(PathExists(alternate_input_file));
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 // }
683 RunBasicJsonPrefStoreTest(
684 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
687 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestBasic) {
688 SimpleTestClock* test_clock = new SimpleTestClock;
689 SetCurrentTimeInMinutes(0, test_clock);
690 JsonPrefStore::WriteCountHistogram histogram(
691 base::TimeDelta::FromSeconds(10),
692 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
693 scoped_ptr<base::Clock>(test_clock));
694 int32 report_interval =
695 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
697 histogram.RecordWriteOccured();
699 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
700 histogram.ReportOutstandingWrites();
701 scoped_ptr<HistogramSamples> samples =
702 histogram.GetHistogram()->SnapshotSamples();
703 ASSERT_EQ(1, samples->GetCount(1));
704 ASSERT_EQ(1, samples->TotalCount());
706 ASSERT_EQ("Settings.JsonDataWriteCount.Local_State",
707 histogram.GetHistogram()->histogram_name());
708 ASSERT_TRUE(histogram.GetHistogram()->HasConstructionArguments(1, 30, 31));
711 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestSinglePeriod) {
712 SimpleTestClock* test_clock = new SimpleTestClock;
713 SetCurrentTimeInMinutes(0, test_clock);
714 JsonPrefStore::WriteCountHistogram histogram(
715 base::TimeDelta::FromSeconds(10),
716 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
717 scoped_ptr<base::Clock>(test_clock));
718 int32 report_interval =
719 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
721 histogram.RecordWriteOccured();
722 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
723 histogram.RecordWriteOccured();
724 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
725 histogram.RecordWriteOccured();
727 // Nothing should be recorded until the report period has elapsed.
728 scoped_ptr<HistogramSamples> samples =
729 histogram.GetHistogram()->SnapshotSamples();
730 ASSERT_EQ(0, samples->TotalCount());
732 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
733 histogram.RecordWriteOccured();
735 // Now the report period has elapsed.
736 samples = histogram.GetHistogram()->SnapshotSamples();
737 ASSERT_EQ(1, samples->GetCount(3));
738 ASSERT_EQ(1, samples->TotalCount());
740 // The last write won't be recorded because the second count period hasn't
741 // fully elapsed.
742 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
743 histogram.ReportOutstandingWrites();
745 samples = histogram.GetHistogram()->SnapshotSamples();
746 ASSERT_EQ(1, samples->GetCount(3));
747 ASSERT_EQ(1, samples->TotalCount());
750 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestMultiplePeriods) {
751 SimpleTestClock* test_clock = new SimpleTestClock;
752 SetCurrentTimeInMinutes(0, test_clock);
753 JsonPrefStore::WriteCountHistogram histogram(
754 base::TimeDelta::FromSeconds(10),
755 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
756 scoped_ptr<base::Clock>(test_clock));
757 int32 report_interval =
758 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
760 histogram.RecordWriteOccured();
761 SetCurrentTimeInMinutes(0.5 * report_interval, test_clock);
762 histogram.RecordWriteOccured();
763 SetCurrentTimeInMinutes(0.7 * report_interval, test_clock);
764 histogram.RecordWriteOccured();
765 SetCurrentTimeInMinutes(1.3 * report_interval, test_clock);
766 histogram.RecordWriteOccured();
767 SetCurrentTimeInMinutes(1.5 * report_interval, test_clock);
768 histogram.RecordWriteOccured();
769 SetCurrentTimeInMinutes(2.1 * report_interval, test_clock);
770 histogram.RecordWriteOccured();
771 SetCurrentTimeInMinutes(2.5 * report_interval, test_clock);
772 histogram.RecordWriteOccured();
773 SetCurrentTimeInMinutes(2.7 * report_interval, test_clock);
774 histogram.RecordWriteOccured();
775 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
776 histogram.RecordWriteOccured();
778 // The last write won't be recorded because the second count period hasn't
779 // fully elapsed
780 SetCurrentTimeInMinutes(3.5 * report_interval, test_clock);
781 histogram.ReportOutstandingWrites();
782 scoped_ptr<HistogramSamples> samples =
783 histogram.GetHistogram()->SnapshotSamples();
784 ASSERT_EQ(2, samples->GetCount(3));
785 ASSERT_EQ(1, samples->GetCount(2));
786 ASSERT_EQ(3, samples->TotalCount());
789 TEST_F(JsonPrefStoreTest, WriteCountHistogramTestPeriodWithGaps) {
790 SimpleTestClock* test_clock = new SimpleTestClock;
791 SetCurrentTimeInMinutes(0, test_clock);
792 JsonPrefStore::WriteCountHistogram histogram(
793 base::TimeDelta::FromSeconds(10),
794 base::FilePath(FILE_PATH_LITERAL("/tmp/Local State")),
795 scoped_ptr<base::Clock>(test_clock));
796 int32 report_interval =
797 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins;
799 // 1 write in the first period.
800 histogram.RecordWriteOccured();
802 // No writes in the second and third periods.
804 // 2 writes in the fourth period.
805 SetCurrentTimeInMinutes(3.1 * report_interval, test_clock);
806 histogram.RecordWriteOccured();
807 SetCurrentTimeInMinutes(3.3 * report_interval, test_clock);
808 histogram.RecordWriteOccured();
810 // No writes in the fifth period.
812 // 3 writes in the sixth period.
813 SetCurrentTimeInMinutes(5.1 * report_interval, test_clock);
814 histogram.RecordWriteOccured();
815 SetCurrentTimeInMinutes(5.3 * report_interval, test_clock);
816 histogram.RecordWriteOccured();
817 SetCurrentTimeInMinutes(5.5 * report_interval, test_clock);
818 histogram.RecordWriteOccured();
820 SetCurrentTimeInMinutes(6.1 * report_interval, test_clock);
821 histogram.ReportOutstandingWrites();
822 scoped_ptr<HistogramSamples> samples =
823 histogram.GetHistogram()->SnapshotSamples();
824 ASSERT_EQ(3, samples->GetCount(0));
825 ASSERT_EQ(1, samples->GetCount(1));
826 ASSERT_EQ(1, samples->GetCount(2));
827 ASSERT_EQ(1, samples->GetCount(3));
828 ASSERT_EQ(6, samples->TotalCount());
831 } // namespace base