1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/key_file_store.h" 18 19 #include <sys/stat.h> 20 21 #include <memory> 22 #include <set> 23 #include <string> 24 #include <vector> 25 26 #include <base/files/file_enumerator.h> 27 #include <base/files/file_util.h> 28 #include <base/files/scoped_temp_dir.h> 29 #include <base/stl_util.h> 30 #include <base/strings/string_number_conversions.h> 31 #include <base/strings/stringprintf.h> 32 #include <gtest/gtest.h> 33 34 #include "shill/key_value_store.h" 35 36 using base::FileEnumerator; 37 using base::FilePath; 38 using std::set; 39 using std::string; 40 using std::unique_ptr; 41 using std::vector; 42 using testing::Test; 43 44 namespace shill { 45 46 namespace { 47 const char kPlainText[] = "This is a test!"; 48 const char kROT47Text[] = "rot47:%9:D :D 2 E6DEP"; 49 } // namespace 50 51 class KeyFileStoreTest : public Test { 52 public: 53 KeyFileStoreTest() {} 54 55 virtual void SetUp() { 56 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 57 test_file_ = temp_dir_.path().Append("test-key-file-store"); 58 store_.reset(new KeyFileStore(test_file_)); 59 } 60 61 virtual void TearDown() { 62 ASSERT_TRUE(temp_dir_.Delete()); 63 } 64 65 protected: 66 string ReadKeyFile(); 67 void WriteKeyFile(string data); 68 69 base::ScopedTempDir temp_dir_; 70 FilePath test_file_; 71 unique_ptr<KeyFileStore> store_; 72 }; 73 74 string KeyFileStoreTest::ReadKeyFile() { 75 string data; 76 EXPECT_TRUE(base::ReadFileToString(test_file_, &data)); 77 return data; 78 } 79 80 void KeyFileStoreTest::WriteKeyFile(string data) { 81 EXPECT_EQ(data.size(), 82 base::WriteFile(test_file_, data.data(), data.size())); 83 } 84 85 TEST_F(KeyFileStoreTest, OpenClose) { 86 EXPECT_FALSE(store_->key_file_); 87 88 EXPECT_FALSE(store_->IsNonEmpty()); 89 ASSERT_TRUE(store_->Open()); 90 EXPECT_TRUE(store_->key_file_); 91 EXPECT_EQ(1, store_->crypto_.cryptos_.size()); 92 ASSERT_TRUE(store_->Close()); 93 EXPECT_FALSE(store_->key_file_); 94 FileEnumerator file_enumerator(temp_dir_.path(), 95 false /* not recursive */, 96 FileEnumerator::FILES); 97 98 // Verify that the file actually got written with the right name. 99 EXPECT_EQ(test_file_.value(), file_enumerator.Next().value()); 100 FileEnumerator::FileInfo file_info = file_enumerator.GetInfo(); 101 102 // Verify that the profile is a regular file, readable and writeable by the 103 // owner only. 104 EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR, file_info.stat().st_mode); 105 106 ASSERT_TRUE(store_->Open()); 107 EXPECT_TRUE(store_->key_file_); 108 ASSERT_TRUE(store_->Close()); 109 EXPECT_FALSE(store_->key_file_); 110 111 ASSERT_TRUE(store_->Open()); 112 // Replace file with directory, to force Flush() to fail. 113 ASSERT_TRUE(base::DeleteFile(test_file_, false)); 114 ASSERT_TRUE(base::CreateDirectory(test_file_)); 115 ASSERT_FALSE(store_->Close()); 116 EXPECT_FALSE(store_->key_file_); 117 } 118 119 TEST_F(KeyFileStoreTest, OpenFail) { 120 WriteKeyFile("garbage\n"); 121 EXPECT_FALSE(store_->Open()); 122 EXPECT_FALSE(store_->key_file_); 123 } 124 125 TEST_F(KeyFileStoreTest, MarkAsCorrupted) { 126 EXPECT_FALSE(store_->MarkAsCorrupted()); 127 EXPECT_FALSE(store_->IsNonEmpty()); 128 WriteKeyFile("garbage\n"); 129 EXPECT_TRUE(store_->IsNonEmpty()); 130 EXPECT_TRUE(base::PathExists(test_file_)); 131 EXPECT_TRUE(store_->MarkAsCorrupted()); 132 EXPECT_FALSE(store_->IsNonEmpty()); 133 EXPECT_FALSE(base::PathExists(test_file_)); 134 EXPECT_TRUE(base::PathExists(FilePath(test_file_.value() + ".corrupted"))); 135 } 136 137 TEST_F(KeyFileStoreTest, GetGroups) { 138 static const char kGroupA[] = "g-a"; 139 static const char kGroupB[] = "g-b"; 140 static const char kGroupC[] = "g-c"; 141 WriteKeyFile(base::StringPrintf("[%s]\n" 142 "[%s]\n" 143 "[%s]\n", 144 kGroupA, kGroupB, kGroupC)); 145 EXPECT_TRUE(store_->IsNonEmpty()); 146 ASSERT_TRUE(store_->Open()); 147 set<string> groups = store_->GetGroups(); 148 EXPECT_EQ(3, groups.size()); 149 EXPECT_TRUE(ContainsKey(groups, kGroupA)); 150 EXPECT_TRUE(ContainsKey(groups, kGroupB)); 151 EXPECT_TRUE(ContainsKey(groups, kGroupC)); 152 EXPECT_FALSE(ContainsKey(groups, "g-x")); 153 ASSERT_TRUE(store_->Close()); 154 } 155 156 TEST_F(KeyFileStoreTest, GetGroupsWithKey) { 157 static const char kGroupA[] = "g-a"; 158 static const char kGroupB[] = "g-b"; 159 static const char kGroupC[] = "g-c"; 160 static const char kKeyA[] = "k-a"; 161 static const char kKeyB[] = "k-b"; 162 static const char kValue[] = "true"; 163 WriteKeyFile(base::StringPrintf("[%s]\n" 164 "%s=%s\n" 165 "[%s]\n" 166 "%s=%s\n" 167 "%s=%s\n" 168 "[%s]\n" 169 "%s=%s\n", 170 kGroupA, kKeyA, kValue, 171 kGroupB, kKeyA, kValue, kKeyB, kValue, 172 kGroupC, kKeyB, kValue)); 173 EXPECT_TRUE(store_->IsNonEmpty()); 174 ASSERT_TRUE(store_->Open()); 175 set<string> groups_a = store_->GetGroupsWithKey(kKeyA); 176 EXPECT_EQ(2, groups_a.size()); 177 EXPECT_TRUE(ContainsKey(groups_a, kGroupA)); 178 EXPECT_TRUE(ContainsKey(groups_a, kGroupB)); 179 set<string> groups_b = store_->GetGroupsWithKey(kKeyB); 180 EXPECT_EQ(2, groups_b.size()); 181 EXPECT_TRUE(ContainsKey(groups_b, kGroupB)); 182 EXPECT_TRUE(ContainsKey(groups_b, kGroupC)); 183 ASSERT_TRUE(store_->Close()); 184 } 185 186 TEST_F(KeyFileStoreTest, ContainsGroup) { 187 static const char kGroupA[] = "group-a"; 188 static const char kGroupB[] = "group-b"; 189 static const char kGroupC[] = "group-c"; 190 WriteKeyFile(base::StringPrintf("[%s]\n" 191 "[%s]\n" 192 "[%s]\n", 193 kGroupA, kGroupB, kGroupC)); 194 ASSERT_TRUE(store_->Open()); 195 EXPECT_TRUE(store_->ContainsGroup(kGroupA)); 196 EXPECT_TRUE(store_->ContainsGroup(kGroupB)); 197 EXPECT_TRUE(store_->ContainsGroup(kGroupC)); 198 EXPECT_FALSE(store_->ContainsGroup("group-d")); 199 ASSERT_TRUE(store_->Close()); 200 } 201 202 TEST_F(KeyFileStoreTest, GetGroupsWithProperties) { 203 static const char kGroupA[] = "group-a"; 204 static const char kGroupB[] = "group-b"; 205 static const char kGroupC[] = "group-c"; 206 static const char kAttributeA[] = "attr-a"; 207 static const char kAttributeB[] = "attr-b"; 208 static const char kAttributeC[] = "attr-c"; 209 static const char kValueA_0[] = "val-a"; 210 static const char kValueA_1[] = "val-b"; 211 static const int kValueB_0 = 1; 212 static const int kValueB_1 = 2; 213 static const bool kValueC_0 = true; 214 static const char kValueC_0_string[] = "true"; 215 static const bool kValueC_1 = false; 216 static const char kValueC_1_string[] = "false"; 217 WriteKeyFile(base::StringPrintf("[%s]\n" 218 "%s=%s\n" 219 "%s=%d\n" 220 "%s=%s\n" 221 "[%s]\n" 222 "%s=%s\n" 223 "%s=%d\n" 224 "%s=%s\n" 225 "[%s]\n" 226 "%s=%s\n" 227 "%s=%d\n" 228 "%s=%s\n", 229 kGroupA, 230 kAttributeA, kValueA_0, 231 kAttributeB, kValueB_0, 232 kAttributeC, kValueC_0_string, 233 kGroupB, 234 kAttributeA, kValueA_0, 235 kAttributeB, kValueB_1, 236 kAttributeC, kValueC_0_string, 237 kGroupC, 238 kAttributeA, kValueA_0, 239 kAttributeB, kValueB_0, 240 kAttributeC, kValueC_1_string)); 241 ASSERT_TRUE(store_->Open()); 242 { 243 KeyValueStore args; 244 args.SetString(kAttributeA, kValueA_0); 245 args.SetInt(kAttributeB, kValueB_0); 246 set<string> results = store_->GetGroupsWithProperties(args); 247 EXPECT_EQ(2, results.size()); 248 EXPECT_TRUE(results.find(kGroupA) != results.end()); 249 EXPECT_TRUE(results.find(kGroupC) != results.end()); 250 } 251 { 252 KeyValueStore args; 253 args.SetString(kAttributeA, kValueA_0); 254 args.SetBool(kAttributeC, kValueC_0); 255 set<string> results = store_->GetGroupsWithProperties(args); 256 EXPECT_EQ(2, results.size()); 257 EXPECT_TRUE(results.find(kGroupA) != results.end()); 258 EXPECT_TRUE(results.find(kGroupB) != results.end()); 259 } 260 { 261 KeyValueStore args; 262 args.SetBool(kAttributeC, kValueC_1); 263 set<string> results = store_->GetGroupsWithProperties(args); 264 EXPECT_EQ(1, results.size()); 265 EXPECT_TRUE(results.find(kGroupC) != results.end()); 266 } 267 { 268 KeyValueStore args; 269 args.SetString(kAttributeA, kValueA_0); 270 set<string> results = store_->GetGroupsWithProperties(args); 271 EXPECT_EQ(3, results.size()); 272 EXPECT_TRUE(results.find(kGroupA) != results.end()); 273 EXPECT_TRUE(results.find(kGroupB) != results.end()); 274 EXPECT_TRUE(results.find(kGroupC) != results.end()); 275 } 276 { 277 KeyValueStore args; 278 args.SetString(kAttributeA, kValueA_1); 279 set<string> results = store_->GetGroupsWithProperties(args); 280 EXPECT_EQ(0, results.size()); 281 } 282 ASSERT_TRUE(store_->Close()); 283 } 284 285 TEST_F(KeyFileStoreTest, DeleteKey) { 286 static const char kGroup[] = "the-group"; 287 static const char kKeyDead[] = "dead"; 288 static const char kKeyAlive[] = "alive"; 289 const int kValueAlive = 3; 290 WriteKeyFile(base::StringPrintf("[%s]\n" 291 "%s=5\n" 292 "%s=%d\n", 293 kGroup, kKeyDead, kKeyAlive, kValueAlive)); 294 ASSERT_TRUE(store_->Open()); 295 EXPECT_TRUE(store_->DeleteKey(kGroup, kKeyDead)); 296 EXPECT_TRUE(store_->DeleteKey(kGroup, "random-key")); 297 EXPECT_FALSE(store_->DeleteKey("random-group", kKeyAlive)); 298 ASSERT_TRUE(store_->Close()); 299 EXPECT_EQ(base::StringPrintf("[%s]\n" 300 "%s=%d\n", 301 kGroup, kKeyAlive, kValueAlive), 302 ReadKeyFile()); 303 } 304 305 TEST_F(KeyFileStoreTest, DeleteGroup) { 306 static const char kGroupA[] = "group-a"; 307 static const char kGroupB[] = "group-b"; 308 static const char kGroupC[] = "group-c"; 309 WriteKeyFile(base::StringPrintf("[%s]\n" 310 "[%s]\n" 311 "key-to-be-deleted=true\n" 312 "[%s]\n", 313 kGroupA, kGroupB, kGroupC)); 314 ASSERT_TRUE(store_->Open()); 315 EXPECT_TRUE(store_->DeleteGroup(kGroupB)); 316 EXPECT_TRUE(store_->DeleteGroup("group-d")); 317 ASSERT_TRUE(store_->Close()); 318 EXPECT_EQ(base::StringPrintf("[%s]\n" 319 "\n" 320 "[%s]\n", 321 kGroupA, kGroupC), 322 ReadKeyFile()); 323 } 324 325 TEST_F(KeyFileStoreTest, GetString) { 326 static const char kGroup[] = "something"; 327 static const char kKey[] = "foo"; 328 static const char kValue[] = "bar"; 329 WriteKeyFile(base::StringPrintf("[%s]\n" 330 "%s=%s\n", 331 kGroup, kKey, kValue)); 332 ASSERT_TRUE(store_->Open()); 333 string value; 334 EXPECT_TRUE(store_->GetString(kGroup, kKey, &value)); 335 EXPECT_EQ(kValue, value); 336 EXPECT_FALSE(store_->GetString("something-else", kKey, &value)); 337 EXPECT_FALSE(store_->GetString(kGroup, "bar", &value)); 338 EXPECT_TRUE(store_->GetString(kGroup, kKey, nullptr)); 339 ASSERT_TRUE(store_->Close()); 340 } 341 342 TEST_F(KeyFileStoreTest, SetString) { 343 static const char kGroup[] = "string-group"; 344 static const char kKey1[] = "test-string"; 345 static const char kValue1[] = "foo"; 346 static const char kKey2[] = "empty-string"; 347 static const char kValue2[] = ""; 348 ASSERT_TRUE(store_->Open()); 349 ASSERT_TRUE(store_->SetString(kGroup, kKey1, kValue1)); 350 ASSERT_TRUE(store_->SetString(kGroup, kKey2, kValue2)); 351 ASSERT_TRUE(store_->Close()); 352 EXPECT_EQ(base::StringPrintf("[%s]\n" 353 "%s=%s\n" 354 "%s=%s\n", 355 kGroup, kKey1, kValue1, kKey2, kValue2), 356 ReadKeyFile()); 357 } 358 359 TEST_F(KeyFileStoreTest, GetBool) { 360 static const char kGroup[] = "boo"; 361 static const char kKeyTrue[] = "foo"; 362 static const char kKeyFalse[] = "bar"; 363 static const char kKeyBad[] = "zoo"; 364 WriteKeyFile(base::StringPrintf("[%s]\n" 365 "%s=true\n" 366 "%s=false\n" 367 "%s=moo\n", 368 kGroup, kKeyTrue, kKeyFalse, kKeyBad)); 369 ASSERT_TRUE(store_->Open()); 370 { 371 bool value = true; 372 EXPECT_TRUE(store_->GetBool(kGroup, kKeyFalse, &value)); 373 EXPECT_FALSE(value); 374 } 375 { 376 bool value = false; 377 EXPECT_TRUE(store_->GetBool(kGroup, kKeyTrue, &value)); 378 EXPECT_TRUE(value); 379 } 380 { 381 bool value; 382 EXPECT_FALSE(store_->GetBool(kGroup, kKeyBad, &value)); 383 EXPECT_FALSE(store_->GetBool(kGroup, "unknown", &value)); 384 EXPECT_FALSE(store_->GetBool("unknown", kKeyTrue, &value)); 385 } 386 EXPECT_TRUE(store_->GetBool(kGroup, kKeyFalse, nullptr)); 387 ASSERT_TRUE(store_->Close()); 388 } 389 390 TEST_F(KeyFileStoreTest, SetBool) { 391 static const char kGroup[] = "bool-group"; 392 static const char kKeyTrue[] = "test-true-bool"; 393 static const char kKeyFalse[] = "test-false-bool"; 394 ASSERT_TRUE(store_->Open()); 395 ASSERT_TRUE(store_->SetBool(kGroup, kKeyTrue, true)); 396 ASSERT_TRUE(store_->SetBool(kGroup, kKeyFalse, false)); 397 ASSERT_TRUE(store_->Close()); 398 EXPECT_EQ(base::StringPrintf("[%s]\n" 399 "%s=true\n" 400 "%s=false\n", 401 kGroup, kKeyTrue, kKeyFalse), 402 ReadKeyFile()); 403 } 404 405 TEST_F(KeyFileStoreTest, GetInt) { 406 static const char kGroup[] = "numbers"; 407 static const char kKeyPos[] = "pos"; 408 static const char kKeyNeg[] = "neg"; 409 static const char kKeyBad[] = "bad"; 410 const int kValuePos = 50; 411 const int kValueNeg = -20; 412 static const char kValueBad[] = "nan"; 413 WriteKeyFile(base::StringPrintf("[%s]\n" 414 "%s=%d\n" 415 "%s=%d\n" 416 "%s=%s\n", 417 kGroup, 418 kKeyPos, kValuePos, 419 kKeyNeg, kValueNeg, 420 kKeyBad, kValueBad)); 421 ASSERT_TRUE(store_->Open()); 422 { 423 int value = 0; 424 EXPECT_TRUE(store_->GetInt(kGroup, kKeyNeg, &value)); 425 EXPECT_EQ(kValueNeg, value); 426 } 427 { 428 int value = 0; 429 EXPECT_TRUE(store_->GetInt(kGroup, kKeyPos, &value)); 430 EXPECT_EQ(kValuePos, value); 431 } 432 { 433 int value; 434 EXPECT_FALSE(store_->GetInt(kGroup, kKeyBad, &value)); 435 EXPECT_FALSE(store_->GetInt(kGroup, "invalid", &value)); 436 EXPECT_FALSE(store_->GetInt("invalid", kKeyPos, &value)); 437 } 438 EXPECT_TRUE(store_->GetInt(kGroup, kKeyPos, nullptr)); 439 ASSERT_TRUE(store_->Close()); 440 } 441 442 TEST_F(KeyFileStoreTest, SetInt) { 443 static const char kGroup[] = "int-group"; 444 static const char kKey1[] = "test-int"; 445 static const char kKey2[] = "test-negative"; 446 const int kValue1 = 5; 447 const int kValue2 = -10; 448 ASSERT_TRUE(store_->Open()); 449 ASSERT_TRUE(store_->SetInt(kGroup, kKey1, kValue1)); 450 ASSERT_TRUE(store_->SetInt(kGroup, kKey2, kValue2)); 451 ASSERT_TRUE(store_->Close()); 452 EXPECT_EQ(base::StringPrintf("[%s]\n" 453 "%s=%d\n" 454 "%s=%d\n", 455 kGroup, kKey1, kValue1, kKey2, kValue2), 456 ReadKeyFile()); 457 } 458 459 TEST_F(KeyFileStoreTest, GetUint64) { 460 static const char kGroup[] = "numbers"; 461 static const char kKeyGood[] = "good"; 462 static const char kKeyBad[] = "bad"; 463 const uint64_t kValueGood = 0xFEDCBA9876543210LL; 464 static const char kValueBad[] = "nan"; 465 // Use base::Uint64ToString() instead of using something like "%llu" 466 // (not correct for native 64 bit architectures) or PRIu64 (does not 467 // work correctly using cros_workon_make due to include intricacies). 468 WriteKeyFile(base::StringPrintf("[%s]\n" 469 "%s=%s\n" 470 "%s=%s\n", 471 kGroup, 472 kKeyGood, 473 base::Uint64ToString(kValueGood).c_str(), 474 kKeyBad, kValueBad)); 475 ASSERT_TRUE(store_->Open()); 476 { 477 uint64_t value = 0; 478 EXPECT_TRUE(store_->GetUint64(kGroup, kKeyGood, &value)); 479 EXPECT_EQ(kValueGood, value); 480 } 481 { 482 uint64_t value; 483 EXPECT_FALSE(store_->GetUint64(kGroup, kKeyBad, &value)); 484 EXPECT_FALSE(store_->GetUint64(kGroup, "invalid", &value)); 485 EXPECT_FALSE(store_->GetUint64("invalid", kKeyGood, &value)); 486 } 487 EXPECT_TRUE(store_->GetUint64(kGroup, kKeyGood, nullptr)); 488 ASSERT_TRUE(store_->Close()); 489 } 490 491 TEST_F(KeyFileStoreTest, SetUint64) { 492 static const char kGroup[] = "int-group"; 493 static const char kKey[] = "test-int"; 494 const uint64_t kValue = 0xFEDCBA9876543210LL; 495 ASSERT_TRUE(store_->Open()); 496 ASSERT_TRUE(store_->SetUint64(kGroup, kKey, kValue)); 497 ASSERT_TRUE(store_->Close()); 498 EXPECT_EQ(base::StringPrintf("[%s]\n" 499 "%s=%s\n", 500 kGroup, kKey, 501 base::Uint64ToString(kValue).c_str()), 502 ReadKeyFile()); 503 } 504 505 TEST_F(KeyFileStoreTest, GetStringList) { 506 static const char kGroup[] = "string-lists"; 507 static const char kKeyEmpty[] = "empty"; 508 static const char kKeyEmptyValue[] = "empty-value"; 509 static const char kKeyValueEmpty[] = "value-empty"; 510 static const char kKeyValueEmptyValue[] = "value-empty-value"; 511 static const char kKeyValues[] = "values"; 512 static const char kValue[] = "value"; 513 static const char kValue2[] = "value2"; 514 static const char kValue3[] = "value3"; 515 WriteKeyFile(base::StringPrintf("[%s]\n" 516 "%s=\n" 517 "%s=;%s\n" 518 "%s=%s;;\n" 519 "%s=%s;;%s\n" 520 "%s=%s;%s;%s\n", 521 kGroup, 522 kKeyEmpty, 523 kKeyEmptyValue, kValue, 524 kKeyValueEmpty, kValue, 525 kKeyValueEmptyValue, kValue, kValue2, 526 kKeyValues, kValue, kValue2, kValue3)); 527 ASSERT_TRUE(store_->Open()); 528 529 vector<string> value; 530 531 EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValues, &value)); 532 ASSERT_EQ(3, value.size()); 533 EXPECT_EQ(kValue, value[0]); 534 EXPECT_EQ(kValue2, value[1]); 535 EXPECT_EQ(kValue3, value[2]); 536 537 EXPECT_TRUE(store_->GetStringList(kGroup, kKeyEmptyValue, &value)); 538 ASSERT_EQ(2, value.size()); 539 EXPECT_EQ("", value[0]); 540 EXPECT_EQ(kValue, value[1]); 541 542 EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValueEmpty, &value)); 543 ASSERT_EQ(2, value.size()); 544 EXPECT_EQ(kValue, value[0]); 545 EXPECT_EQ("", value[1]); 546 547 EXPECT_TRUE(store_->GetStringList(kGroup, kKeyEmpty, &value)); 548 ASSERT_EQ(0, value.size()); 549 550 EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValueEmptyValue, &value)); 551 ASSERT_EQ(3, value.size()); 552 EXPECT_EQ(kValue, value[0]); 553 EXPECT_EQ("", value[1]); 554 EXPECT_EQ(kValue2, value[2]); 555 556 EXPECT_FALSE(store_->GetStringList("unknown-string-lists", 557 kKeyEmpty, 558 &value)); 559 EXPECT_FALSE(store_->GetStringList(kGroup, "some-key", &value)); 560 EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValues, nullptr)); 561 ASSERT_TRUE(store_->Close()); 562 } 563 564 TEST_F(KeyFileStoreTest, SetStringList) { 565 static const char kGroup[] = "strings"; 566 static const char kKeyEmpty[] = "e"; 567 static const char kKeyEmptyValue[] = "ev"; 568 static const char kKeyValueEmpty[] = "ve"; 569 static const char kKeyValueEmptyValue[] = "vev"; 570 static const char kKeyValues[] = "v"; 571 static const char kValue[] = "abc"; 572 static const char kValue2[] = "pqr"; 573 static const char kValue3[] = "xyz"; 574 ASSERT_TRUE(store_->Open()); 575 { 576 vector<string> value; 577 ASSERT_TRUE(store_->SetStringList(kGroup, kKeyEmpty, value)); 578 } 579 { 580 vector<string> value; 581 value.push_back(""); 582 value.push_back(kValue); 583 ASSERT_TRUE(store_->SetStringList(kGroup, kKeyEmptyValue, value)); 584 } 585 { 586 vector<string> value; 587 value.push_back(kValue); 588 value.push_back(""); 589 ASSERT_TRUE(store_->SetStringList(kGroup, kKeyValueEmpty, value)); 590 } 591 { 592 vector<string> value; 593 value.push_back(kValue); 594 value.push_back(""); 595 value.push_back(kValue2); 596 ASSERT_TRUE(store_->SetStringList(kGroup, kKeyValueEmptyValue, value)); 597 } 598 { 599 vector<string> value; 600 value.push_back(kValue); 601 value.push_back(kValue2); 602 value.push_back(kValue3); 603 ASSERT_TRUE(store_->SetStringList(kGroup, kKeyValues, value)); 604 } 605 ASSERT_TRUE(store_->Close()); 606 EXPECT_EQ(base::StringPrintf("[%s]\n" 607 "%s=\n" 608 "%s=;%s;\n" 609 "%s=%s;;\n" 610 "%s=%s;;%s;\n" 611 "%s=%s;%s;%s;\n", 612 kGroup, 613 kKeyEmpty, 614 kKeyEmptyValue, kValue, 615 kKeyValueEmpty, kValue, 616 kKeyValueEmptyValue, kValue, kValue2, 617 kKeyValues, kValue, kValue2, kValue3), 618 ReadKeyFile()); 619 } 620 621 TEST_F(KeyFileStoreTest, GetCryptedString) { 622 static const char kGroup[] = "crypto-group"; 623 static const char kKey[] = "secret"; 624 WriteKeyFile(base::StringPrintf("[%s]\n" 625 "%s=%s\n", 626 kGroup, kKey, kROT47Text)); 627 ASSERT_TRUE(store_->Open()); 628 string value; 629 EXPECT_TRUE(store_->GetCryptedString(kGroup, kKey, &value)); 630 EXPECT_EQ(kPlainText, value); 631 EXPECT_FALSE(store_->GetCryptedString("something-else", kKey, &value)); 632 EXPECT_FALSE(store_->GetCryptedString(kGroup, "non-secret", &value)); 633 EXPECT_TRUE(store_->GetCryptedString(kGroup, kKey, nullptr)); 634 ASSERT_TRUE(store_->Close()); 635 } 636 637 TEST_F(KeyFileStoreTest, SetCryptedString) { 638 static const char kGroup[] = "crypted-string-group"; 639 static const char kKey[] = "test-string"; 640 ASSERT_TRUE(store_->Open()); 641 ASSERT_TRUE(store_->SetCryptedString(kGroup, kKey, kPlainText)); 642 ASSERT_TRUE(store_->Close()); 643 EXPECT_EQ(base::StringPrintf("[%s]\n" 644 "%s=%s\n", 645 kGroup, kKey, kROT47Text), 646 ReadKeyFile()); 647 } 648 649 TEST_F(KeyFileStoreTest, PersistAcrossClose) { 650 static const char kGroup[] = "string-group"; 651 static const char kKey1[] = "test-string"; 652 static const char kValue1[] = "foo"; 653 static const char kKey2[] = "empty-string"; 654 static const char kValue2[] = ""; 655 ASSERT_TRUE(store_->Open()); 656 ASSERT_TRUE(store_->SetString(kGroup, kKey1, kValue1)); 657 ASSERT_TRUE(store_->Close()); 658 ASSERT_TRUE(store_->Open()); 659 ASSERT_TRUE(store_->SetString(kGroup, kKey2, kValue2)); 660 string value; 661 ASSERT_TRUE(store_->GetString(kGroup, kKey1, &value)); 662 ASSERT_EQ(kValue1, value); 663 ASSERT_TRUE(store_->GetString(kGroup, kKey2, &value)); 664 ASSERT_EQ(kValue2, value); 665 ASSERT_TRUE(store_->Close()); 666 } 667 668 namespace { 669 class ReadOnlyKeyFileStore : public KeyFileStore { 670 public: 671 explicit ReadOnlyKeyFileStore(const base::FilePath& path) 672 : KeyFileStore(path) {} 673 bool Flush() override { return true; } 674 }; 675 676 bool OpenCheckClose(const FilePath& path, 677 const string& group, 678 const string& key, 679 const string& expected_value) { 680 ReadOnlyKeyFileStore store(path); // Don't modify file owned by caller. 681 EXPECT_TRUE(store.Open()); 682 string value; 683 bool could_get = store.GetString(group, key, &value); 684 store.Close(); 685 return could_get && expected_value == value; 686 } 687 688 TEST_F(KeyFileStoreTest, Flush) { 689 static const char kGroup[] = "string-group"; 690 static const char kKey1[] = "test-string"; 691 static const char kValue1[] = "foo"; 692 static const char kKey2[] = "empty-string"; 693 static const char kValue2[] = ""; 694 ASSERT_TRUE(store_->Open()); 695 ASSERT_TRUE(store_->SetString(kGroup, kKey1, kValue1)); 696 ASSERT_TRUE(store_->Flush()); 697 ASSERT_TRUE(OpenCheckClose(test_file_, kGroup, kKey1, kValue1)); 698 699 ASSERT_TRUE(store_->SetString(kGroup, kKey2, kValue2)); 700 ASSERT_TRUE(store_->Flush()); 701 ASSERT_TRUE(OpenCheckClose(test_file_, kGroup, kKey2, kValue2)); 702 703 EXPECT_TRUE(store_->DeleteKey(kGroup, kKey1)); 704 ASSERT_TRUE(store_->Flush()); 705 ASSERT_FALSE(OpenCheckClose(test_file_, kGroup, kKey1, kValue1)); 706 } 707 } // namespace 708 709 TEST_F(KeyFileStoreTest, EmptyFile) { 710 ASSERT_TRUE(store_->Open()); 711 ASSERT_TRUE(store_->Close()); 712 EXPECT_FALSE(store_->IsNonEmpty()); 713 } 714 715 TEST_F(KeyFileStoreTest, SetHeader) { 716 ASSERT_TRUE(store_->Open()); 717 ASSERT_TRUE(store_->SetHeader("this is a test")); 718 ASSERT_TRUE(store_->Close()); 719 EXPECT_TRUE(store_->IsNonEmpty()); 720 ASSERT_TRUE(store_->Open()); 721 } 722 723 TEST_F(KeyFileStoreTest, Combo) { 724 static const char kGroupA[] = "square"; 725 static const char kGroupB[] = "circle"; 726 static const char kGroupC[] = "triangle"; 727 static const char kGroupX[] = "pentagon"; 728 static const char kKeyString[] = "color"; 729 static const char kKeyStringList[] = "alternative-colors"; 730 static const char kKeyInt[] = "area"; 731 static const char kKeyBool[] = "visible"; 732 static const char kValueStringA[] = "blue"; 733 static const char kValueStringB[] = "red"; 734 static const char kValueStringC[] = "yellow"; 735 static const char kValueStringCNew[] = "purple"; 736 const int kValueIntA = 5; 737 const int kValueIntB = 10; 738 const int kValueIntBNew = 333; 739 WriteKeyFile(base::StringPrintf("[%s]\n" 740 "%s=%s\n" 741 "%s=%s;%s\n" 742 "%s=%d\n" 743 "[%s]\n" 744 "%s=%s\n" 745 "%s=%s;%s\n" 746 "%s=%d\n" 747 "%s=true\n" 748 "[%s]\n" 749 "%s=%s\n" 750 "%s=false\n", 751 kGroupA, 752 kKeyString, kValueStringA, 753 kKeyStringList, kValueStringB, kValueStringC, 754 kKeyInt, kValueIntA, 755 kGroupB, 756 kKeyString, kValueStringB, 757 kKeyStringList, kValueStringA, kValueStringC, 758 kKeyInt, kValueIntB, 759 kKeyBool, 760 kGroupC, 761 kKeyString, kValueStringC, 762 kKeyBool)); 763 ASSERT_TRUE(store_->Open()); 764 765 EXPECT_TRUE(store_->ContainsGroup(kGroupA)); 766 EXPECT_TRUE(store_->ContainsGroup(kGroupB)); 767 EXPECT_TRUE(store_->ContainsGroup(kGroupC)); 768 EXPECT_FALSE(store_->ContainsGroup(kGroupX)); 769 770 set<string> groups = store_->GetGroups(); 771 EXPECT_EQ(3, groups.size()); 772 EXPECT_TRUE(ContainsKey(groups, kGroupA)); 773 EXPECT_TRUE(ContainsKey(groups, kGroupB)); 774 EXPECT_TRUE(ContainsKey(groups, kGroupC)); 775 EXPECT_FALSE(ContainsKey(groups, kGroupX)); 776 777 { 778 string value; 779 EXPECT_TRUE(store_->GetString(kGroupB, kKeyString, &value)); 780 EXPECT_EQ(kValueStringB, value); 781 EXPECT_TRUE(store_->GetString(kGroupA, kKeyString, &value)); 782 EXPECT_EQ(kValueStringA, value); 783 EXPECT_TRUE(store_->GetString(kGroupC, kKeyString, &value)); 784 EXPECT_EQ(kValueStringC, value); 785 } 786 { 787 vector<string> value; 788 EXPECT_TRUE(store_->GetStringList(kGroupB, kKeyStringList, &value)); 789 ASSERT_EQ(2, value.size()); 790 EXPECT_EQ(kValueStringA, value[0]); 791 EXPECT_EQ(kValueStringC, value[1]); 792 EXPECT_TRUE(store_->GetStringList(kGroupA, kKeyStringList, &value)); 793 ASSERT_EQ(2, value.size()); 794 EXPECT_EQ(kValueStringB, value[0]); 795 EXPECT_EQ(kValueStringC, value[1]); 796 EXPECT_FALSE(store_->GetStringList(kGroupC, kKeyStringList, &value)); 797 } 798 { 799 int value = 0; 800 EXPECT_TRUE(store_->GetInt(kGroupB, kKeyInt, &value)); 801 EXPECT_EQ(kValueIntB, value); 802 EXPECT_TRUE(store_->GetInt(kGroupA, kKeyInt, &value)); 803 EXPECT_EQ(kValueIntA, value); 804 EXPECT_FALSE(store_->GetInt(kGroupC, kKeyInt, &value)); 805 } 806 { 807 bool value = false; 808 EXPECT_TRUE(store_->GetBool(kGroupB, kKeyBool, &value)); 809 EXPECT_TRUE(value); 810 EXPECT_TRUE(store_->GetBool(kGroupC, kKeyBool, &value)); 811 EXPECT_FALSE(value); 812 EXPECT_FALSE(store_->GetBool(kGroupA, kKeyBool, &value)); 813 } 814 815 EXPECT_TRUE(store_->DeleteGroup(kGroupA)); 816 EXPECT_TRUE(store_->DeleteGroup(kGroupA)); 817 818 EXPECT_FALSE(store_->ContainsGroup(kGroupA)); 819 EXPECT_TRUE(store_->ContainsGroup(kGroupB)); 820 EXPECT_TRUE(store_->ContainsGroup(kGroupC)); 821 822 groups = store_->GetGroups(); 823 EXPECT_EQ(2, groups.size()); 824 EXPECT_FALSE(ContainsKey(groups, kGroupA)); 825 EXPECT_TRUE(ContainsKey(groups, kGroupB)); 826 EXPECT_TRUE(ContainsKey(groups, kGroupC)); 827 828 EXPECT_TRUE(store_->SetBool(kGroupB, kKeyBool, false)); 829 EXPECT_TRUE(store_->SetInt(kGroupB, kKeyInt, kValueIntBNew)); 830 EXPECT_TRUE(store_->SetString(kGroupC, kKeyString, kValueStringCNew)); 831 store_->SetStringList(kGroupB, 832 kKeyStringList, 833 vector<string>(1, kValueStringB)); 834 835 EXPECT_TRUE(store_->DeleteKey(kGroupB, kKeyString)); 836 EXPECT_TRUE(store_->DeleteKey(kGroupB, kKeyString)); 837 838 { 839 string value; 840 EXPECT_FALSE(store_->GetString(kGroupB, kKeyString, &value)); 841 EXPECT_FALSE(store_->GetString(kGroupA, kKeyString, &value)); 842 EXPECT_TRUE(store_->GetString(kGroupC, kKeyString, &value)); 843 EXPECT_EQ(kValueStringCNew, value); 844 } 845 { 846 vector<string> value; 847 EXPECT_TRUE(store_->GetStringList(kGroupB, kKeyStringList, &value)); 848 ASSERT_EQ(1, value.size()); 849 EXPECT_EQ(kValueStringB, value[0]); 850 EXPECT_FALSE(store_->GetStringList(kGroupA, kKeyStringList, &value)); 851 EXPECT_FALSE(store_->GetStringList(kGroupC, kKeyStringList, &value)); 852 } 853 { 854 int value = 0; 855 EXPECT_TRUE(store_->GetInt(kGroupB, kKeyInt, &value)); 856 EXPECT_EQ(kValueIntBNew, value); 857 EXPECT_FALSE(store_->GetInt(kGroupA, kKeyInt, &value)); 858 EXPECT_FALSE(store_->GetInt(kGroupC, kKeyInt, &value)); 859 } 860 { 861 bool value = false; 862 EXPECT_TRUE(store_->GetBool(kGroupB, kKeyBool, &value)); 863 EXPECT_FALSE(value); 864 EXPECT_TRUE(store_->GetBool(kGroupC, kKeyBool, &value)); 865 EXPECT_FALSE(value); 866 EXPECT_FALSE(store_->GetBool(kGroupA, kKeyBool, &value)); 867 } 868 869 ASSERT_TRUE(store_->Close()); 870 EXPECT_EQ(base::StringPrintf("[%s]\n" 871 "%s=%s;\n" 872 "%s=%d\n" 873 "%s=false\n" 874 "\n" 875 "[%s]\n" 876 "%s=%s\n" 877 "%s=false\n", 878 kGroupB, 879 kKeyStringList, kValueStringB, 880 kKeyInt, kValueIntBNew, 881 kKeyBool, 882 kGroupC, 883 kKeyString, kValueStringCNew, 884 kKeyBool), 885 ReadKeyFile()); 886 } 887 888 } // namespace shill 889