Home | History | Annotate | Download | only in shill
      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