blob: 37d04de62719adfc4d49048c2b33e97d922e3048 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
5#include "base/file_util.h"
6#include "base/path_service.h"
7#include "chrome/common/chrome_paths.h"
8#include "chrome/common/json_value_serializer.h"
9#include "chrome/common/notification_service.h"
10#include "chrome/common/notification_types.h"
11#include "chrome/common/pref_names.h"
12#include "chrome/common/pref_service.h"
13#include "chrome/test/data/resource.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16namespace {
17
18class PrefServiceTest : public testing::Test {
19protected:
20 virtual void SetUp() {
21 // Name a subdirectory of the temp directory.
22 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
23 file_util::AppendToPath(&test_dir_, L"PrefServiceTest");
24
25 // Create a fresh, empty copy of this directory.
26 file_util::Delete(test_dir_, true);
27 CreateDirectory(test_dir_.c_str(), NULL);
28
29 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_dir_));
30 file_util::AppendToPath(&data_dir_, L"pref_service");
31 ASSERT_TRUE(file_util::PathExists(data_dir_));
32 }
33 virtual void TearDown() {
34 // Clean up test directory
35 ASSERT_TRUE(file_util::Delete(test_dir_, false));
36 ASSERT_FALSE(file_util::PathExists(test_dir_));
37 }
38
39 // the path to temporary directory used to contain the test operations
40 std::wstring test_dir_;
41 // the path to the directory where the test data is stored
42 std::wstring data_dir_;
43};
44
45class TestPrefObserver : public NotificationObserver {
46 public:
47 TestPrefObserver(const PrefService* prefs, const std::wstring& pref_name,
48 const std::wstring& new_pref_value)
49 : observer_fired_(false),
50 prefs_(prefs),
51 pref_name_(pref_name),
52 new_pref_value_(new_pref_value) {
53 }
54 virtual ~TestPrefObserver() {}
55
56 virtual void Observe(NotificationType type,
57 const NotificationSource& source,
58 const NotificationDetails& details) {
59 EXPECT_EQ(type, NOTIFY_PREF_CHANGED);
60 PrefService* prefs_in = Source<PrefService>(source).ptr();
61 EXPECT_EQ(prefs_in, prefs_);
62 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
63 EXPECT_EQ(*pref_name_in, pref_name_);
64 EXPECT_EQ(new_pref_value_, prefs_in->GetString(L"homepage"));
65 observer_fired_ = true;
66 }
67
68 bool observer_fired() { return observer_fired_; }
69
70 void Reset(const std::wstring& new_pref_value) {
71 observer_fired_ = false;
72 new_pref_value_ = new_pref_value;
73 }
74
75 private:
76 bool observer_fired_;
77 const PrefService* prefs_;
78 const std::wstring pref_name_;
79 std::wstring new_pref_value_;
80};
81
82} // anonymous namespace
83
84TEST_F(PrefServiceTest, Basic) {
85 PrefService prefs;
86
87 // Test that it fails on nonexistent file.
88 std::wstring bogus_input_file = data_dir_;
89 file_util::AppendToPath(&bogus_input_file, L"read.txt");
90 EXPECT_FALSE(prefs.LoadPersistentPrefs(bogus_input_file));
91
92 // Test that the persistent value can be loaded.
93 std::wstring input_file = data_dir_;
94 file_util::AppendToPath(&input_file, L"read.json");
95 ASSERT_TRUE(file_util::PathExists(input_file));
96 ASSERT_TRUE(prefs.LoadPersistentPrefs(input_file));
97
98 // Register test prefs.
99 const wchar_t kNewWindowsInTabs[] = L"tabs.new_windows_in_tabs";
100 const wchar_t kMaxTabs[] = L"tabs.max_tabs";
101 prefs.RegisterStringPref(prefs::kHomePage, L"");
102 prefs.RegisterBooleanPref(kNewWindowsInTabs, false);
103 prefs.RegisterIntegerPref(kMaxTabs, 0);
104
105 std::wstring microsoft(L"http://www.microsoft.com");
106 std::wstring cnn(L"http://www.cnn.com");
107 std::wstring homepage(L"http://www.example.com");
108
109 EXPECT_EQ(cnn, prefs.GetString(prefs::kHomePage));
110
111 // Now test that the transient value overrides the persistent value,
112 // without actually altering the persistent store.
113 EXPECT_TRUE(prefs.transient()->SetString(prefs::kHomePage, microsoft));
114 EXPECT_TRUE(prefs.transient()->GetString(prefs::kHomePage, &homepage));
115 EXPECT_EQ(microsoft, homepage);
116
117 EXPECT_EQ(microsoft, prefs.GetString(prefs::kHomePage));
118
119 // Test reading some other data types from sub-dictionaries, and
120 // writing to the persistent store.
121 EXPECT_TRUE(prefs.GetBoolean(kNewWindowsInTabs));
122 prefs.SetBoolean(kNewWindowsInTabs, false);
123 EXPECT_FALSE(prefs.GetBoolean(kNewWindowsInTabs));
124
125 EXPECT_EQ(20, prefs.GetInteger(kMaxTabs));
126 prefs.SetInteger(kMaxTabs, 10);
127 EXPECT_EQ(10, prefs.GetInteger(kMaxTabs));
128
129 // Serialize and compare to expected output.
130 std::wstring output_file = test_dir_;
131 file_util::AppendToPath(&output_file, L"write.json");
132 prefs.pref_filename_ = output_file;
133 ASSERT_TRUE(prefs.SavePersistentPrefs(NULL));
134 std::wstring golden_output_file = data_dir_;
135 file_util::AppendToPath(&golden_output_file, L"write.golden.json");
136 ASSERT_TRUE(file_util::PathExists(golden_output_file));
137 ASSERT_TRUE(file_util::ContentsEqual(golden_output_file, output_file));
138}
139
140TEST_F(PrefServiceTest, Overlay) {
141 const std::string transient =
142 "{\"bool\":true, \"int\":2, \"real\":2.0, \"string\":\"transient\","
143 "\"dictionary\":{\"value\":\"transient\"},"
144 "\"list\":[\"transient\"]}";
145
146 std::wstring persistent_string(L"persistent");
147 std::wstring transient_string(L"transient");
148
149 PrefService prefs;
150
151 std::wstring persistent_file = data_dir_;
152 file_util::AppendToPath(&persistent_file, L"overlay.json");
153 EXPECT_TRUE(prefs.LoadPersistentPrefs(persistent_file));
154
155 Value* transient_value;
156 {
157 JSONStringValueSerializer serializer(transient);
158 ASSERT_TRUE(serializer.Deserialize(&transient_value));
159 }
160 prefs.transient()->Set(transient_string, transient_value);
161
162 Value* both_transient_value;
163 {
164 JSONStringValueSerializer serializer(transient);
165 ASSERT_TRUE(serializer.Deserialize(&both_transient_value));
166 }
167 prefs.transient()->Set(L"both", both_transient_value);
168
169 // Register test prefs
170 const wchar_t* kTypes[] = { L"neither.", L"persistent.", L"transient.", L"both." };
171 for (size_t i = 0; i < arraysize(kTypes); ++i) {
172 wchar_t temp[1024];
173 wcscpy_s(temp, kTypes[i]);
174 wcscat_s(temp, L"bool");
175 prefs.RegisterBooleanPref(temp, false);
176
177 wcscpy_s(temp, kTypes[i]);
178 wcscat_s(temp, L"int");
179 prefs.RegisterIntegerPref(temp, 0);
180
181 wcscpy_s(temp, kTypes[i]);
182 wcscat_s(temp, L"real");
183 prefs.RegisterRealPref(temp, 0.0);
184
185 wcscpy_s(temp, kTypes[i]);
186 wcscat_s(temp, L"string");
187 prefs.RegisterStringPref(temp, L"");
188
189 wcscpy_s(temp, kTypes[i]);
190 wcscat_s(temp, L"list");
191 prefs.RegisterListPref(temp);
192
193 wcscpy_s(temp, kTypes[i]);
194 wcscat_s(temp, L"dictionary");
195 prefs.RegisterDictionaryPref(temp);
196 }
197
198 ASSERT_FALSE(prefs.GetBoolean(L"neither.bool"));
199 ASSERT_FALSE(prefs.GetBoolean(L"persistent.bool"));
200 ASSERT_TRUE(prefs.GetBoolean(L"transient.bool"));
201 ASSERT_TRUE(prefs.GetBoolean(L"both.bool"));
202
203 ASSERT_EQ(0, prefs.GetInteger(L"neither.int"));
204 ASSERT_EQ(1, prefs.GetInteger(L"persistent.int"));
205 ASSERT_EQ(2, prefs.GetInteger(L"transient.int"));
206 ASSERT_EQ(2, prefs.GetInteger(L"both.int"));
207
208 ASSERT_EQ(0.0, prefs.GetReal(L"neither.real"));
209 ASSERT_EQ(1.0, prefs.GetReal(L"persistent.real"));
210 ASSERT_EQ(2.0, prefs.GetReal(L"transient.real"));
211 ASSERT_EQ(2.0, prefs.GetReal(L"both.real"));
212
213 ASSERT_EQ(std::wstring(), prefs.GetString(L"neither.string"));
214 ASSERT_EQ(persistent_string, prefs.GetString(L"persistent.string"));
215 ASSERT_EQ(transient_string, prefs.GetString(L"transient.string"));
216 ASSERT_EQ(transient_string, prefs.GetString(L"both.string"));
217
218 {
219 const DictionaryValue* result_value =
220 prefs.GetDictionary(L"neither.dictionary");
221 ASSERT_FALSE(result_value);
222 }
223
224 {
225 const DictionaryValue* result_value =
226 prefs.GetDictionary(L"persistent.dictionary");
227 ASSERT_TRUE(result_value);
228 std::wstring result_string;
229 ASSERT_TRUE(result_value->GetString(L"value", &result_string));
230 ASSERT_EQ(persistent_string, result_string);
231 }
232
233 {
234 const DictionaryValue* result_value =
235 prefs.GetDictionary(L"transient.dictionary");
236 ASSERT_TRUE(result_value);
237 std::wstring result_string;
238 ASSERT_TRUE(result_value->GetString(L"value", &result_string));
239 ASSERT_EQ(transient_string, result_string);
240 }
241
242 {
243 const DictionaryValue* result_value =
244 prefs.GetDictionary(L"both.dictionary");
245 ASSERT_TRUE(result_value);
246 std::wstring result_string;
247 ASSERT_TRUE(result_value->GetString(L"value", &result_string));
248 ASSERT_EQ(transient_string, result_string);
249 }
250
251 {
252 const ListValue* result_value = prefs.GetList(L"neither.list");
253 ASSERT_FALSE(result_value);
254 }
255
256 {
257 const ListValue* result_value = prefs.GetList(L"persistent.list");
258 ASSERT_TRUE(result_value);
259 Value* member_value;
260 ASSERT_TRUE(result_value->Get(0, &member_value));
261 ASSERT_TRUE(member_value);
262 std::wstring result_string;
263 ASSERT_TRUE(member_value->GetAsString(&result_string));
264 ASSERT_EQ(persistent_string, result_string);
265 }
266
267 {
268 const ListValue* result_value = prefs.GetList(L"transient.list");
269 ASSERT_TRUE(result_value);
270 Value* member_value;
271 ASSERT_TRUE(result_value->Get(0, &member_value));
272 ASSERT_TRUE(member_value);
273 std::wstring result_string;
274 ASSERT_TRUE(member_value->GetAsString(&result_string));
275 ASSERT_EQ(transient_string, result_string);
276 }
277
278 {
279 const ListValue* result_value = prefs.GetList(L"both.list");
280 ASSERT_TRUE(result_value);
281 Value* member_value;
282 ASSERT_TRUE(result_value->Get(0, &member_value));
283 ASSERT_TRUE(member_value);
284 std::wstring result_string;
285 ASSERT_TRUE(member_value->GetAsString(&result_string));
286 ASSERT_EQ(transient_string, result_string);
287 }
288}
289
290TEST_F(PrefServiceTest, Observers) {
291 PrefService prefs;
292
293 std::wstring input_file = data_dir_;
294 file_util::AppendToPath(&input_file, L"read.json");
295 EXPECT_TRUE(file_util::PathExists(input_file));
296 EXPECT_TRUE(prefs.LoadPersistentPrefs(input_file));
297
298 const wchar_t pref_name[] = L"homepage";
299 prefs.RegisterStringPref(pref_name, L"");
300 EXPECT_EQ(std::wstring(L"http://www.cnn.com"), prefs.GetString(pref_name));
301
302 const std::wstring new_pref_value(L"http://www.google.com/");
303 TestPrefObserver obs(&prefs, pref_name, new_pref_value);
304 prefs.AddPrefObserver(pref_name, &obs);
305 // This should fire the checks in TestPrefObserver::Observe.
306 prefs.SetString(pref_name, new_pref_value);
307
308 // Make sure the tests were actually run.
309 EXPECT_TRUE(obs.observer_fired());
310
311 // Now try adding a second pref observer.
312 const std::wstring new_pref_value2(L"http://www.youtube.com/");
313 obs.Reset(new_pref_value2);
314 TestPrefObserver obs2(&prefs, pref_name, new_pref_value2);
315 prefs.AddPrefObserver(pref_name, &obs2);
316 // This should fire the checks in obs and obs2.
317 prefs.SetString(pref_name, new_pref_value2);
318 EXPECT_TRUE(obs.observer_fired());
319 EXPECT_TRUE(obs2.observer_fired());
320
321 // Make sure obs2 still works after removing obs.
322 prefs.RemovePrefObserver(pref_name, &obs);
323 obs.Reset(L"");
324 obs2.Reset(new_pref_value);
325 // This should only fire the observer in obs2.
326 prefs.SetString(pref_name, new_pref_value);
327 EXPECT_FALSE(obs.observer_fired());
328 EXPECT_TRUE(obs2.observer_fired());
329
330 // Ok, clean up.
331 prefs.RemovePrefObserver(pref_name, &obs2);
332}
333
334TEST_F(PrefServiceTest, LocalizedPrefs) {
335 PrefService prefs;
336 const wchar_t kBoolean[] = L"boolean";
337 const wchar_t kInteger[] = L"integer";
338 const wchar_t kString[] = L"string";
339 prefs.RegisterLocalizedBooleanPref(kBoolean, IDS_LOCALE_BOOL);
340 prefs.RegisterLocalizedIntegerPref(kInteger, IDS_LOCALE_INT);
341 prefs.RegisterLocalizedStringPref(kString, IDS_LOCALE_STRING);
342
343 // The locale default should take preference over the user default.
344 EXPECT_FALSE(prefs.GetBoolean(kBoolean));
345 EXPECT_EQ(1, prefs.GetInteger(kInteger));
346 EXPECT_EQ(L"hello", prefs.GetString(kString));
347
348 prefs.SetBoolean(kBoolean, true);
349 EXPECT_TRUE(prefs.GetBoolean(kBoolean));
350 prefs.SetInteger(kInteger, 5);
351 EXPECT_EQ(5, prefs.GetInteger(kInteger));
352 prefs.SetString(kString, L"foo");
353 EXPECT_EQ(L"foo", prefs.GetString(kString));
354}
355
356TEST_F(PrefServiceTest, NoObserverFire) {
357 PrefService prefs;
358
359 const wchar_t pref_name[] = L"homepage";
360 prefs.RegisterStringPref(pref_name, L"");
361
362 const std::wstring new_pref_value(L"http://www.google.com/");
363 TestPrefObserver obs(&prefs, pref_name, new_pref_value);
364 prefs.AddPrefObserver(pref_name, &obs);
365 // This should fire the checks in TestPrefObserver::Observe.
366 prefs.SetString(pref_name, new_pref_value);
367
368 // Make sure the observer was actually fired.
369 EXPECT_TRUE(obs.observer_fired());
370
371 // Setting the pref to the same value should not set the pref value a second
372 // time.
373 obs.Reset(new_pref_value);
374 prefs.SetString(pref_name, new_pref_value);
375 EXPECT_FALSE(obs.observer_fired());
376
377 // Clearing the pref should cause the pref to fire.
378 obs.Reset(L"");
379 prefs.ClearPref(pref_name);
380 EXPECT_TRUE(obs.observer_fired());
381
382 // Clearing the pref again should not cause the pref to fire.
383 obs.Reset(L"");
384 prefs.ClearPref(pref_name);
385 EXPECT_FALSE(obs.observer_fired());
386
387 // Ok, clean up.
388 prefs.RemovePrefObserver(pref_name, &obs);
389}
390
391TEST_F(PrefServiceTest, HasPrefPath) {
392 PrefService prefs;
393
394 const wchar_t path[] = L"fake.path";
395
396 // Shouldn't initially have a path.
397 EXPECT_FALSE(prefs.HasPrefPath(path));
398
399 // Register the path. This doesn't set a value, so the path still shouldn't
400 // exist.
401 prefs.RegisterStringPref(path, std::wstring());
402 EXPECT_FALSE(prefs.HasPrefPath(path));
403
404 // Set a value and make sure we have a path.
405 prefs.persistent_->SetString(path, L"blah");
406 EXPECT_TRUE(prefs.HasPrefPath(path));
407}
license.botbf09a502008-08-24 00:55:55408