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.
5 #include "base/prefs/pref_member.h"
8 #include "base/location.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
18 const char kBoolPref
[] = "bool";
19 const char kIntPref
[] = "int";
20 const char kDoublePref
[] = "double";
21 const char kStringPref
[] = "string";
22 const char kStringListPref
[] = "string_list";
24 void RegisterTestPrefs(PrefRegistrySimple
* registry
) {
25 registry
->RegisterBooleanPref(kBoolPref
, false);
26 registry
->RegisterIntegerPref(kIntPref
, 0);
27 registry
->RegisterDoublePref(kDoublePref
, 0.0);
28 registry
->RegisterStringPref(kStringPref
, "default");
29 registry
->RegisterListPref(kStringListPref
, new base::ListValue());
32 class GetPrefValueHelper
33 : public base::RefCountedThreadSafe
<GetPrefValueHelper
> {
35 GetPrefValueHelper() : value_(false), pref_thread_("pref thread") {
39 void Init(const std::string
& pref_name
, PrefService
* prefs
) {
40 pref_
.Init(pref_name
, prefs
);
41 pref_
.MoveToThread(pref_thread_
.task_runner());
49 base::WaitableEvent
event(true, false);
50 ASSERT_TRUE(pref_thread_
.task_runner()->PostTask(
52 base::Bind(&GetPrefValueHelper::GetPrefValue
, this, &event
)));
56 // The thread must be stopped on the main thread. GetPrefValueHelper being
57 // ref-counted, the destructor can be called from any thread.
62 bool value() { return value_
; }
65 friend class base::RefCountedThreadSafe
<GetPrefValueHelper
>;
66 ~GetPrefValueHelper() {}
68 void GetPrefValue(base::WaitableEvent
* event
) {
69 value_
= pref_
.GetValue();
73 BooleanPrefMember pref_
;
76 base::Thread pref_thread_
; // The thread |pref_| runs on.
79 class PrefMemberTestClass
{
81 explicit PrefMemberTestClass(PrefService
* prefs
)
82 : observe_cnt_(0), prefs_(prefs
) {
83 str_
.Init(kStringPref
, prefs
,
84 base::Bind(&PrefMemberTestClass::OnPreferenceChanged
,
85 base::Unretained(this)));
88 void OnPreferenceChanged(const std::string
& pref_name
) {
89 EXPECT_EQ(pref_name
, kStringPref
);
90 EXPECT_EQ(str_
.GetValue(), prefs_
->GetString(kStringPref
));
94 StringPrefMember str_
;
101 } // anonymous namespace
103 class PrefMemberTest
: public testing::Test
{
104 base::MessageLoop message_loop_
;
107 TEST_F(PrefMemberTest
, BasicGetAndSet
) {
108 TestingPrefServiceSimple prefs
;
109 RegisterTestPrefs(prefs
.registry());
112 BooleanPrefMember boolean
;
113 boolean
.Init(kBoolPref
, &prefs
);
115 // Check the defaults
116 EXPECT_FALSE(prefs
.GetBoolean(kBoolPref
));
117 EXPECT_FALSE(boolean
.GetValue());
118 EXPECT_FALSE(*boolean
);
120 // Try changing through the member variable.
121 boolean
.SetValue(true);
122 EXPECT_TRUE(boolean
.GetValue());
123 EXPECT_TRUE(prefs
.GetBoolean(kBoolPref
));
124 EXPECT_TRUE(*boolean
);
126 // Try changing back through the pref.
127 prefs
.SetBoolean(kBoolPref
, false);
128 EXPECT_FALSE(prefs
.GetBoolean(kBoolPref
));
129 EXPECT_FALSE(boolean
.GetValue());
130 EXPECT_FALSE(*boolean
);
133 IntegerPrefMember integer
;
134 integer
.Init(kIntPref
, &prefs
);
136 // Check the defaults
137 EXPECT_EQ(0, prefs
.GetInteger(kIntPref
));
138 EXPECT_EQ(0, integer
.GetValue());
139 EXPECT_EQ(0, *integer
);
141 // Try changing through the member variable.
143 EXPECT_EQ(5, integer
.GetValue());
144 EXPECT_EQ(5, prefs
.GetInteger(kIntPref
));
145 EXPECT_EQ(5, *integer
);
147 // Try changing back through the pref.
148 prefs
.SetInteger(kIntPref
, 2);
149 EXPECT_EQ(2, prefs
.GetInteger(kIntPref
));
150 EXPECT_EQ(2, integer
.GetValue());
151 EXPECT_EQ(2, *integer
);
154 DoublePrefMember double_member
;
155 double_member
.Init(kDoublePref
, &prefs
);
157 // Check the defaults
158 EXPECT_EQ(0.0, prefs
.GetDouble(kDoublePref
));
159 EXPECT_EQ(0.0, double_member
.GetValue());
160 EXPECT_EQ(0.0, *double_member
);
162 // Try changing through the member variable.
163 double_member
.SetValue(1.0);
164 EXPECT_EQ(1.0, double_member
.GetValue());
165 EXPECT_EQ(1.0, prefs
.GetDouble(kDoublePref
));
166 EXPECT_EQ(1.0, *double_member
);
168 // Try changing back through the pref.
169 prefs
.SetDouble(kDoublePref
, 3.0);
170 EXPECT_EQ(3.0, prefs
.GetDouble(kDoublePref
));
171 EXPECT_EQ(3.0, double_member
.GetValue());
172 EXPECT_EQ(3.0, *double_member
);
175 StringPrefMember string
;
176 string
.Init(kStringPref
, &prefs
);
178 // Check the defaults
179 EXPECT_EQ("default", prefs
.GetString(kStringPref
));
180 EXPECT_EQ("default", string
.GetValue());
181 EXPECT_EQ("default", *string
);
183 // Try changing through the member variable.
184 string
.SetValue("foo");
185 EXPECT_EQ("foo", string
.GetValue());
186 EXPECT_EQ("foo", prefs
.GetString(kStringPref
));
187 EXPECT_EQ("foo", *string
);
189 // Try changing back through the pref.
190 prefs
.SetString(kStringPref
, "bar");
191 EXPECT_EQ("bar", prefs
.GetString(kStringPref
));
192 EXPECT_EQ("bar", string
.GetValue());
193 EXPECT_EQ("bar", *string
);
196 base::ListValue expected_list
;
197 std::vector
<std::string
> expected_vector
;
198 StringListPrefMember string_list
;
199 string_list
.Init(kStringListPref
, &prefs
);
201 // Check the defaults
202 EXPECT_TRUE(expected_list
.Equals(prefs
.GetList(kStringListPref
)));
203 EXPECT_EQ(expected_vector
, string_list
.GetValue());
204 EXPECT_EQ(expected_vector
, *string_list
);
206 // Try changing through the pref member.
207 expected_list
.AppendString("foo");
208 expected_vector
.push_back("foo");
209 string_list
.SetValue(expected_vector
);
211 EXPECT_TRUE(expected_list
.Equals(prefs
.GetList(kStringListPref
)));
212 EXPECT_EQ(expected_vector
, string_list
.GetValue());
213 EXPECT_EQ(expected_vector
, *string_list
);
215 // Try adding through the pref.
216 expected_list
.AppendString("bar");
217 expected_vector
.push_back("bar");
218 prefs
.Set(kStringListPref
, expected_list
);
220 EXPECT_TRUE(expected_list
.Equals(prefs
.GetList(kStringListPref
)));
221 EXPECT_EQ(expected_vector
, string_list
.GetValue());
222 EXPECT_EQ(expected_vector
, *string_list
);
224 // Try removing through the pref.
225 expected_list
.Remove(0, NULL
);
226 expected_vector
.erase(expected_vector
.begin());
227 prefs
.Set(kStringListPref
, expected_list
);
229 EXPECT_TRUE(expected_list
.Equals(prefs
.GetList(kStringListPref
)));
230 EXPECT_EQ(expected_vector
, string_list
.GetValue());
231 EXPECT_EQ(expected_vector
, *string_list
);
234 TEST_F(PrefMemberTest
, InvalidList
) {
235 // Set the vector to an initial good value.
236 std::vector
<std::string
> expected_vector
;
237 expected_vector
.push_back("foo");
239 // Try to add a valid list first.
240 base::ListValue list
;
241 list
.AppendString("foo");
242 std::vector
<std::string
> vector
;
243 EXPECT_TRUE(subtle::PrefMemberVectorStringUpdate(list
, &vector
));
244 EXPECT_EQ(expected_vector
, vector
);
246 // Now try to add an invalid list. |vector| should not be changed.
247 list
.AppendInteger(0);
248 EXPECT_FALSE(subtle::PrefMemberVectorStringUpdate(list
, &vector
));
249 EXPECT_EQ(expected_vector
, vector
);
252 TEST_F(PrefMemberTest
, TwoPrefs
) {
253 // Make sure two DoublePrefMembers stay in sync.
254 TestingPrefServiceSimple prefs
;
255 RegisterTestPrefs(prefs
.registry());
257 DoublePrefMember pref1
;
258 pref1
.Init(kDoublePref
, &prefs
);
259 DoublePrefMember pref2
;
260 pref2
.Init(kDoublePref
, &prefs
);
263 EXPECT_EQ(2.3, *pref2
);
266 EXPECT_EQ(3.5, *pref1
);
268 prefs
.SetDouble(kDoublePref
, 4.2);
269 EXPECT_EQ(4.2, *pref1
);
270 EXPECT_EQ(4.2, *pref2
);
273 TEST_F(PrefMemberTest
, Observer
) {
274 TestingPrefServiceSimple prefs
;
275 RegisterTestPrefs(prefs
.registry());
277 PrefMemberTestClass
test_obj(&prefs
);
278 EXPECT_EQ("default", *test_obj
.str_
);
280 // Calling SetValue should not fire the observer.
281 test_obj
.str_
.SetValue("hello");
282 EXPECT_EQ(0, test_obj
.observe_cnt_
);
283 EXPECT_EQ("hello", prefs
.GetString(kStringPref
));
285 // Changing the pref does fire the observer.
286 prefs
.SetString(kStringPref
, "world");
287 EXPECT_EQ(1, test_obj
.observe_cnt_
);
288 EXPECT_EQ("world", *(test_obj
.str_
));
290 // Not changing the value should not fire the observer.
291 prefs
.SetString(kStringPref
, "world");
292 EXPECT_EQ(1, test_obj
.observe_cnt_
);
293 EXPECT_EQ("world", *(test_obj
.str_
));
295 prefs
.SetString(kStringPref
, "hello");
296 EXPECT_EQ(2, test_obj
.observe_cnt_
);
297 EXPECT_EQ("hello", prefs
.GetString(kStringPref
));
300 TEST_F(PrefMemberTest
, NoInit
) {
301 // Make sure not calling Init on a PrefMember doesn't cause problems.
302 IntegerPrefMember pref
;
305 TEST_F(PrefMemberTest
, MoveToThread
) {
306 TestingPrefServiceSimple prefs
;
307 scoped_refptr
<GetPrefValueHelper
> helper(new GetPrefValueHelper());
308 RegisterTestPrefs(prefs
.registry());
309 helper
->Init(kBoolPref
, &prefs
);
311 helper
->FetchValue();
312 EXPECT_FALSE(helper
->value());
314 prefs
.SetBoolean(kBoolPref
, true);
316 helper
->FetchValue();
317 EXPECT_TRUE(helper
->value());
321 helper
->FetchValue();
322 EXPECT_TRUE(helper
->value());
324 helper
->StopThread();