// Copyright (c) 2010 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 #include "app/test/data/resource.h" #include "base/scoped_ptr.h" #include "base/values.h" #include "chrome/browser/dummy_pref_store.h" #include "chrome/browser/pref_value_store.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/notification_observer_mock.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" #include "chrome/test/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::_; using testing::Mock; using testing::Pointee; using testing::Property; class TestPrefObserver : public NotificationObserver { public: TestPrefObserver(const PrefService* prefs, const std::wstring& pref_name, const std::string& new_pref_value) : observer_fired_(false), prefs_(prefs), pref_name_(pref_name), new_pref_value_(new_pref_value) { } virtual ~TestPrefObserver() {} virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { EXPECT_EQ(type.value, NotificationType::PREF_CHANGED); PrefService* prefs_in = Source(source).ptr(); EXPECT_EQ(prefs_in, prefs_); std::wstring* pref_name_in = Details(details).ptr(); EXPECT_EQ(*pref_name_in, pref_name_); EXPECT_EQ(new_pref_value_, prefs_in->GetString(L"homepage")); observer_fired_ = true; } bool observer_fired() { return observer_fired_; } void Reset(const std::string& new_pref_value) { observer_fired_ = false; new_pref_value_ = new_pref_value; } private: bool observer_fired_; const PrefService* prefs_; const std::wstring pref_name_; std::string new_pref_value_; }; // TODO(port): port this test to POSIX. #if defined(OS_WIN) TEST(PrefServiceTest, LocalizedPrefs) { TestingPrefService prefs; const wchar_t kBoolean[] = L"boolean"; const wchar_t kInteger[] = L"integer"; const wchar_t kString[] = L"string"; prefs.RegisterLocalizedBooleanPref(kBoolean, IDS_LOCALE_BOOL); prefs.RegisterLocalizedIntegerPref(kInteger, IDS_LOCALE_INT); prefs.RegisterLocalizedStringPref(kString, IDS_LOCALE_STRING); // The locale default should take preference over the user default. EXPECT_FALSE(prefs.GetBoolean(kBoolean)); EXPECT_EQ(1, prefs.GetInteger(kInteger)); EXPECT_EQ("hello", prefs.GetString(kString)); prefs.SetBoolean(kBoolean, true); EXPECT_TRUE(prefs.GetBoolean(kBoolean)); prefs.SetInteger(kInteger, 5); EXPECT_EQ(5, prefs.GetInteger(kInteger)); prefs.SetString(kString, "foo"); EXPECT_EQ("foo", prefs.GetString(kString)); } #endif TEST(PrefServiceTest, NoObserverFire) { TestingPrefService prefs; const wchar_t pref_name[] = L"homepage"; prefs.RegisterStringPref(pref_name, ""); const std::string new_pref_value("http://www.google.com/"); TestPrefObserver obs(&prefs, pref_name, new_pref_value); prefs.AddPrefObserver(pref_name, &obs); // This should fire the checks in TestPrefObserver::Observe. prefs.SetString(pref_name, new_pref_value); // Make sure the observer was actually fired. EXPECT_TRUE(obs.observer_fired()); // Setting the pref to the same value should not set the pref value a second // time. obs.Reset(new_pref_value); prefs.SetString(pref_name, new_pref_value); EXPECT_FALSE(obs.observer_fired()); // Clearing the pref should cause the pref to fire. obs.Reset(""); prefs.ClearPref(pref_name); EXPECT_TRUE(obs.observer_fired()); // Clearing the pref again should not cause the pref to fire. obs.Reset(""); prefs.ClearPref(pref_name); EXPECT_FALSE(obs.observer_fired()); // Ok, clean up. prefs.RemovePrefObserver(pref_name, &obs); } TEST(PrefServiceTest, HasPrefPath) { TestingPrefService prefs; const wchar_t path[] = L"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.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 wchar_t pref_name[] = L"homepage"; TestingPrefService prefs; prefs.SetUserPref(pref_name, Value::CreateStringValue(L"http://www.cnn.com")); prefs.RegisterStringPref(pref_name, ""); const std::string new_pref_value("http://www.google.com/"); TestPrefObserver obs(&prefs, pref_name, new_pref_value); prefs.AddPrefObserver(pref_name, &obs); // This should fire the checks in TestPrefObserver::Observe. prefs.SetString(pref_name, new_pref_value); // Make sure the tests were actually run. EXPECT_TRUE(obs.observer_fired()); // Now try adding a second pref observer. const std::string new_pref_value2("http://www.youtube.com/"); obs.Reset(new_pref_value2); TestPrefObserver obs2(&prefs, pref_name, new_pref_value2); prefs.AddPrefObserver(pref_name, &obs2); // This should fire the checks in obs and obs2. prefs.SetString(pref_name, new_pref_value2); EXPECT_TRUE(obs.observer_fired()); EXPECT_TRUE(obs2.observer_fired()); // Make sure obs2 still works after removing obs. prefs.RemovePrefObserver(pref_name, &obs); obs.Reset(""); obs2.Reset(new_pref_value); // This should only fire the observer in obs2. prefs.SetString(pref_name, new_pref_value); EXPECT_FALSE(obs.observer_fired()); EXPECT_TRUE(obs2.observer_fired()); // Ok, clean up. prefs.RemovePrefObserver(pref_name, &obs2); } class PrefServiceSetValueTest : public testing::Test { protected: static const wchar_t name_[]; static const char value_[]; PrefServiceSetValueTest() : name_string_(name_), null_value_(Value::CreateNullValue()) {} void SetExpectNoNotification() { EXPECT_CALL(observer_, Observe(_, _, _)).Times(0); } void SetExpectPrefChanged() { EXPECT_CALL(observer_, Observe(NotificationType(NotificationType::PREF_CHANGED), _, Property(&Details::ptr, Pointee(name_string_)))); } TestingPrefService prefs_; std::wstring name_string_; scoped_ptr null_value_; NotificationObserverMock observer_; }; const wchar_t PrefServiceSetValueTest::name_[] = L"name"; const char PrefServiceSetValueTest::value_[] = "value"; TEST_F(PrefServiceSetValueTest, SetStringValue) { const char default_string[] = "default"; scoped_ptr default_value(Value::CreateStringValue(default_string)); prefs_.RegisterStringPref(name_, default_string); prefs_.AddPrefObserver(name_, &observer_); SetExpectNoNotification(); prefs_.Set(name_, *default_value); Mock::VerifyAndClearExpectations(&observer_); scoped_ptr new_value(Value::CreateStringValue(value_)); SetExpectPrefChanged(); prefs_.Set(name_, *new_value); EXPECT_EQ(value_, prefs_.GetString(name_)); prefs_.RemovePrefObserver(name_, &observer_); } TEST_F(PrefServiceSetValueTest, SetDictionaryValue) { prefs_.RegisterDictionaryPref(name_); prefs_.AddPrefObserver(name_, &observer_); SetExpectNoNotification(); prefs_.Set(name_, *null_value_); Mock::VerifyAndClearExpectations(&observer_); DictionaryValue new_value; new_value.SetString(name_, value_); SetExpectPrefChanged(); prefs_.Set(name_, new_value); Mock::VerifyAndClearExpectations(&observer_); DictionaryValue* dict = prefs_.GetMutableDictionary(name_); EXPECT_EQ(1U, dict->size()); std::string out_value; dict->GetString(name_, &out_value); EXPECT_EQ(value_, out_value); SetExpectNoNotification(); prefs_.Set(name_, new_value); Mock::VerifyAndClearExpectations(&observer_); SetExpectPrefChanged(); prefs_.Set(name_, *null_value_); Mock::VerifyAndClearExpectations(&observer_); dict = prefs_.GetMutableDictionary(name_); EXPECT_EQ(0U, dict->size()); prefs_.RemovePrefObserver(name_, &observer_); } TEST_F(PrefServiceSetValueTest, SetListValue) { prefs_.RegisterListPref(name_); prefs_.AddPrefObserver(name_, &observer_); SetExpectNoNotification(); prefs_.Set(name_, *null_value_); Mock::VerifyAndClearExpectations(&observer_); ListValue new_value; new_value.Append(Value::CreateStringValue(value_)); SetExpectPrefChanged(); prefs_.Set(name_, new_value); Mock::VerifyAndClearExpectations(&observer_); ListValue* list = prefs_.GetMutableList(name_); ASSERT_EQ(1U, list->GetSize()); std::string out_value; list->GetString(0, &out_value); EXPECT_EQ(value_, out_value); SetExpectNoNotification(); prefs_.Set(name_, new_value); Mock::VerifyAndClearExpectations(&observer_); SetExpectPrefChanged(); prefs_.Set(name_, *null_value_); Mock::VerifyAndClearExpectations(&observer_); list = prefs_.GetMutableList(name_); EXPECT_EQ(0U, list->GetSize()); prefs_.RemovePrefObserver(name_, &observer_); }