1// Copyright (c) 2011 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_member.h" 6 7#include "base/message_loop.h" 8#include "chrome/browser/prefs/pref_value_store.h" 9#include "chrome/test/testing_pref_service.h" 10#include "content/browser/browser_thread.h" 11#include "content/common/notification_details.h" 12#include "content/common/notification_source.h" 13#include "content/common/notification_type.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16namespace { 17 18const char kBoolPref[] = "bool"; 19const char kIntPref[] = "int"; 20const char kDoublePref[] = "double"; 21const char kStringPref[] = "string"; 22const char kListPref[] = "list"; 23 24void RegisterTestPrefs(PrefService* prefs) { 25 prefs->RegisterBooleanPref(kBoolPref, false); 26 prefs->RegisterIntegerPref(kIntPref, 0); 27 prefs->RegisterDoublePref(kDoublePref, 0.0); 28 prefs->RegisterStringPref(kStringPref, "default"); 29 prefs->RegisterListPref(kListPref); 30} 31 32class GetPrefValueCallback 33 : public base::RefCountedThreadSafe<GetPrefValueCallback> { 34 public: 35 GetPrefValueCallback() : value_(false) {} 36 37 void Init(const char* pref_name, PrefService* prefs) { 38 pref_.Init(pref_name, prefs, NULL); 39 pref_.MoveToThread(BrowserThread::IO); 40 } 41 42 bool FetchValue() { 43 if (!BrowserThread::PostTask( 44 BrowserThread::IO, FROM_HERE, 45 NewRunnableMethod(this, 46 &GetPrefValueCallback::GetPrefValueOnIOThread))) { 47 return false; 48 } 49 MessageLoop::current()->Run(); 50 return true; 51 } 52 53 bool value() { return value_; } 54 55 private: 56 friend class base::RefCountedThreadSafe<GetPrefValueCallback>; 57 ~GetPrefValueCallback() {} 58 59 void GetPrefValueOnIOThread() { 60 value_ = pref_.GetValue(); 61 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 62 new MessageLoop::QuitTask()); 63 } 64 65 BooleanPrefMember pref_; 66 bool value_; 67}; 68 69class PrefMemberTestClass : public NotificationObserver { 70 public: 71 explicit PrefMemberTestClass(PrefService* prefs) 72 : observe_cnt_(0), prefs_(prefs) { 73 str_.Init(kStringPref, prefs, this); 74 } 75 76 virtual void Observe(NotificationType type, 77 const NotificationSource& source, 78 const NotificationDetails& details) { 79 DCHECK(NotificationType::PREF_CHANGED == type); 80 PrefService* prefs_in = Source<PrefService>(source).ptr(); 81 EXPECT_EQ(prefs_in, prefs_); 82 std::string* pref_name_in = Details<std::string>(details).ptr(); 83 EXPECT_EQ(*pref_name_in, kStringPref); 84 EXPECT_EQ(str_.GetValue(), prefs_->GetString(kStringPref)); 85 ++observe_cnt_; 86 } 87 88 StringPrefMember str_; 89 int observe_cnt_; 90 91 private: 92 PrefService* prefs_; 93}; 94 95} // anonymous namespace 96 97TEST(PrefMemberTest, BasicGetAndSet) { 98 TestingPrefService prefs; 99 RegisterTestPrefs(&prefs); 100 101 // Test bool 102 BooleanPrefMember boolean; 103 boolean.Init(kBoolPref, &prefs, NULL); 104 105 // Check the defaults 106 EXPECT_FALSE(prefs.GetBoolean(kBoolPref)); 107 EXPECT_FALSE(boolean.GetValue()); 108 EXPECT_FALSE(*boolean); 109 110 // Try changing through the member variable. 111 boolean.SetValue(true); 112 EXPECT_TRUE(boolean.GetValue()); 113 EXPECT_TRUE(prefs.GetBoolean(kBoolPref)); 114 EXPECT_TRUE(*boolean); 115 116 // Try changing back through the pref. 117 prefs.SetBoolean(kBoolPref, false); 118 EXPECT_FALSE(prefs.GetBoolean(kBoolPref)); 119 EXPECT_FALSE(boolean.GetValue()); 120 EXPECT_FALSE(*boolean); 121 122 // Test int 123 IntegerPrefMember integer; 124 integer.Init(kIntPref, &prefs, NULL); 125 126 // Check the defaults 127 EXPECT_EQ(0, prefs.GetInteger(kIntPref)); 128 EXPECT_EQ(0, integer.GetValue()); 129 EXPECT_EQ(0, *integer); 130 131 // Try changing through the member variable. 132 integer.SetValue(5); 133 EXPECT_EQ(5, integer.GetValue()); 134 EXPECT_EQ(5, prefs.GetInteger(kIntPref)); 135 EXPECT_EQ(5, *integer); 136 137 // Try changing back through the pref. 138 prefs.SetInteger(kIntPref, 2); 139 EXPECT_EQ(2, prefs.GetInteger(kIntPref)); 140 EXPECT_EQ(2, integer.GetValue()); 141 EXPECT_EQ(2, *integer); 142 143 // Test double 144 DoublePrefMember double_member; 145 double_member.Init(kDoublePref, &prefs, NULL); 146 147 // Check the defaults 148 EXPECT_EQ(0.0, prefs.GetDouble(kDoublePref)); 149 EXPECT_EQ(0.0, double_member.GetValue()); 150 EXPECT_EQ(0.0, *double_member); 151 152 // Try changing through the member variable. 153 double_member.SetValue(1.0); 154 EXPECT_EQ(1.0, double_member.GetValue()); 155 EXPECT_EQ(1.0, prefs.GetDouble(kDoublePref)); 156 EXPECT_EQ(1.0, *double_member); 157 158 // Try changing back through the pref. 159 prefs.SetDouble(kDoublePref, 3.0); 160 EXPECT_EQ(3.0, prefs.GetDouble(kDoublePref)); 161 EXPECT_EQ(3.0, double_member.GetValue()); 162 EXPECT_EQ(3.0, *double_member); 163 164 // Test string 165 StringPrefMember string; 166 string.Init(kStringPref, &prefs, NULL); 167 168 // Check the defaults 169 EXPECT_EQ("default", prefs.GetString(kStringPref)); 170 EXPECT_EQ("default", string.GetValue()); 171 EXPECT_EQ("default", *string); 172 173 // Try changing through the member variable. 174 string.SetValue("foo"); 175 EXPECT_EQ("foo", string.GetValue()); 176 EXPECT_EQ("foo", prefs.GetString(kStringPref)); 177 EXPECT_EQ("foo", *string); 178 179 // Try changing back through the pref. 180 prefs.SetString(kStringPref, "bar"); 181 EXPECT_EQ("bar", prefs.GetString(kStringPref)); 182 EXPECT_EQ("bar", string.GetValue()); 183 EXPECT_EQ("bar", *string); 184 185 // Test list 186 ListPrefMember list; 187 list.Init(kListPref, &prefs, NULL); 188 189 // Check the defaults 190 const ListValue* list_value = prefs.GetList(kListPref); 191 ASSERT_TRUE(list_value != NULL); 192 EXPECT_EQ(0u, list_value->GetSize()); 193 EXPECT_TRUE(list_value->empty()); 194 ASSERT_TRUE(list.GetValue() != NULL); 195 EXPECT_EQ(0u, list.GetValue()->GetSize()); 196 EXPECT_TRUE(list.GetValue()->empty()); 197 ASSERT_TRUE(*list != NULL); 198 EXPECT_EQ(0u, (*list)->GetSize()); 199 EXPECT_TRUE((*list)->empty()); 200 201 // Try changing through the member variable. 202 scoped_ptr<ListValue> list_value_numbers(new ListValue()); 203 list_value_numbers->Append(new StringValue("one")); 204 list_value_numbers->Append(new StringValue("two")); 205 list_value_numbers->Append(new StringValue("three")); 206 list.SetValue(list_value_numbers.get()); 207 EXPECT_TRUE(list_value_numbers->Equals(list.GetValue())); 208 EXPECT_TRUE(list_value_numbers->Equals(prefs.GetList(kListPref))); 209 EXPECT_TRUE(list_value_numbers->Equals(*list)); 210 211 // Try changing back through the pref. 212 ListValue* list_value_ints = new ListValue(); 213 list_value_ints->Append(new FundamentalValue(1)); 214 list_value_ints->Append(new FundamentalValue(2)); 215 list_value_ints->Append(new FundamentalValue(3)); 216 prefs.SetList(kListPref, list_value_ints); // takes ownership 217 EXPECT_TRUE(list_value_ints->Equals(list.GetValue())); 218 EXPECT_TRUE(list_value_ints->Equals(prefs.GetList(kListPref))); 219 EXPECT_TRUE(list_value_ints->Equals(*list)); 220} 221 222TEST(PrefMemberTest, TwoPrefs) { 223 // Make sure two DoublePrefMembers stay in sync. 224 TestingPrefService prefs; 225 RegisterTestPrefs(&prefs); 226 227 DoublePrefMember pref1; 228 pref1.Init(kDoublePref, &prefs, NULL); 229 DoublePrefMember pref2; 230 pref2.Init(kDoublePref, &prefs, NULL); 231 232 pref1.SetValue(2.3); 233 EXPECT_EQ(2.3, *pref2); 234 235 pref2.SetValue(3.5); 236 EXPECT_EQ(3.5, *pref1); 237 238 prefs.SetDouble(kDoublePref, 4.2); 239 EXPECT_EQ(4.2, *pref1); 240 EXPECT_EQ(4.2, *pref2); 241} 242 243TEST(PrefMemberTest, Observer) { 244 TestingPrefService prefs; 245 RegisterTestPrefs(&prefs); 246 247 PrefMemberTestClass test_obj(&prefs); 248 EXPECT_EQ("default", *test_obj.str_); 249 250 // Calling SetValue should not fire the observer. 251 test_obj.str_.SetValue("hello"); 252 EXPECT_EQ(0, test_obj.observe_cnt_); 253 EXPECT_EQ("hello", prefs.GetString(kStringPref)); 254 255 // Changing the pref does fire the observer. 256 prefs.SetString(kStringPref, "world"); 257 EXPECT_EQ(1, test_obj.observe_cnt_); 258 EXPECT_EQ("world", *(test_obj.str_)); 259 260 // Not changing the value should not fire the observer. 261 prefs.SetString(kStringPref, "world"); 262 EXPECT_EQ(1, test_obj.observe_cnt_); 263 EXPECT_EQ("world", *(test_obj.str_)); 264 265 prefs.SetString(kStringPref, "hello"); 266 EXPECT_EQ(2, test_obj.observe_cnt_); 267 EXPECT_EQ("hello", prefs.GetString(kStringPref)); 268} 269 270TEST(PrefMemberTest, NoInit) { 271 // Make sure not calling Init on a PrefMember doesn't cause problems. 272 IntegerPrefMember pref; 273} 274 275TEST(PrefMemberTest, MoveToThread) { 276 TestingPrefService prefs; 277 scoped_refptr<GetPrefValueCallback> callback = 278 make_scoped_refptr(new GetPrefValueCallback()); 279 MessageLoop message_loop; 280 BrowserThread ui_thread(BrowserThread::UI, &message_loop); 281 BrowserThread io_thread(BrowserThread::IO); 282 ASSERT_TRUE(io_thread.Start()); 283 RegisterTestPrefs(&prefs); 284 callback->Init(kBoolPref, &prefs); 285 286 ASSERT_TRUE(callback->FetchValue()); 287 EXPECT_FALSE(callback->value()); 288 289 prefs.SetBoolean(kBoolPref, true); 290 291 ASSERT_TRUE(callback->FetchValue()); 292 EXPECT_TRUE(callback->value()); 293} 294