Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Side by Side Diff: base/prefs/json_pref_store_unittest.cc

Issue 257003007: Introduce a new framework for back-and-forth tracked/protected preferences migration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix ios compile for realz?! Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/prefs/json_pref_store.h" 5 #include "base/prefs/json_pref_store.h"
6 6
7 #include "base/bind.h"
7 #include "base/file_util.h" 8 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h" 9 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
11 #include "base/path_service.h" 12 #include "base/path_service.h"
12 #include "base/prefs/pref_filter.h" 13 #include "base/prefs/pref_filter.h"
13 #include "base/run_loop.h" 14 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/sequenced_worker_pool.h" 18 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/threading/thread.h" 19 #include "base/threading/thread.h"
19 #include "base/values.h" 20 #include "base/values.h"
20 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
22 23
23 namespace base { 24 namespace base {
24 namespace { 25 namespace {
25 26
26 const char kHomePage[] = "homepage"; 27 const char kHomePage[] = "homepage";
27 28
29 class TestFileReadInterceptor {
30 public:
31 TestFileReadInterceptor();
32 ~TestFileReadInterceptor();
33
34 // Tells this TestFileReadInterceptor to intercept the next file read on
35 // |json_pref_store|.
36 void InterceptNextFileReadOnPrefStore(JsonPrefStore* json_pref_store);
37
38 bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; }
39
40 // Finalize an intercepted read, handing |intercept_prefs_| back to its
41 // JsonPrefStore.
42 void FinalizeInterceptedRead();
43
44 private:
45 void OnFileRead(
46 scoped_ptr<base::DictionaryValue> prefs,
47 const JsonPrefStore::FinalizePrefsReadCallback& finalize_prefs_read);
48
49 scoped_ptr<base::DictionaryValue> intercepted_prefs_;
50 JsonPrefStore::FinalizePrefsReadCallback finalize_prefs_read_;
51
52 DISALLOW_COPY_AND_ASSIGN(TestFileReadInterceptor);
53 };
54
55 TestFileReadInterceptor::TestFileReadInterceptor() {}
56 TestFileReadInterceptor::~TestFileReadInterceptor() {}
57
58 void TestFileReadInterceptor::InterceptNextFileReadOnPrefStore(
59 JsonPrefStore* json_pref_store) {
60 json_pref_store->InterceptNextFileRead(
61 base::Bind(&TestFileReadInterceptor::OnFileRead, base::Unretained(this)));
62 }
63
64 void TestFileReadInterceptor::FinalizeInterceptedRead() {
65 EXPECT_FALSE(finalize_prefs_read_.is_null());
66 finalize_prefs_read_.Run(intercepted_prefs_.Pass(), false);
67 }
68
69 void TestFileReadInterceptor::OnFileRead(
70 scoped_ptr<base::DictionaryValue> prefs,
71 const JsonPrefStore::FinalizePrefsReadCallback& finalize_prefs_read) {
72 intercepted_prefs_ = prefs.Pass();
73 finalize_prefs_read_ = finalize_prefs_read;
74 }
75
28 class MockPrefStoreObserver : public PrefStore::Observer { 76 class MockPrefStoreObserver : public PrefStore::Observer {
29 public: 77 public:
30 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&)); 78 MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
31 MOCK_METHOD1(OnInitializationCompleted, void (bool)); 79 MOCK_METHOD1(OnInitializationCompleted, void (bool));
32 }; 80 };
33 81
34 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate { 82 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
35 public: 83 public:
36 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError)); 84 MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
37 }; 85 };
38 86
39 } // namespace 87 } // namespace
40 88
41 class JsonPrefStoreTest : public testing::Test { 89 class JsonPrefStoreTest : public testing::Test {
42 protected: 90 protected:
43 virtual void SetUp() OVERRIDE { 91 virtual void SetUp() OVERRIDE {
44 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 92 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
45 93
46 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_)); 94 ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &data_dir_));
47 data_dir_ = data_dir_.AppendASCII("prefs"); 95 data_dir_ = data_dir_.AppendASCII("prefs");
48 ASSERT_TRUE(PathExists(data_dir_)); 96 ASSERT_TRUE(PathExists(data_dir_));
49 } 97 }
50 98
99 TestFileReadInterceptor file_read_interceptor_;
100
51 // The path to temporary directory used to contain the test operations. 101 // The path to temporary directory used to contain the test operations.
52 base::ScopedTempDir temp_dir_; 102 base::ScopedTempDir temp_dir_;
53 // The path to the directory where the test data is stored. 103 // The path to the directory where the test data is stored.
54 base::FilePath data_dir_; 104 base::FilePath data_dir_;
55 // A message loop that we can use as the file thread message loop. 105 // A message loop that we can use as the file thread message loop.
56 MessageLoop message_loop_; 106 MessageLoop message_loop_;
57 }; 107 };
58 108
59 // Test fallback behavior for a nonexistent file. 109 // Test fallback behavior for a nonexistent file.
60 TEST_F(JsonPrefStoreTest, NonExistentFile) { 110 TEST_F(JsonPrefStoreTest, NonExistentFile) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // Serialize and compare to expected output. 200 // Serialize and compare to expected output.
151 ASSERT_TRUE(PathExists(golden_output_file)); 201 ASSERT_TRUE(PathExists(golden_output_file));
152 pref_store->CommitPendingWrite(); 202 pref_store->CommitPendingWrite();
153 RunLoop().RunUntilIdle(); 203 RunLoop().RunUntilIdle();
154 EXPECT_TRUE(TextContentsEqual(golden_output_file, output_file)); 204 EXPECT_TRUE(TextContentsEqual(golden_output_file, output_file));
155 ASSERT_TRUE(base::DeleteFile(output_file, false)); 205 ASSERT_TRUE(base::DeleteFile(output_file, false));
156 } 206 }
157 207
158 TEST_F(JsonPrefStoreTest, Basic) { 208 TEST_F(JsonPrefStoreTest, Basic) {
159 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"), 209 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
160 temp_dir_.path().AppendASCII("write.json"))); 210 temp_dir_.path().AppendASCII("write.json")));
161 211
162 // Test that the persistent value can be loaded. 212 // Test that the persistent value can be loaded.
163 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); 213 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
164 ASSERT_TRUE(PathExists(input_file)); 214 ASSERT_TRUE(PathExists(input_file));
165 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( 215 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
166 input_file, 216 input_file,
167 message_loop_.message_loop_proxy().get(), 217 message_loop_.message_loop_proxy().get(),
168 scoped_ptr<PrefFilter>()); 218 scoped_ptr<PrefFilter>());
169 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); 219 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
170 ASSERT_FALSE(pref_store->ReadOnly()); 220 EXPECT_FALSE(pref_store->ReadOnly());
221 EXPECT_FALSE(file_read_interceptor_.has_intercepted_prefs());
222 EXPECT_TRUE(pref_store->IsInitializationComplete());
171 223
172 // The JSON file looks like this: 224 // The JSON file looks like this:
173 // { 225 // {
174 // "homepage": "http://www.cnn.com", 226 // "homepage": "http://www.cnn.com",
175 // "some_directory": "/usr/local/", 227 // "some_directory": "/usr/local/",
176 // "tabs": { 228 // "tabs": {
177 // "new_windows_in_tabs": true, 229 // "new_windows_in_tabs": true,
178 // "max_tabs": 20 230 // "max_tabs": 20
179 // } 231 // }
180 // } 232 // }
181 233
182 RunBasicJsonPrefStoreTest( 234 RunBasicJsonPrefStoreTest(
183 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json")); 235 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
184 } 236 }
185 237
186 TEST_F(JsonPrefStoreTest, BasicAsync) { 238 TEST_F(JsonPrefStoreTest, BasicAsync) {
187 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"), 239 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
188 temp_dir_.path().AppendASCII("write.json"))); 240 temp_dir_.path().AppendASCII("write.json")));
189 241
190 // Test that the persistent value can be loaded. 242 // Test that the persistent value can be loaded.
191 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); 243 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
192 ASSERT_TRUE(PathExists(input_file)); 244 ASSERT_TRUE(PathExists(input_file));
193 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore( 245 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
194 input_file, 246 input_file,
195 message_loop_.message_loop_proxy().get(), 247 message_loop_.message_loop_proxy().get(),
196 scoped_ptr<PrefFilter>()); 248 scoped_ptr<PrefFilter>());
197 249
198 { 250 {
199 MockPrefStoreObserver mock_observer; 251 MockPrefStoreObserver mock_observer;
200 pref_store->AddObserver(&mock_observer); 252 pref_store->AddObserver(&mock_observer);
201 253
202 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate; 254 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
203 pref_store->ReadPrefsAsync(mock_error_delegate); 255 pref_store->ReadPrefsAsync(mock_error_delegate);
204 256
205 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); 257 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
206 EXPECT_CALL(*mock_error_delegate, 258 EXPECT_CALL(*mock_error_delegate,
207 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); 259 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
208 RunLoop().RunUntilIdle(); 260 RunLoop().RunUntilIdle();
209 pref_store->RemoveObserver(&mock_observer); 261 pref_store->RemoveObserver(&mock_observer);
210 262
211 ASSERT_FALSE(pref_store->ReadOnly()); 263 EXPECT_FALSE(pref_store->ReadOnly());
264 EXPECT_FALSE(file_read_interceptor_.has_intercepted_prefs());
265 EXPECT_TRUE(pref_store->IsInitializationComplete());
212 } 266 }
213 267
214 // The JSON file looks like this: 268 // The JSON file looks like this:
215 // { 269 // {
216 // "homepage": "http://www.cnn.com", 270 // "homepage": "http://www.cnn.com",
217 // "some_directory": "/usr/local/", 271 // "some_directory": "/usr/local/",
218 // "tabs": { 272 // "tabs": {
219 // "new_windows_in_tabs": true, 273 // "new_windows_in_tabs": true,
220 // "max_tabs": 20 274 // "max_tabs": 20
221 // } 275 // }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 348
295 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); 349 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
296 EXPECT_CALL(*mock_error_delegate, 350 EXPECT_CALL(*mock_error_delegate,
297 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1); 351 OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
298 RunLoop().RunUntilIdle(); 352 RunLoop().RunUntilIdle();
299 pref_store->RemoveObserver(&mock_observer); 353 pref_store->RemoveObserver(&mock_observer);
300 354
301 EXPECT_FALSE(pref_store->ReadOnly()); 355 EXPECT_FALSE(pref_store->ReadOnly());
302 } 356 }
303 357
358 TEST_F(JsonPrefStoreTest, ReadWithInterceptor) {
359 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
360 temp_dir_.path().AppendASCII("write.json")));
361
362 // Test that the persistent value can be loaded.
363 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
364 ASSERT_TRUE(PathExists(input_file));
365 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
366 input_file,
367 message_loop_.message_loop_proxy().get(),
368 scoped_ptr<PrefFilter>());
369 file_read_interceptor_.InterceptNextFileReadOnPrefStore(pref_store);
370
371 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
372 EXPECT_FALSE(pref_store->ReadOnly());
373
374 // The store shouldn't be considered initialized until the interceptor
375 // returns.
376 EXPECT_TRUE(file_read_interceptor_.has_intercepted_prefs());
377 EXPECT_FALSE(pref_store->IsInitializationComplete());
378 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
379
380 file_read_interceptor_.FinalizeInterceptedRead();
381
382 EXPECT_FALSE(file_read_interceptor_.has_intercepted_prefs());
383 EXPECT_TRUE(pref_store->IsInitializationComplete());
384 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
385
386 // The JSON file looks like this:
387 // {
388 // "homepage": "http://www.cnn.com",
389 // "some_directory": "/usr/local/",
390 // "tabs": {
391 // "new_windows_in_tabs": true,
392 // "max_tabs": 20
393 // }
394 // }
395
396 RunBasicJsonPrefStoreTest(
397 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
398 }
399
400 TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
401 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
402 temp_dir_.path().AppendASCII("write.json")));
403
404 // Test that the persistent value can be loaded.
405 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
406 ASSERT_TRUE(PathExists(input_file));
407 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
408 input_file,
409 message_loop_.message_loop_proxy().get(),
410 scoped_ptr<PrefFilter>());
411 file_read_interceptor_.InterceptNextFileReadOnPrefStore(pref_store);
412
413 MockPrefStoreObserver mock_observer;
414 pref_store->AddObserver(&mock_observer);
415
416 // Ownership of the |mock_error_delegate| is handed to the |pref_store| below.
417 MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate;
418
419 {
420 pref_store->ReadPrefsAsync(mock_error_delegate);
421
422 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
423 EXPECT_CALL(*mock_error_delegate,
424 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
425 RunLoop().RunUntilIdle();
426
427 EXPECT_FALSE(pref_store->ReadOnly());
428 EXPECT_TRUE(file_read_interceptor_.has_intercepted_prefs());
429 EXPECT_FALSE(pref_store->IsInitializationComplete());
430 EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL));
431 }
432
433 {
434 EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
435 EXPECT_CALL(*mock_error_delegate,
436 OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
437
438 file_read_interceptor_.FinalizeInterceptedRead();
439
440 EXPECT_FALSE(pref_store->ReadOnly());
441 EXPECT_FALSE(file_read_interceptor_.has_intercepted_prefs());
442 EXPECT_TRUE(pref_store->IsInitializationComplete());
443 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
444 }
445
446 pref_store->RemoveObserver(&mock_observer);
447
448 // The JSON file looks like this:
449 // {
450 // "homepage": "http://www.cnn.com",
451 // "some_directory": "/usr/local/",
452 // "tabs": {
453 // "new_windows_in_tabs": true,
454 // "max_tabs": 20
455 // }
456 // }
457
458 RunBasicJsonPrefStoreTest(
459 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
460 }
461
462 TEST_F(JsonPrefStoreTest, MultipleReadsResultInASingleIntercept) {
463 ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"),
464 temp_dir_.path().AppendASCII("write.json")));
465
466 // Test that the persistent value can be loaded.
467 base::FilePath input_file = temp_dir_.path().AppendASCII("write.json");
468 ASSERT_TRUE(PathExists(input_file));
469 scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
470 input_file,
471 message_loop_.message_loop_proxy().get(),
472 scoped_ptr<PrefFilter>());
473 file_read_interceptor_.InterceptNextFileReadOnPrefStore(pref_store);
474
475 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
476 EXPECT_TRUE(file_read_interceptor_.has_intercepted_prefs());
477 file_read_interceptor_.FinalizeInterceptedRead();
478 EXPECT_FALSE(file_read_interceptor_.has_intercepted_prefs());
479
480 // Read again; expect no intercepts.
481 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
482 EXPECT_FALSE(pref_store->ReadOnly());
483 EXPECT_FALSE(file_read_interceptor_.has_intercepted_prefs());
484 EXPECT_TRUE(pref_store->IsInitializationComplete());
485 EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL));
486
487 // The JSON file looks like this:
488 // {
489 // "homepage": "http://www.cnn.com",
490 // "some_directory": "/usr/local/",
491 // "tabs": {
492 // "new_windows_in_tabs": true,
493 // "max_tabs": 20
494 // }
495 // }
496
497 RunBasicJsonPrefStoreTest(
498 pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json"));
499 }
500
304 } // namespace base 501 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698