Home | History | Annotate | Download | only in prefs
      1 // Copyright (c) 2010 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.
      4 
      5 #include "chrome/browser/prefs/pref_notifier_impl.h"
      6 #include "chrome/browser/prefs/pref_observer_mock.h"
      7 #include "chrome/browser/prefs/pref_service.h"
      8 #include "chrome/browser/prefs/pref_value_store.h"
      9 #include "chrome/test/testing_pref_service.h"
     10 #include "content/common/notification_observer_mock.h"
     11 #include "content/common/notification_registrar.h"
     12 #include "content/common/notification_service.h"
     13 #include "testing/gmock/include/gmock/gmock.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 using testing::_;
     17 using testing::Field;
     18 using testing::Invoke;
     19 using testing::Mock;
     20 using testing::Truly;
     21 
     22 namespace {
     23 
     24 const char kChangedPref[] = "changed_pref";
     25 const char kUnchangedPref[] = "unchanged_pref";
     26 
     27 bool DetailsAreChangedPref(const Details<std::string>& details) {
     28   std::string* string_in = Details<std::string>(details).ptr();
     29   return strcmp(string_in->c_str(), kChangedPref) == 0;
     30 }
     31 
     32 // Test PrefNotifier that allows tracking of observers and notifications.
     33 class MockPrefNotifier : public PrefNotifierImpl {
     34  public:
     35   explicit MockPrefNotifier(PrefService* pref_service)
     36       : PrefNotifierImpl(pref_service) {}
     37   virtual ~MockPrefNotifier() {}
     38 
     39   MOCK_METHOD1(FireObservers, void(const std::string& path));
     40 
     41   size_t CountObserver(const char* path, NotificationObserver* obs) {
     42     PrefObserverMap::const_iterator observer_iterator =
     43         pref_observers()->find(path);
     44     if (observer_iterator == pref_observers()->end())
     45       return false;
     46 
     47     NotificationObserverList* observer_list = observer_iterator->second;
     48     NotificationObserverList::Iterator it(*observer_list);
     49     NotificationObserver* existing_obs;
     50     size_t count = 0;
     51     while ((existing_obs = it.GetNext()) != NULL) {
     52       if (existing_obs == obs)
     53         count++;
     54     }
     55 
     56     return count;
     57   }
     58 };
     59 
     60 // Test fixture class.
     61 class PrefNotifierTest : public testing::Test {
     62  protected:
     63   virtual void SetUp() {
     64     pref_service_.RegisterBooleanPref(kChangedPref, true);
     65     pref_service_.RegisterBooleanPref(kUnchangedPref, true);
     66   }
     67 
     68   TestingPrefService pref_service_;
     69 
     70   PrefObserverMock obs1_;
     71   PrefObserverMock obs2_;
     72 };
     73 
     74 TEST_F(PrefNotifierTest, OnPreferenceChanged) {
     75   MockPrefNotifier notifier(&pref_service_);
     76   EXPECT_CALL(notifier, FireObservers(kChangedPref)).Times(1);
     77   notifier.OnPreferenceChanged(kChangedPref);
     78 }
     79 
     80 TEST_F(PrefNotifierTest, OnInitializationCompleted) {
     81   MockPrefNotifier notifier(&pref_service_);
     82   NotificationObserverMock observer;
     83   NotificationRegistrar registrar;
     84   registrar.Add(&observer, NotificationType::PREF_INITIALIZATION_COMPLETED,
     85                 Source<PrefService>(&pref_service_));
     86   EXPECT_CALL(observer, Observe(
     87       Field(&NotificationType::value,
     88             NotificationType::PREF_INITIALIZATION_COMPLETED),
     89       Source<PrefService>(&pref_service_),
     90       NotificationService::NoDetails()));
     91   notifier.OnInitializationCompleted();
     92 }
     93 
     94 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
     95   const char pref_name[] = "homepage";
     96   const char pref_name2[] = "proxy";
     97 
     98   MockPrefNotifier notifier(&pref_service_);
     99   notifier.AddPrefObserver(pref_name, &obs1_);
    100   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
    101   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
    102   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
    103   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    104 
    105   // Re-adding the same observer for the same pref doesn't change anything.
    106   // Skip this in debug mode, since it hits a DCHECK and death tests aren't
    107   // thread-safe.
    108 #if defined(NDEBUG)
    109   notifier.AddPrefObserver(pref_name, &obs1_);
    110   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
    111   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
    112   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
    113   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    114 #endif  // NDEBUG
    115 
    116   // Ensure that we can add the same observer to a different pref.
    117   notifier.AddPrefObserver(pref_name2, &obs1_);
    118   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
    119   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
    120   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
    121   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    122 
    123   // Ensure that we can add another observer to the same pref.
    124   notifier.AddPrefObserver(pref_name, &obs2_);
    125   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
    126   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
    127   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
    128   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    129 
    130   // Ensure that we can remove all observers, and that removing a non-existent
    131   // observer is harmless.
    132   notifier.RemovePrefObserver(pref_name, &obs1_);
    133   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
    134   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
    135   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
    136   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    137 
    138   notifier.RemovePrefObserver(pref_name, &obs2_);
    139   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
    140   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
    141   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
    142   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    143 
    144   notifier.RemovePrefObserver(pref_name, &obs1_);
    145   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
    146   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
    147   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
    148   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    149 
    150   notifier.RemovePrefObserver(pref_name2, &obs1_);
    151   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
    152   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
    153   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
    154   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
    155 }
    156 
    157 TEST_F(PrefNotifierTest, FireObservers) {
    158   FundamentalValue value_true(true);
    159   PrefNotifierImpl notifier(&pref_service_);
    160   notifier.AddPrefObserver(kChangedPref, &obs1_);
    161   notifier.AddPrefObserver(kUnchangedPref, &obs1_);
    162 
    163   obs1_.Expect(&pref_service_, kChangedPref, &value_true);
    164   EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
    165   notifier.OnPreferenceChanged(kChangedPref);
    166   Mock::VerifyAndClearExpectations(&obs1_);
    167   Mock::VerifyAndClearExpectations(&obs2_);
    168 
    169   notifier.AddPrefObserver(kChangedPref, &obs2_);
    170   notifier.AddPrefObserver(kUnchangedPref, &obs2_);
    171 
    172   obs1_.Expect(&pref_service_, kChangedPref, &value_true);
    173   obs2_.Expect(&pref_service_, kChangedPref, &value_true);
    174   notifier.OnPreferenceChanged(kChangedPref);
    175   Mock::VerifyAndClearExpectations(&obs1_);
    176   Mock::VerifyAndClearExpectations(&obs2_);
    177 
    178   // Make sure removing an observer from one pref doesn't affect anything else.
    179   notifier.RemovePrefObserver(kChangedPref, &obs1_);
    180 
    181   EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
    182   obs2_.Expect(&pref_service_, kChangedPref, &value_true);
    183   notifier.OnPreferenceChanged(kChangedPref);
    184   Mock::VerifyAndClearExpectations(&obs1_);
    185   Mock::VerifyAndClearExpectations(&obs2_);
    186 
    187   // Make sure removing an observer entirely doesn't affect anything else.
    188   notifier.RemovePrefObserver(kUnchangedPref, &obs1_);
    189 
    190   EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
    191   obs2_.Expect(&pref_service_, kChangedPref, &value_true);
    192   notifier.OnPreferenceChanged(kChangedPref);
    193   Mock::VerifyAndClearExpectations(&obs1_);
    194   Mock::VerifyAndClearExpectations(&obs2_);
    195 
    196   notifier.RemovePrefObserver(kChangedPref, &obs2_);
    197   notifier.RemovePrefObserver(kUnchangedPref, &obs2_);
    198 }
    199 
    200 }  // namespace
    201