summaryrefslogtreecommitdiffstats
path: root/base/prefs
diff options
context:
space:
mode:
authorjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-14 17:20:19 +0000
committerjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-14 17:20:19 +0000
commite5ba874f019eb505a048ffb38aadf8bb5f495d7f (patch)
treecd845816e0959333555fc883d2fac49e3374fecc /base/prefs
parentad694eb0fddfdbcb74e31d13e473ce277c680ca8 (diff)
downloadchromium_src-e5ba874f019eb505a048ffb38aadf8bb5f495d7f.zip
chromium_src-e5ba874f019eb505a048ffb38aadf8bb5f495d7f.tar.gz
chromium_src-e5ba874f019eb505a048ffb38aadf8bb5f495d7f.tar.bz2
Moving last generic Prefs implementation files to base/prefs/.
This completes componentization of Prefs, although there are some remaining TODOs that were created during componentization and interface improvement that still need to be tackled. TBR=ben@chromium.org BUG=155525 Review URL: https://chromiumcodereview.appspot.com/12253004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182485 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/prefs')
-rw-r--r--base/prefs/pref_notifier_impl_unittest.cc227
-rw-r--r--base/prefs/pref_service_unittest.cc316
-rw-r--r--base/prefs/public/pref_change_registrar_unittest.cc2
-rw-r--r--base/prefs/public/pref_member_unittest.cc2
-rw-r--r--base/prefs/testing_pref_service.cc56
-rw-r--r--base/prefs/testing_pref_service.h196
6 files changed, 797 insertions, 2 deletions
diff --git a/base/prefs/pref_notifier_impl_unittest.cc b/base/prefs/pref_notifier_impl_unittest.cc
new file mode 100644
index 0000000..ff36ca8
--- /dev/null
+++ b/base/prefs/pref_notifier_impl_unittest.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2011 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 "base/bind.h"
+#include "base/callback.h"
+#include "base/prefs/mock_pref_change_callback.h"
+#include "base/prefs/pref_notifier_impl.h"
+#include "base/prefs/pref_observer.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/pref_value_store.h"
+#include "base/prefs/testing_pref_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Field;
+using testing::Invoke;
+using testing::Mock;
+using testing::Truly;
+
+namespace {
+
+const char kChangedPref[] = "changed_pref";
+const char kUnchangedPref[] = "unchanged_pref";
+
+class MockPrefInitObserver {
+ public:
+ MOCK_METHOD1(OnInitializationCompleted, void(bool));
+};
+
+// This is an unmodified PrefNotifierImpl, except we make
+// OnPreferenceChanged public for tests.
+class TestingPrefNotifierImpl : public PrefNotifierImpl {
+ public:
+ explicit TestingPrefNotifierImpl(PrefService* service)
+ : PrefNotifierImpl(service) {
+ }
+
+ // Make public for tests.
+ using PrefNotifierImpl::OnPreferenceChanged;
+};
+
+// Mock PrefNotifier that allows tracking of observers and notifications.
+class MockPrefNotifier : public PrefNotifierImpl {
+ public:
+ explicit MockPrefNotifier(PrefService* pref_service)
+ : PrefNotifierImpl(pref_service) {}
+ virtual ~MockPrefNotifier() {}
+
+ MOCK_METHOD1(FireObservers, void(const std::string& path));
+
+ size_t CountObserver(const char* path, PrefObserver* obs) {
+ PrefObserverMap::const_iterator observer_iterator =
+ pref_observers()->find(path);
+ if (observer_iterator == pref_observers()->end())
+ return false;
+
+ PrefObserverList* observer_list = observer_iterator->second;
+ PrefObserverList::Iterator it(*observer_list);
+ PrefObserver* existing_obs;
+ size_t count = 0;
+ while ((existing_obs = it.GetNext()) != NULL) {
+ if (existing_obs == obs)
+ count++;
+ }
+
+ return count;
+ }
+
+ // Make public for tests below.
+ using PrefNotifierImpl::OnPreferenceChanged;
+ using PrefNotifierImpl::OnInitializationCompleted;
+};
+
+class PrefObserverMock : public PrefObserver {
+ public:
+ PrefObserverMock() {}
+ virtual ~PrefObserverMock() {}
+
+ MOCK_METHOD2(OnPreferenceChanged, void(PrefServiceBase*, const std::string&));
+
+ void Expect(PrefServiceBase* prefs,
+ const std::string& pref_name,
+ const Value* value) {
+ EXPECT_CALL(*this, OnPreferenceChanged(prefs, pref_name))
+ .With(PrefValueMatches(prefs, pref_name, value));
+ }
+};
+
+// Test fixture class.
+class PrefNotifierTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ pref_service_.registry()->RegisterBooleanPref(kChangedPref, true);
+ pref_service_.registry()->RegisterBooleanPref(kUnchangedPref, true);
+ }
+
+ TestingPrefServiceSimple pref_service_;
+
+ PrefObserverMock obs1_;
+ PrefObserverMock obs2_;
+};
+
+TEST_F(PrefNotifierTest, OnPreferenceChanged) {
+ MockPrefNotifier notifier(&pref_service_);
+ EXPECT_CALL(notifier, FireObservers(kChangedPref)).Times(1);
+ notifier.OnPreferenceChanged(kChangedPref);
+}
+
+TEST_F(PrefNotifierTest, OnInitializationCompleted) {
+ MockPrefNotifier notifier(&pref_service_);
+ MockPrefInitObserver observer;
+ notifier.AddInitObserver(
+ base::Bind(&MockPrefInitObserver::OnInitializationCompleted,
+ base::Unretained(&observer)));
+ EXPECT_CALL(observer, OnInitializationCompleted(true));
+ notifier.OnInitializationCompleted(true);
+}
+
+TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
+ const char pref_name[] = "homepage";
+ const char pref_name2[] = "proxy";
+
+ MockPrefNotifier notifier(&pref_service_);
+ notifier.AddPrefObserver(pref_name, &obs1_);
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+
+ // Re-adding the same observer for the same pref doesn't change anything.
+ // Skip this in debug mode, since it hits a DCHECK and death tests aren't
+ // thread-safe.
+#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
+ notifier.AddPrefObserver(pref_name, &obs1_);
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+#endif
+
+ // Ensure that we can add the same observer to a different pref.
+ notifier.AddPrefObserver(pref_name2, &obs1_);
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+
+ // Ensure that we can add another observer to the same pref.
+ notifier.AddPrefObserver(pref_name, &obs2_);
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+
+ // Ensure that we can remove all observers, and that removing a non-existent
+ // observer is harmless.
+ notifier.RemovePrefObserver(pref_name, &obs1_);
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+
+ notifier.RemovePrefObserver(pref_name, &obs2_);
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+
+ notifier.RemovePrefObserver(pref_name, &obs1_);
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+
+ notifier.RemovePrefObserver(pref_name2, &obs1_);
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
+ ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
+}
+
+TEST_F(PrefNotifierTest, FireObservers) {
+ TestingPrefNotifierImpl notifier(&pref_service_);
+ notifier.AddPrefObserver(kChangedPref, &obs1_);
+ notifier.AddPrefObserver(kUnchangedPref, &obs1_);
+
+ EXPECT_CALL(obs1_, OnPreferenceChanged(&pref_service_, kChangedPref));
+ EXPECT_CALL(obs2_, OnPreferenceChanged(_, _)).Times(0);
+ notifier.OnPreferenceChanged(kChangedPref);
+ Mock::VerifyAndClearExpectations(&obs1_);
+ Mock::VerifyAndClearExpectations(&obs2_);
+
+ notifier.AddPrefObserver(kChangedPref, &obs2_);
+ notifier.AddPrefObserver(kUnchangedPref, &obs2_);
+
+ EXPECT_CALL(obs1_, OnPreferenceChanged(&pref_service_, kChangedPref));
+ EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref));
+ notifier.OnPreferenceChanged(kChangedPref);
+ Mock::VerifyAndClearExpectations(&obs1_);
+ Mock::VerifyAndClearExpectations(&obs2_);
+
+ // Make sure removing an observer from one pref doesn't affect anything else.
+ notifier.RemovePrefObserver(kChangedPref, &obs1_);
+
+ EXPECT_CALL(obs1_, OnPreferenceChanged(_, _)).Times(0);
+ EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref));
+ notifier.OnPreferenceChanged(kChangedPref);
+ Mock::VerifyAndClearExpectations(&obs1_);
+ Mock::VerifyAndClearExpectations(&obs2_);
+
+ // Make sure removing an observer entirely doesn't affect anything else.
+ notifier.RemovePrefObserver(kUnchangedPref, &obs1_);
+
+ EXPECT_CALL(obs1_, OnPreferenceChanged(_, _)).Times(0);
+ EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref));
+ notifier.OnPreferenceChanged(kChangedPref);
+ Mock::VerifyAndClearExpectations(&obs1_);
+ Mock::VerifyAndClearExpectations(&obs2_);
+
+ notifier.RemovePrefObserver(kChangedPref, &obs2_);
+ notifier.RemovePrefObserver(kUnchangedPref, &obs2_);
+}
+
+} // namespace
diff --git a/base/prefs/pref_service_unittest.cc b/base/prefs/pref_service_unittest.cc
new file mode 100644
index 0000000..0c61a8e
--- /dev/null
+++ b/base/prefs/pref_service_unittest.cc
@@ -0,0 +1,316 @@
+// Copyright (c) 2012 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 <string>
+
+#include "base/prefs/json_pref_store.h"
+#include "base/prefs/mock_pref_change_callback.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_value_store.h"
+#include "base/prefs/public/pref_change_registrar.h"
+#include "base/prefs/testing_pref_service.h"
+#include "base/prefs/testing_pref_store.h"
+#include "base/values.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Mock;
+
+const char kPrefName[] = "pref.name";
+
+TEST(PrefServiceTest, NoObserverFire) {
+ TestingPrefServiceSimple prefs;
+
+ const char pref_name[] = "homepage";
+ prefs.registry()->RegisterStringPref(pref_name, std::string());
+
+ const char new_pref_value[] = "http://www.google.com/";
+ MockPrefChangeCallback obs(&prefs);
+ PrefChangeRegistrar registrar;
+ registrar.Init(&prefs);
+ registrar.Add(pref_name, obs.GetCallback());
+
+ // This should fire the checks in MockPrefChangeCallback::OnPreferenceChanged.
+ const StringValue expected_value(new_pref_value);
+ obs.Expect(pref_name, &expected_value);
+ prefs.SetString(pref_name, new_pref_value);
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Setting the pref to the same value should not set the pref value a second
+ // time.
+ EXPECT_CALL(obs, OnPreferenceChanged(_)).Times(0);
+ prefs.SetString(pref_name, new_pref_value);
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Clearing the pref should cause the pref to fire.
+ const StringValue expected_default_value("");
+ obs.Expect(pref_name, &expected_default_value);
+ prefs.ClearPref(pref_name);
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Clearing the pref again should not cause the pref to fire.
+ EXPECT_CALL(obs, OnPreferenceChanged(_)).Times(0);
+ prefs.ClearPref(pref_name);
+ Mock::VerifyAndClearExpectations(&obs);
+}
+
+TEST(PrefServiceTest, HasPrefPath) {
+ TestingPrefServiceSimple prefs;
+
+ const char path[] = "fake.path";
+
+ // Shouldn't initially have a path.
+ EXPECT_FALSE(prefs.HasPrefPath(path));
+
+ // Register the path. This doesn't set a value, so the path still shouldn't
+ // exist.
+ prefs.registry()->RegisterStringPref(path, std::string());
+ EXPECT_FALSE(prefs.HasPrefPath(path));
+
+ // Set a value and make sure we have a path.
+ prefs.SetString(path, "blah");
+ EXPECT_TRUE(prefs.HasPrefPath(path));
+}
+
+TEST(PrefServiceTest, Observers) {
+ const char pref_name[] = "homepage";
+
+ TestingPrefServiceSimple prefs;
+ prefs.SetUserPref(pref_name, Value::CreateStringValue("http://www.cnn.com"));
+ prefs.registry()->RegisterStringPref(pref_name, std::string());
+
+ const char new_pref_value[] = "http://www.google.com/";
+ const StringValue expected_new_pref_value(new_pref_value);
+ MockPrefChangeCallback obs(&prefs);
+ PrefChangeRegistrar registrar;
+ registrar.Init(&prefs);
+ registrar.Add(pref_name, obs.GetCallback());
+
+ PrefChangeRegistrar registrar_two;
+ registrar_two.Init(&prefs);
+
+ // This should fire the checks in MockPrefChangeCallback::OnPreferenceChanged.
+ obs.Expect(pref_name, &expected_new_pref_value);
+ prefs.SetString(pref_name, new_pref_value);
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Now try adding a second pref observer.
+ const char new_pref_value2[] = "http://www.youtube.com/";
+ const StringValue expected_new_pref_value2(new_pref_value2);
+ MockPrefChangeCallback obs2(&prefs);
+ obs.Expect(pref_name, &expected_new_pref_value2);
+ obs2.Expect(pref_name, &expected_new_pref_value2);
+ registrar_two.Add(pref_name, obs2.GetCallback());
+ // This should fire the checks in obs and obs2.
+ prefs.SetString(pref_name, new_pref_value2);
+ Mock::VerifyAndClearExpectations(&obs);
+ Mock::VerifyAndClearExpectations(&obs2);
+
+ // Set a recommended value.
+ const StringValue recommended_pref_value("http://www.gmail.com/");
+ obs.Expect(pref_name, &expected_new_pref_value2);
+ obs2.Expect(pref_name, &expected_new_pref_value2);
+ // This should fire the checks in obs and obs2 but with an unchanged value
+ // as the recommended value is being overridden by the user-set value.
+ prefs.SetRecommendedPref(pref_name, recommended_pref_value.DeepCopy());
+ Mock::VerifyAndClearExpectations(&obs);
+ Mock::VerifyAndClearExpectations(&obs2);
+
+ // Make sure obs2 still works after removing obs.
+ registrar.Remove(pref_name);
+ EXPECT_CALL(obs, OnPreferenceChanged(_)).Times(0);
+ obs2.Expect(pref_name, &expected_new_pref_value);
+ // This should only fire the observer in obs2.
+ prefs.SetString(pref_name, new_pref_value);
+ Mock::VerifyAndClearExpectations(&obs);
+ Mock::VerifyAndClearExpectations(&obs2);
+}
+
+// Make sure that if a preference changes type, so the wrong type is stored in
+// the user pref file, it uses the correct fallback value instead.
+TEST(PrefServiceTest, GetValueChangedType) {
+ const int kTestValue = 10;
+ TestingPrefServiceSimple prefs;
+ prefs.registry()->RegisterIntegerPref(kPrefName, kTestValue);
+
+ // Check falling back to a recommended value.
+ prefs.SetUserPref(kPrefName, Value::CreateStringValue("not an integer"));
+ const PrefService::Preference* pref = prefs.FindPreference(kPrefName);
+ ASSERT_TRUE(pref);
+ const Value* value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ int actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kTestValue, actual_int_value);
+}
+
+TEST(PrefServiceTest, GetValueAndGetRecommendedValue) {
+ const int kDefaultValue = 5;
+ const int kUserValue = 10;
+ const int kRecommendedValue = 15;
+ TestingPrefServiceSimple prefs;
+ prefs.registry()->RegisterIntegerPref(kPrefName, kDefaultValue);
+
+ // Create pref with a default value only.
+ const PrefService::Preference* pref = prefs.FindPreference(kPrefName);
+ ASSERT_TRUE(pref);
+
+ // Check that GetValue() returns the default value.
+ const Value* value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ int actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kDefaultValue, actual_int_value);
+
+ // Check that GetRecommendedValue() returns no value.
+ value = pref->GetRecommendedValue();
+ ASSERT_FALSE(value);
+
+ // Set a user-set value.
+ prefs.SetUserPref(kPrefName, Value::CreateIntegerValue(kUserValue));
+
+ // Check that GetValue() returns the user-set value.
+ value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kUserValue, actual_int_value);
+
+ // Check that GetRecommendedValue() returns no value.
+ value = pref->GetRecommendedValue();
+ ASSERT_FALSE(value);
+
+ // Set a recommended value.
+ prefs.SetRecommendedPref(kPrefName,
+ Value::CreateIntegerValue(kRecommendedValue));
+
+ // Check that GetValue() returns the user-set value.
+ value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kUserValue, actual_int_value);
+
+ // Check that GetRecommendedValue() returns the recommended value.
+ value = pref->GetRecommendedValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kRecommendedValue, actual_int_value);
+
+ // Remove the user-set value.
+ prefs.RemoveUserPref(kPrefName);
+
+ // Check that GetValue() returns the recommended value.
+ value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kRecommendedValue, actual_int_value);
+
+ // Check that GetRecommendedValue() returns the recommended value.
+ value = pref->GetRecommendedValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kRecommendedValue, actual_int_value);
+}
+
+class PrefServiceSetValueTest : public testing::Test {
+ protected:
+ static const char kName[];
+ static const char kValue[];
+
+ PrefServiceSetValueTest() : observer_(&prefs_) {}
+
+ TestingPrefServiceSimple prefs_;
+ MockPrefChangeCallback observer_;
+};
+
+const char PrefServiceSetValueTest::kName[] = "name";
+const char PrefServiceSetValueTest::kValue[] = "value";
+
+TEST_F(PrefServiceSetValueTest, SetStringValue) {
+ const char default_string[] = "default";
+ const StringValue default_value(default_string);
+ prefs_.registry()->RegisterStringPref(kName, default_string);
+
+ PrefChangeRegistrar registrar;
+ registrar.Init(&prefs_);
+ registrar.Add(kName, observer_.GetCallback());
+
+ // Changing the controlling store from default to user triggers notification.
+ observer_.Expect(kName, &default_value);
+ prefs_.Set(kName, default_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ EXPECT_CALL(observer_, OnPreferenceChanged(_)).Times(0);
+ prefs_.Set(kName, default_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ StringValue new_value(kValue);
+ observer_.Expect(kName, &new_value);
+ prefs_.Set(kName, new_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+}
+
+TEST_F(PrefServiceSetValueTest, SetDictionaryValue) {
+ prefs_.registry()->RegisterDictionaryPref(kName);
+ PrefChangeRegistrar registrar;
+ registrar.Init(&prefs_);
+ registrar.Add(kName, observer_.GetCallback());
+
+ EXPECT_CALL(observer_, OnPreferenceChanged(_)).Times(0);
+ prefs_.RemoveUserPref(kName);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ DictionaryValue new_value;
+ new_value.SetString(kName, kValue);
+ observer_.Expect(kName, &new_value);
+ prefs_.Set(kName, new_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ EXPECT_CALL(observer_, OnPreferenceChanged(_)).Times(0);
+ prefs_.Set(kName, new_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ DictionaryValue empty;
+ observer_.Expect(kName, &empty);
+ prefs_.Set(kName, empty);
+ Mock::VerifyAndClearExpectations(&observer_);
+}
+
+TEST_F(PrefServiceSetValueTest, SetListValue) {
+ prefs_.registry()->RegisterListPref(kName);
+ PrefChangeRegistrar registrar;
+ registrar.Init(&prefs_);
+ registrar.Add(kName, observer_.GetCallback());
+
+ EXPECT_CALL(observer_, OnPreferenceChanged(_)).Times(0);
+ prefs_.RemoveUserPref(kName);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ ListValue new_value;
+ new_value.Append(Value::CreateStringValue(kValue));
+ observer_.Expect(kName, &new_value);
+ prefs_.Set(kName, new_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ EXPECT_CALL(observer_, OnPreferenceChanged(_)).Times(0);
+ prefs_.Set(kName, new_value);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ ListValue empty;
+ observer_.Expect(kName, &empty);
+ prefs_.Set(kName, empty);
+ Mock::VerifyAndClearExpectations(&observer_);
+}
diff --git a/base/prefs/public/pref_change_registrar_unittest.cc b/base/prefs/public/pref_change_registrar_unittest.cc
index 5e1ad5f..b29f43a 100644
--- a/base/prefs/public/pref_change_registrar_unittest.cc
+++ b/base/prefs/public/pref_change_registrar_unittest.cc
@@ -7,7 +7,7 @@
#include "base/prefs/pref_observer.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/public/pref_change_registrar.h"
-#include "chrome/test/base/testing_pref_service.h"
+#include "base/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/base/prefs/public/pref_member_unittest.cc b/base/prefs/public/pref_member_unittest.cc
index 5f1c3f1..2a68059 100644
--- a/base/prefs/public/pref_member_unittest.cc
+++ b/base/prefs/public/pref_member_unittest.cc
@@ -7,9 +7,9 @@
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/testing_pref_service.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
-#include "chrome/test/base/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
diff --git a/base/prefs/testing_pref_service.cc b/base/prefs/testing_pref_service.cc
new file mode 100644
index 0000000..22755da
--- /dev/null
+++ b/base/prefs/testing_pref_service.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 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 "base/prefs/testing_pref_service.h"
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/prefs/default_pref_store.h"
+#include "base/prefs/pref_notifier_impl.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_value_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+template<>
+TestingPrefServiceBase<PrefService, PrefRegistry>::TestingPrefServiceBase(
+ TestingPrefStore* managed_prefs,
+ TestingPrefStore* user_prefs,
+ TestingPrefStore* recommended_prefs,
+ PrefRegistry* pref_registry,
+ PrefNotifierImpl* pref_notifier)
+ : PrefService(pref_notifier,
+ new PrefValueStore(
+ managed_prefs,
+ NULL,
+ NULL,
+ user_prefs,
+ recommended_prefs,
+ pref_registry->defaults(),
+ pref_notifier),
+ user_prefs,
+ pref_registry,
+ base::Bind(
+ &TestingPrefServiceBase<
+ PrefService, PrefRegistry>::HandleReadError),
+ false),
+ managed_prefs_(managed_prefs),
+ user_prefs_(user_prefs),
+ recommended_prefs_(recommended_prefs) {
+}
+
+TestingPrefServiceSimple::TestingPrefServiceSimple()
+ : TestingPrefServiceBase<PrefService, PrefRegistry>(
+ new TestingPrefStore(),
+ new TestingPrefStore(),
+ new TestingPrefStore(),
+ new PrefRegistrySimple(),
+ new PrefNotifierImpl()) {
+}
+
+TestingPrefServiceSimple::~TestingPrefServiceSimple() {
+}
+
+PrefRegistrySimple* TestingPrefServiceSimple::registry() {
+ return static_cast<PrefRegistrySimple*>(DeprecatedGetPrefRegistry());
+}
diff --git a/base/prefs/testing_pref_service.h b/base/prefs/testing_pref_service.h
new file mode 100644
index 0000000..9d290fe
--- /dev/null
+++ b/base/prefs/testing_pref_service.h
@@ -0,0 +1,196 @@
+// Copyright (c) 2012 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.
+
+#ifndef BASE_PREFS_TESTING_PREF_SERVICE_H_
+#define BASE_PREFS_TESTING_PREF_SERVICE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_registry.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/testing_pref_store.h"
+
+class PrefNotifierImpl;
+class PrefRegistrySimple;
+class TestingPrefStore;
+
+// A PrefService subclass for testing. It operates totally in memory and
+// provides additional API for manipulating preferences at the different levels
+// (managed, extension, user) conveniently.
+//
+// Use this via its specializations, e.g. TestingPrefServiceSimple.
+template <class SuperPrefService, class ConstructionPrefRegistry>
+class TestingPrefServiceBase : public SuperPrefService {
+ public:
+ virtual ~TestingPrefServiceBase();
+
+ // Read the value of a preference from the managed layer. Returns NULL if the
+ // preference is not defined at the managed layer.
+ const Value* GetManagedPref(const char* path) const;
+
+ // Set a preference on the managed layer and fire observers if the preference
+ // changed. Assumes ownership of |value|.
+ void SetManagedPref(const char* path, Value* value);
+
+ // Clear the preference on the managed layer and fire observers if the
+ // preference has been defined previously.
+ void RemoveManagedPref(const char* path);
+
+ // Similar to the above, but for user preferences.
+ const Value* GetUserPref(const char* path) const;
+ void SetUserPref(const char* path, Value* value);
+ void RemoveUserPref(const char* path);
+
+ // Similar to the above, but for recommended policy preferences.
+ const Value* GetRecommendedPref(const char* path) const;
+ void SetRecommendedPref(const char* path, Value* value);
+ void RemoveRecommendedPref(const char* path);
+
+ // Do-nothing implementation for TestingPrefService.
+ static void HandleReadError(PersistentPrefStore::PrefReadError error) {}
+
+ protected:
+ TestingPrefServiceBase(
+ TestingPrefStore* managed_prefs,
+ TestingPrefStore* user_prefs,
+ TestingPrefStore* recommended_prefs,
+ ConstructionPrefRegistry* pref_registry,
+ PrefNotifierImpl* pref_notifier);
+
+ private:
+ // Reads the value of the preference indicated by |path| from |pref_store|.
+ // Returns NULL if the preference was not found.
+ const Value* GetPref(TestingPrefStore* pref_store, const char* path) const;
+
+ // Sets the value for |path| in |pref_store|.
+ void SetPref(TestingPrefStore* pref_store, const char* path, Value* value);
+
+ // Removes the preference identified by |path| from |pref_store|.
+ void RemovePref(TestingPrefStore* pref_store, const char* path);
+
+ // Pointers to the pref stores our value store uses.
+ scoped_refptr<TestingPrefStore> managed_prefs_;
+ scoped_refptr<TestingPrefStore> user_prefs_;
+ scoped_refptr<TestingPrefStore> recommended_prefs_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestingPrefServiceBase);
+};
+
+// Test version of PrefService.
+class TestingPrefServiceSimple
+ : public TestingPrefServiceBase<PrefService, PrefRegistry> {
+ public:
+ TestingPrefServiceSimple();
+ virtual ~TestingPrefServiceSimple();
+
+ // This is provided as a convenience for registering preferences on
+ // an existing TestingPrefServiceSimple instance. On a production
+ // PrefService you would do all registrations before constructing
+ // it, passing it a PrefRegistry via its constructor (or via
+ // e.g. PrefServiceBuilder).
+ PrefRegistrySimple* registry();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestingPrefServiceSimple);
+};
+
+template<>
+TestingPrefServiceBase<PrefService, PrefRegistry>::TestingPrefServiceBase(
+ TestingPrefStore* managed_prefs,
+ TestingPrefStore* user_prefs,
+ TestingPrefStore* recommended_prefs,
+ PrefRegistry* pref_registry,
+ PrefNotifierImpl* pref_notifier);
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::~TestingPrefServiceBase() {
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+const Value* TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::GetManagedPref(
+ const char* path) const {
+ return GetPref(managed_prefs_, path);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::SetManagedPref(
+ const char* path, Value* value) {
+ SetPref(managed_prefs_, path, value);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::RemoveManagedPref(
+ const char* path) {
+ RemovePref(managed_prefs_, path);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+const Value* TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::GetUserPref(
+ const char* path) const {
+ return GetPref(user_prefs_, path);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::SetUserPref(
+ const char* path, Value* value) {
+ SetPref(user_prefs_, path, value);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::RemoveUserPref(
+ const char* path) {
+ RemovePref(user_prefs_, path);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+const Value* TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::GetRecommendedPref(
+ const char* path) const {
+ return GetPref(recommended_prefs_, path);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::SetRecommendedPref(
+ const char* path, Value* value) {
+ SetPref(recommended_prefs_, path, value);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::RemoveRecommendedPref(
+ const char* path) {
+ RemovePref(recommended_prefs_, path);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+const Value* TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::GetPref(
+ TestingPrefStore* pref_store, const char* path) const {
+ const Value* res;
+ return pref_store->GetValue(path, &res) ? res : NULL;
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::SetPref(
+ TestingPrefStore* pref_store, const char* path, Value* value) {
+ pref_store->SetValue(path, value);
+}
+
+template<class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<
+ SuperPrefService, ConstructionPrefRegistry>::RemovePref(
+ TestingPrefStore* pref_store, const char* path) {
+ pref_store->RemoveValue(path);
+}
+
+#endif // BASE_PREFS_TESTING_PREF_SERVICE_H_