123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/prefs/segregated_pref_store.h"
- #include <memory>
- #include <set>
- #include <string>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/memory/raw_ptr.h"
- #include "base/memory/ref_counted.h"
- #include "base/run_loop.h"
- #include "base/synchronization/waitable_event.h"
- #include "base/test/task_environment.h"
- #include "base/values.h"
- #include "components/prefs/persistent_pref_store.h"
- #include "components/prefs/pref_store_observer_mock.h"
- #include "components/prefs/testing_pref_store.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace {
- const char kSelectedPref[] = "selected_pref";
- const char kUnselectedPref[] = "unselected_pref";
- const char kSharedPref[] = "shared_pref";
- const char kValue1[] = "value1";
- const char kValue2[] = "value2";
- class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
- public:
- struct Data {
- Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in)
- : invoked(invoked_in), read_error(read_error_in) {}
- bool invoked;
- PersistentPrefStore::PrefReadError read_error;
- };
- explicit MockReadErrorDelegate(Data* data) : data_(data) {
- DCHECK(data_);
- EXPECT_FALSE(data_->invoked);
- }
- // PersistentPrefStore::ReadErrorDelegate implementation
- void OnError(PersistentPrefStore::PrefReadError read_error) override {
- EXPECT_FALSE(data_->invoked);
- data_->invoked = true;
- data_->read_error = read_error;
- }
- private:
- raw_ptr<Data> data_;
- };
- enum class CommitPendingWriteMode {
- // Basic mode.
- WITHOUT_CALLBACK,
- // With reply callback.
- WITH_CALLBACK,
- // With synchronous notify callback (synchronous after the write -- shouldn't
- // require pumping messages to observe).
- WITH_SYNCHRONOUS_CALLBACK,
- };
- class SegregatedPrefStoreTest
- : public testing::TestWithParam<CommitPendingWriteMode> {
- public:
- SegregatedPrefStoreTest()
- : read_error_delegate_data_(false,
- PersistentPrefStore::PREF_READ_ERROR_NONE),
- read_error_delegate_(
- new MockReadErrorDelegate(&read_error_delegate_data_)) {}
- void SetUp() override {
- selected_store_ = new TestingPrefStore;
- default_store_ = new TestingPrefStore;
- selected_pref_names_.insert(kSelectedPref);
- selected_pref_names_.insert(kSharedPref);
- segregated_store_ = new SegregatedPrefStore(default_store_, selected_store_,
- selected_pref_names_);
- segregated_store_->AddObserver(&observer_);
- }
- void TearDown() override { segregated_store_->RemoveObserver(&observer_); }
- protected:
- std::unique_ptr<PersistentPrefStore::ReadErrorDelegate>
- GetReadErrorDelegate() {
- EXPECT_TRUE(read_error_delegate_);
- return std::move(read_error_delegate_);
- }
- base::test::TaskEnvironment task_environment_;
- PrefStoreObserverMock observer_;
- scoped_refptr<TestingPrefStore> default_store_;
- scoped_refptr<TestingPrefStore> selected_store_;
- scoped_refptr<SegregatedPrefStore> segregated_store_;
- std::set<std::string> selected_pref_names_;
- MockReadErrorDelegate::Data read_error_delegate_data_;
- private:
- std::unique_ptr<MockReadErrorDelegate> read_error_delegate_;
- };
- } // namespace
- TEST_P(SegregatedPrefStoreTest, StoreValues) {
- ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->ReadPrefs());
- // Properly stores new values.
- segregated_store_->SetValue(kSelectedPref,
- std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- segregated_store_->SetValue(kUnselectedPref,
- std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
- ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
- ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
- ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
- ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
- ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
- ASSERT_FALSE(selected_store_->committed());
- ASSERT_FALSE(default_store_->committed());
- switch (GetParam()) {
- case CommitPendingWriteMode::WITHOUT_CALLBACK: {
- segregated_store_->CommitPendingWrite();
- base::RunLoop().RunUntilIdle();
- break;
- }
- case CommitPendingWriteMode::WITH_CALLBACK: {
- base::RunLoop run_loop;
- segregated_store_->CommitPendingWrite(run_loop.QuitClosure());
- run_loop.Run();
- break;
- }
- case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK: {
- base::WaitableEvent written;
- segregated_store_->CommitPendingWrite(
- base::OnceClosure(),
- base::BindOnce(&base::WaitableEvent::Signal, Unretained(&written)));
- written.Wait();
- break;
- }
- }
- ASSERT_TRUE(selected_store_->committed());
- ASSERT_TRUE(default_store_->committed());
- }
- TEST_F(SegregatedPrefStoreTest, ReadValues) {
- selected_store_->SetValue(kSelectedPref,
- std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- default_store_->SetValue(kUnselectedPref,
- std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- // Works properly with values that are already there.
- ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->ReadPrefs());
- ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->GetReadError());
- ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
- ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
- ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
- ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
- ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
- ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
- }
- TEST_F(SegregatedPrefStoreTest, RemoveValuesByPrefix) {
- const std::string subpref_name1 = kSelectedPref;
- const std::string subpref_name2 = std::string(kSelectedPref) + "b";
- const std::string other_name = kUnselectedPref;
- const std::string prefix = kSelectedPref;
- selected_store_->SetValue(subpref_name1,
- std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- default_store_->SetValue(subpref_name2,
- std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- default_store_->SetValue(other_name, std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- ASSERT_TRUE(selected_store_->GetValue(subpref_name1, nullptr));
- ASSERT_TRUE(default_store_->GetValue(subpref_name2, nullptr));
- ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
- segregated_store_->RemoveValuesByPrefixSilently(kSelectedPref);
- ASSERT_FALSE(selected_store_->GetValue(subpref_name1, nullptr));
- ASSERT_FALSE(default_store_->GetValue(subpref_name2, nullptr));
- ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
- }
- TEST_F(SegregatedPrefStoreTest, Observer) {
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->ReadPrefs());
- EXPECT_TRUE(observer_.initialized);
- EXPECT_TRUE(observer_.initialization_success);
- EXPECT_TRUE(observer_.changed_keys.empty());
- segregated_store_->SetValue(kSelectedPref,
- std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- observer_.VerifyAndResetChangedKey(kSelectedPref);
- segregated_store_->SetValue(kUnselectedPref,
- std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- observer_.VerifyAndResetChangedKey(kUnselectedPref);
- }
- TEST_F(SegregatedPrefStoreTest,
- ObserverAfterConstructionAfterSubInitialization) {
- // Ensure that underlying PrefStores are initialized first.
- default_store_->ReadPrefs();
- selected_store_->ReadPrefs();
- EXPECT_TRUE(default_store_->IsInitializationComplete());
- EXPECT_TRUE(selected_store_->IsInitializationComplete());
- // Create a new SegregatedPrefStore based on the initialized PrefStores.
- segregated_store_->RemoveObserver(&observer_);
- segregated_store_ = base::MakeRefCounted<SegregatedPrefStore>(
- default_store_, selected_store_, selected_pref_names_);
- segregated_store_->AddObserver(&observer_);
- EXPECT_TRUE(segregated_store_->IsInitializationComplete());
- // The Observer should receive notifications from the SegregatedPrefStore.
- EXPECT_TRUE(observer_.changed_keys.empty());
- segregated_store_->SetValue(kSelectedPref,
- std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- observer_.VerifyAndResetChangedKey(kSelectedPref);
- segregated_store_->SetValue(kUnselectedPref,
- std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- observer_.VerifyAndResetChangedKey(kUnselectedPref);
- }
- TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) {
- // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
- // to PREF_READ_ERROR_NONE.
- selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->ReadPrefs());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) {
- selected_store_->set_read_error(
- PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
- segregated_store_->ReadPrefs());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileErrorAsync) {
- // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
- // to PREF_READ_ERROR_NONE.
- selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
- default_store_->SetBlockAsyncRead(true);
- EXPECT_FALSE(read_error_delegate_data_.invoked);
- segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
- EXPECT_FALSE(read_error_delegate_data_.invoked);
- default_store_->SetBlockAsyncRead(false);
- // ReadErrorDelegate is not invoked for ERROR_NONE.
- EXPECT_FALSE(read_error_delegate_data_.invoked);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->GetReadError());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadNoFileError) {
- default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- segregated_store_->ReadPrefs());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) {
- default_store_->set_read_error(
- PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
- segregated_store_->ReadPrefs());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, BothPrefReadError) {
- default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
- selected_store_->set_read_error(
- PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- segregated_store_->ReadPrefs());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) {
- default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
- selected_store_->set_read_error(
- PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
- selected_store_->SetBlockAsyncRead(true);
- EXPECT_FALSE(read_error_delegate_data_.invoked);
- segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
- EXPECT_FALSE(read_error_delegate_data_.invoked);
- selected_store_->SetBlockAsyncRead(false);
- EXPECT_TRUE(read_error_delegate_data_.invoked);
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- segregated_store_->GetReadError());
- EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- segregated_store_->GetReadError());
- }
- TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) {
- EXPECT_FALSE(segregated_store_->IsInitializationComplete());
- segregated_store_->ReadPrefs();
- EXPECT_TRUE(segregated_store_->IsInitializationComplete());
- }
- TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) {
- selected_store_->SetBlockAsyncRead(true);
- default_store_->SetBlockAsyncRead(true);
- EXPECT_FALSE(segregated_store_->IsInitializationComplete());
- segregated_store_->ReadPrefsAsync(NULL);
- EXPECT_FALSE(segregated_store_->IsInitializationComplete());
- selected_store_->SetBlockAsyncRead(false);
- EXPECT_FALSE(segregated_store_->IsInitializationComplete());
- default_store_->SetBlockAsyncRead(false);
- EXPECT_TRUE(segregated_store_->IsInitializationComplete());
- }
- TEST_F(SegregatedPrefStoreTest, GetValues) {
- // To check merge behavior, create selected and default stores so each has a
- // key the other doesn't have and they have one key in common.
- selected_store_->SetValue(kSelectedPref,
- std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- default_store_->SetValue(kUnselectedPref,
- std::make_unique<base::Value>(kValue2),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- selected_store_->SetValue(kSharedPref, std::make_unique<base::Value>(kValue1),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- auto values = segregated_store_->GetValues();
- // Check that a selected preference is returned.
- const base::Value* value = values.Find(kSelectedPref);
- ASSERT_TRUE(value);
- EXPECT_EQ(base::Value(kValue1), *value);
- // Check that a a default preference is returned.
- value = values.Find(kUnselectedPref);
- ASSERT_TRUE(value);
- EXPECT_EQ(base::Value(kValue2), *value);
- // Check that the selected preference is preferred.
- value = values.Find(kSharedPref);
- ASSERT_TRUE(value);
- EXPECT_EQ(base::Value(kValue1), *value);
- }
- INSTANTIATE_TEST_SUITE_P(
- WithoutCallback,
- SegregatedPrefStoreTest,
- ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK));
- INSTANTIATE_TEST_SUITE_P(
- WithCallback,
- SegregatedPrefStoreTest,
- ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK));
- INSTANTIATE_TEST_SUITE_P(
- WithSynchronousCallback,
- SegregatedPrefStoreTest,
- ::testing::Values(CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK));
|