license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame^] | 1 | // 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.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
| 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 | |
| 16 | namespace { |
| 17 | |
| 18 | class PrefServiceTest : public testing::Test { |
| 19 | protected: |
| 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 | |
| 45 | class 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 | |
| 84 | TEST_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 | |
| 140 | TEST_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 | |
| 290 | TEST_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 | |
| 334 | TEST_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 | |
| 356 | TEST_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 | |
| 391 | TEST_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.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame^] | 408 | |