| // |
| // Copyright (C) 2012 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "shill/key_file_store.h" |
| |
| #include <sys/stat.h> |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include <base/files/file_enumerator.h> |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/stl_util.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <base/strings/stringprintf.h> |
| #include <gtest/gtest.h> |
| |
| #include "shill/key_value_store.h" |
| |
| using base::FileEnumerator; |
| using base::FilePath; |
| using std::set; |
| using std::string; |
| using std::unique_ptr; |
| using std::vector; |
| using testing::Test; |
| |
| namespace shill { |
| |
| namespace { |
| const char kPlainText[] = "This is a test!"; |
| const char kROT47Text[] = "rot47:%9:D :D 2 E6DEP"; |
| } // namespace |
| |
| class KeyFileStoreTest : public Test { |
| public: |
| KeyFileStoreTest() {} |
| |
| virtual void SetUp() { |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| test_file_ = temp_dir_.path().Append("test-key-file-store"); |
| store_.reset(new KeyFileStore(test_file_)); |
| } |
| |
| virtual void TearDown() { |
| ASSERT_TRUE(temp_dir_.Delete()); |
| } |
| |
| protected: |
| string ReadKeyFile(); |
| void WriteKeyFile(string data); |
| |
| base::ScopedTempDir temp_dir_; |
| FilePath test_file_; |
| unique_ptr<KeyFileStore> store_; |
| }; |
| |
| string KeyFileStoreTest::ReadKeyFile() { |
| string data; |
| EXPECT_TRUE(base::ReadFileToString(test_file_, &data)); |
| return data; |
| } |
| |
| void KeyFileStoreTest::WriteKeyFile(string data) { |
| EXPECT_EQ(data.size(), |
| base::WriteFile(test_file_, data.data(), data.size())); |
| } |
| |
| TEST_F(KeyFileStoreTest, OpenClose) { |
| EXPECT_FALSE(store_->key_file_); |
| |
| EXPECT_FALSE(store_->IsNonEmpty()); |
| ASSERT_TRUE(store_->Open()); |
| EXPECT_TRUE(store_->key_file_); |
| EXPECT_EQ(1, store_->crypto_.cryptos_.size()); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_FALSE(store_->key_file_); |
| FileEnumerator file_enumerator(temp_dir_.path(), |
| false /* not recursive */, |
| FileEnumerator::FILES); |
| |
| // Verify that the file actually got written with the right name. |
| EXPECT_EQ(test_file_.value(), file_enumerator.Next().value()); |
| FileEnumerator::FileInfo file_info = file_enumerator.GetInfo(); |
| |
| // Verify that the profile is a regular file, readable and writeable by the |
| // owner only. |
| EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR, file_info.stat().st_mode); |
| |
| ASSERT_TRUE(store_->Open()); |
| EXPECT_TRUE(store_->key_file_); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_FALSE(store_->key_file_); |
| |
| ASSERT_TRUE(store_->Open()); |
| // Replace file with directory, to force Flush() to fail. |
| ASSERT_TRUE(base::DeleteFile(test_file_, false)); |
| ASSERT_TRUE(base::CreateDirectory(test_file_)); |
| ASSERT_FALSE(store_->Close()); |
| EXPECT_FALSE(store_->key_file_); |
| } |
| |
| TEST_F(KeyFileStoreTest, OpenFail) { |
| WriteKeyFile("garbage\n"); |
| EXPECT_FALSE(store_->Open()); |
| EXPECT_FALSE(store_->key_file_); |
| } |
| |
| TEST_F(KeyFileStoreTest, MarkAsCorrupted) { |
| EXPECT_FALSE(store_->MarkAsCorrupted()); |
| EXPECT_FALSE(store_->IsNonEmpty()); |
| WriteKeyFile("garbage\n"); |
| EXPECT_TRUE(store_->IsNonEmpty()); |
| EXPECT_TRUE(base::PathExists(test_file_)); |
| EXPECT_TRUE(store_->MarkAsCorrupted()); |
| EXPECT_FALSE(store_->IsNonEmpty()); |
| EXPECT_FALSE(base::PathExists(test_file_)); |
| EXPECT_TRUE(base::PathExists(FilePath(test_file_.value() + ".corrupted"))); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetGroups) { |
| static const char kGroupA[] = "g-a"; |
| static const char kGroupB[] = "g-b"; |
| static const char kGroupC[] = "g-c"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "[%s]\n" |
| "[%s]\n", |
| kGroupA, kGroupB, kGroupC)); |
| EXPECT_TRUE(store_->IsNonEmpty()); |
| ASSERT_TRUE(store_->Open()); |
| set<string> groups = store_->GetGroups(); |
| EXPECT_EQ(3, groups.size()); |
| EXPECT_TRUE(ContainsKey(groups, kGroupA)); |
| EXPECT_TRUE(ContainsKey(groups, kGroupB)); |
| EXPECT_TRUE(ContainsKey(groups, kGroupC)); |
| EXPECT_FALSE(ContainsKey(groups, "g-x")); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetGroupsWithKey) { |
| static const char kGroupA[] = "g-a"; |
| static const char kGroupB[] = "g-b"; |
| static const char kGroupC[] = "g-c"; |
| static const char kKeyA[] = "k-a"; |
| static const char kKeyB[] = "k-b"; |
| static const char kValue[] = "true"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%s\n" |
| "[%s]\n" |
| "%s=%s\n" |
| "%s=%s\n" |
| "[%s]\n" |
| "%s=%s\n", |
| kGroupA, kKeyA, kValue, |
| kGroupB, kKeyA, kValue, kKeyB, kValue, |
| kGroupC, kKeyB, kValue)); |
| EXPECT_TRUE(store_->IsNonEmpty()); |
| ASSERT_TRUE(store_->Open()); |
| set<string> groups_a = store_->GetGroupsWithKey(kKeyA); |
| EXPECT_EQ(2, groups_a.size()); |
| EXPECT_TRUE(ContainsKey(groups_a, kGroupA)); |
| EXPECT_TRUE(ContainsKey(groups_a, kGroupB)); |
| set<string> groups_b = store_->GetGroupsWithKey(kKeyB); |
| EXPECT_EQ(2, groups_b.size()); |
| EXPECT_TRUE(ContainsKey(groups_b, kGroupB)); |
| EXPECT_TRUE(ContainsKey(groups_b, kGroupC)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, ContainsGroup) { |
| static const char kGroupA[] = "group-a"; |
| static const char kGroupB[] = "group-b"; |
| static const char kGroupC[] = "group-c"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "[%s]\n" |
| "[%s]\n", |
| kGroupA, kGroupB, kGroupC)); |
| ASSERT_TRUE(store_->Open()); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupA)); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupB)); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupC)); |
| EXPECT_FALSE(store_->ContainsGroup("group-d")); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetGroupsWithProperties) { |
| static const char kGroupA[] = "group-a"; |
| static const char kGroupB[] = "group-b"; |
| static const char kGroupC[] = "group-c"; |
| static const char kAttributeA[] = "attr-a"; |
| static const char kAttributeB[] = "attr-b"; |
| static const char kAttributeC[] = "attr-c"; |
| static const char kValueA_0[] = "val-a"; |
| static const char kValueA_1[] = "val-b"; |
| static const int kValueB_0 = 1; |
| static const int kValueB_1 = 2; |
| static const bool kValueC_0 = true; |
| static const char kValueC_0_string[] = "true"; |
| static const bool kValueC_1 = false; |
| static const char kValueC_1_string[] = "false"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%s\n" |
| "%s=%d\n" |
| "%s=%s\n" |
| "[%s]\n" |
| "%s=%s\n" |
| "%s=%d\n" |
| "%s=%s\n" |
| "[%s]\n" |
| "%s=%s\n" |
| "%s=%d\n" |
| "%s=%s\n", |
| kGroupA, |
| kAttributeA, kValueA_0, |
| kAttributeB, kValueB_0, |
| kAttributeC, kValueC_0_string, |
| kGroupB, |
| kAttributeA, kValueA_0, |
| kAttributeB, kValueB_1, |
| kAttributeC, kValueC_0_string, |
| kGroupC, |
| kAttributeA, kValueA_0, |
| kAttributeB, kValueB_0, |
| kAttributeC, kValueC_1_string)); |
| ASSERT_TRUE(store_->Open()); |
| { |
| KeyValueStore args; |
| args.SetString(kAttributeA, kValueA_0); |
| args.SetInt(kAttributeB, kValueB_0); |
| set<string> results = store_->GetGroupsWithProperties(args); |
| EXPECT_EQ(2, results.size()); |
| EXPECT_TRUE(results.find(kGroupA) != results.end()); |
| EXPECT_TRUE(results.find(kGroupC) != results.end()); |
| } |
| { |
| KeyValueStore args; |
| args.SetString(kAttributeA, kValueA_0); |
| args.SetBool(kAttributeC, kValueC_0); |
| set<string> results = store_->GetGroupsWithProperties(args); |
| EXPECT_EQ(2, results.size()); |
| EXPECT_TRUE(results.find(kGroupA) != results.end()); |
| EXPECT_TRUE(results.find(kGroupB) != results.end()); |
| } |
| { |
| KeyValueStore args; |
| args.SetBool(kAttributeC, kValueC_1); |
| set<string> results = store_->GetGroupsWithProperties(args); |
| EXPECT_EQ(1, results.size()); |
| EXPECT_TRUE(results.find(kGroupC) != results.end()); |
| } |
| { |
| KeyValueStore args; |
| args.SetString(kAttributeA, kValueA_0); |
| set<string> results = store_->GetGroupsWithProperties(args); |
| EXPECT_EQ(3, results.size()); |
| EXPECT_TRUE(results.find(kGroupA) != results.end()); |
| EXPECT_TRUE(results.find(kGroupB) != results.end()); |
| EXPECT_TRUE(results.find(kGroupC) != results.end()); |
| } |
| { |
| KeyValueStore args; |
| args.SetString(kAttributeA, kValueA_1); |
| set<string> results = store_->GetGroupsWithProperties(args); |
| EXPECT_EQ(0, results.size()); |
| } |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, DeleteKey) { |
| static const char kGroup[] = "the-group"; |
| static const char kKeyDead[] = "dead"; |
| static const char kKeyAlive[] = "alive"; |
| const int kValueAlive = 3; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=5\n" |
| "%s=%d\n", |
| kGroup, kKeyDead, kKeyAlive, kValueAlive)); |
| ASSERT_TRUE(store_->Open()); |
| EXPECT_TRUE(store_->DeleteKey(kGroup, kKeyDead)); |
| EXPECT_TRUE(store_->DeleteKey(kGroup, "random-key")); |
| EXPECT_FALSE(store_->DeleteKey("random-group", kKeyAlive)); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=%d\n", |
| kGroup, kKeyAlive, kValueAlive), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, DeleteGroup) { |
| static const char kGroupA[] = "group-a"; |
| static const char kGroupB[] = "group-b"; |
| static const char kGroupC[] = "group-c"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "[%s]\n" |
| "key-to-be-deleted=true\n" |
| "[%s]\n", |
| kGroupA, kGroupB, kGroupC)); |
| ASSERT_TRUE(store_->Open()); |
| EXPECT_TRUE(store_->DeleteGroup(kGroupB)); |
| EXPECT_TRUE(store_->DeleteGroup("group-d")); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "\n" |
| "[%s]\n", |
| kGroupA, kGroupC), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetString) { |
| static const char kGroup[] = "something"; |
| static const char kKey[] = "foo"; |
| static const char kValue[] = "bar"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%s\n", |
| kGroup, kKey, kValue)); |
| ASSERT_TRUE(store_->Open()); |
| string value; |
| EXPECT_TRUE(store_->GetString(kGroup, kKey, &value)); |
| EXPECT_EQ(kValue, value); |
| EXPECT_FALSE(store_->GetString("something-else", kKey, &value)); |
| EXPECT_FALSE(store_->GetString(kGroup, "bar", &value)); |
| EXPECT_TRUE(store_->GetString(kGroup, kKey, nullptr)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetString) { |
| static const char kGroup[] = "string-group"; |
| static const char kKey1[] = "test-string"; |
| static const char kValue1[] = "foo"; |
| static const char kKey2[] = "empty-string"; |
| static const char kValue2[] = ""; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetString(kGroup, kKey1, kValue1)); |
| ASSERT_TRUE(store_->SetString(kGroup, kKey2, kValue2)); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=%s\n" |
| "%s=%s\n", |
| kGroup, kKey1, kValue1, kKey2, kValue2), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetBool) { |
| static const char kGroup[] = "boo"; |
| static const char kKeyTrue[] = "foo"; |
| static const char kKeyFalse[] = "bar"; |
| static const char kKeyBad[] = "zoo"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=true\n" |
| "%s=false\n" |
| "%s=moo\n", |
| kGroup, kKeyTrue, kKeyFalse, kKeyBad)); |
| ASSERT_TRUE(store_->Open()); |
| { |
| bool value = true; |
| EXPECT_TRUE(store_->GetBool(kGroup, kKeyFalse, &value)); |
| EXPECT_FALSE(value); |
| } |
| { |
| bool value = false; |
| EXPECT_TRUE(store_->GetBool(kGroup, kKeyTrue, &value)); |
| EXPECT_TRUE(value); |
| } |
| { |
| bool value; |
| EXPECT_FALSE(store_->GetBool(kGroup, kKeyBad, &value)); |
| EXPECT_FALSE(store_->GetBool(kGroup, "unknown", &value)); |
| EXPECT_FALSE(store_->GetBool("unknown", kKeyTrue, &value)); |
| } |
| EXPECT_TRUE(store_->GetBool(kGroup, kKeyFalse, nullptr)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetBool) { |
| static const char kGroup[] = "bool-group"; |
| static const char kKeyTrue[] = "test-true-bool"; |
| static const char kKeyFalse[] = "test-false-bool"; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetBool(kGroup, kKeyTrue, true)); |
| ASSERT_TRUE(store_->SetBool(kGroup, kKeyFalse, false)); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=true\n" |
| "%s=false\n", |
| kGroup, kKeyTrue, kKeyFalse), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetInt) { |
| static const char kGroup[] = "numbers"; |
| static const char kKeyPos[] = "pos"; |
| static const char kKeyNeg[] = "neg"; |
| static const char kKeyBad[] = "bad"; |
| const int kValuePos = 50; |
| const int kValueNeg = -20; |
| static const char kValueBad[] = "nan"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%d\n" |
| "%s=%d\n" |
| "%s=%s\n", |
| kGroup, |
| kKeyPos, kValuePos, |
| kKeyNeg, kValueNeg, |
| kKeyBad, kValueBad)); |
| ASSERT_TRUE(store_->Open()); |
| { |
| int value = 0; |
| EXPECT_TRUE(store_->GetInt(kGroup, kKeyNeg, &value)); |
| EXPECT_EQ(kValueNeg, value); |
| } |
| { |
| int value = 0; |
| EXPECT_TRUE(store_->GetInt(kGroup, kKeyPos, &value)); |
| EXPECT_EQ(kValuePos, value); |
| } |
| { |
| int value; |
| EXPECT_FALSE(store_->GetInt(kGroup, kKeyBad, &value)); |
| EXPECT_FALSE(store_->GetInt(kGroup, "invalid", &value)); |
| EXPECT_FALSE(store_->GetInt("invalid", kKeyPos, &value)); |
| } |
| EXPECT_TRUE(store_->GetInt(kGroup, kKeyPos, nullptr)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetInt) { |
| static const char kGroup[] = "int-group"; |
| static const char kKey1[] = "test-int"; |
| static const char kKey2[] = "test-negative"; |
| const int kValue1 = 5; |
| const int kValue2 = -10; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetInt(kGroup, kKey1, kValue1)); |
| ASSERT_TRUE(store_->SetInt(kGroup, kKey2, kValue2)); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=%d\n" |
| "%s=%d\n", |
| kGroup, kKey1, kValue1, kKey2, kValue2), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetUint64) { |
| static const char kGroup[] = "numbers"; |
| static const char kKeyGood[] = "good"; |
| static const char kKeyBad[] = "bad"; |
| const uint64_t kValueGood = 0xFEDCBA9876543210LL; |
| static const char kValueBad[] = "nan"; |
| // Use base::Uint64ToString() instead of using something like "%llu" |
| // (not correct for native 64 bit architectures) or PRIu64 (does not |
| // work correctly using cros_workon_make due to include intricacies). |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%s\n" |
| "%s=%s\n", |
| kGroup, |
| kKeyGood, |
| base::Uint64ToString(kValueGood).c_str(), |
| kKeyBad, kValueBad)); |
| ASSERT_TRUE(store_->Open()); |
| { |
| uint64_t value = 0; |
| EXPECT_TRUE(store_->GetUint64(kGroup, kKeyGood, &value)); |
| EXPECT_EQ(kValueGood, value); |
| } |
| { |
| uint64_t value; |
| EXPECT_FALSE(store_->GetUint64(kGroup, kKeyBad, &value)); |
| EXPECT_FALSE(store_->GetUint64(kGroup, "invalid", &value)); |
| EXPECT_FALSE(store_->GetUint64("invalid", kKeyGood, &value)); |
| } |
| EXPECT_TRUE(store_->GetUint64(kGroup, kKeyGood, nullptr)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetUint64) { |
| static const char kGroup[] = "int-group"; |
| static const char kKey[] = "test-int"; |
| const uint64_t kValue = 0xFEDCBA9876543210LL; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetUint64(kGroup, kKey, kValue)); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=%s\n", |
| kGroup, kKey, |
| base::Uint64ToString(kValue).c_str()), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetStringList) { |
| static const char kGroup[] = "string-lists"; |
| static const char kKeyEmpty[] = "empty"; |
| static const char kKeyEmptyValue[] = "empty-value"; |
| static const char kKeyValueEmpty[] = "value-empty"; |
| static const char kKeyValueEmptyValue[] = "value-empty-value"; |
| static const char kKeyValues[] = "values"; |
| static const char kValue[] = "value"; |
| static const char kValue2[] = "value2"; |
| static const char kValue3[] = "value3"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=\n" |
| "%s=;%s\n" |
| "%s=%s;;\n" |
| "%s=%s;;%s\n" |
| "%s=%s;%s;%s\n", |
| kGroup, |
| kKeyEmpty, |
| kKeyEmptyValue, kValue, |
| kKeyValueEmpty, kValue, |
| kKeyValueEmptyValue, kValue, kValue2, |
| kKeyValues, kValue, kValue2, kValue3)); |
| ASSERT_TRUE(store_->Open()); |
| |
| vector<string> value; |
| |
| EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValues, &value)); |
| ASSERT_EQ(3, value.size()); |
| EXPECT_EQ(kValue, value[0]); |
| EXPECT_EQ(kValue2, value[1]); |
| EXPECT_EQ(kValue3, value[2]); |
| |
| EXPECT_TRUE(store_->GetStringList(kGroup, kKeyEmptyValue, &value)); |
| ASSERT_EQ(2, value.size()); |
| EXPECT_EQ("", value[0]); |
| EXPECT_EQ(kValue, value[1]); |
| |
| EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValueEmpty, &value)); |
| ASSERT_EQ(2, value.size()); |
| EXPECT_EQ(kValue, value[0]); |
| EXPECT_EQ("", value[1]); |
| |
| EXPECT_TRUE(store_->GetStringList(kGroup, kKeyEmpty, &value)); |
| ASSERT_EQ(0, value.size()); |
| |
| EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValueEmptyValue, &value)); |
| ASSERT_EQ(3, value.size()); |
| EXPECT_EQ(kValue, value[0]); |
| EXPECT_EQ("", value[1]); |
| EXPECT_EQ(kValue2, value[2]); |
| |
| EXPECT_FALSE(store_->GetStringList("unknown-string-lists", |
| kKeyEmpty, |
| &value)); |
| EXPECT_FALSE(store_->GetStringList(kGroup, "some-key", &value)); |
| EXPECT_TRUE(store_->GetStringList(kGroup, kKeyValues, nullptr)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetStringList) { |
| static const char kGroup[] = "strings"; |
| static const char kKeyEmpty[] = "e"; |
| static const char kKeyEmptyValue[] = "ev"; |
| static const char kKeyValueEmpty[] = "ve"; |
| static const char kKeyValueEmptyValue[] = "vev"; |
| static const char kKeyValues[] = "v"; |
| static const char kValue[] = "abc"; |
| static const char kValue2[] = "pqr"; |
| static const char kValue3[] = "xyz"; |
| ASSERT_TRUE(store_->Open()); |
| { |
| vector<string> value; |
| ASSERT_TRUE(store_->SetStringList(kGroup, kKeyEmpty, value)); |
| } |
| { |
| vector<string> value; |
| value.push_back(""); |
| value.push_back(kValue); |
| ASSERT_TRUE(store_->SetStringList(kGroup, kKeyEmptyValue, value)); |
| } |
| { |
| vector<string> value; |
| value.push_back(kValue); |
| value.push_back(""); |
| ASSERT_TRUE(store_->SetStringList(kGroup, kKeyValueEmpty, value)); |
| } |
| { |
| vector<string> value; |
| value.push_back(kValue); |
| value.push_back(""); |
| value.push_back(kValue2); |
| ASSERT_TRUE(store_->SetStringList(kGroup, kKeyValueEmptyValue, value)); |
| } |
| { |
| vector<string> value; |
| value.push_back(kValue); |
| value.push_back(kValue2); |
| value.push_back(kValue3); |
| ASSERT_TRUE(store_->SetStringList(kGroup, kKeyValues, value)); |
| } |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=\n" |
| "%s=;%s;\n" |
| "%s=%s;;\n" |
| "%s=%s;;%s;\n" |
| "%s=%s;%s;%s;\n", |
| kGroup, |
| kKeyEmpty, |
| kKeyEmptyValue, kValue, |
| kKeyValueEmpty, kValue, |
| kKeyValueEmptyValue, kValue, kValue2, |
| kKeyValues, kValue, kValue2, kValue3), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, GetCryptedString) { |
| static const char kGroup[] = "crypto-group"; |
| static const char kKey[] = "secret"; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%s\n", |
| kGroup, kKey, kROT47Text)); |
| ASSERT_TRUE(store_->Open()); |
| string value; |
| EXPECT_TRUE(store_->GetCryptedString(kGroup, kKey, &value)); |
| EXPECT_EQ(kPlainText, value); |
| EXPECT_FALSE(store_->GetCryptedString("something-else", kKey, &value)); |
| EXPECT_FALSE(store_->GetCryptedString(kGroup, "non-secret", &value)); |
| EXPECT_TRUE(store_->GetCryptedString(kGroup, kKey, nullptr)); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetCryptedString) { |
| static const char kGroup[] = "crypted-string-group"; |
| static const char kKey[] = "test-string"; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetCryptedString(kGroup, kKey, kPlainText)); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=%s\n", |
| kGroup, kKey, kROT47Text), |
| ReadKeyFile()); |
| } |
| |
| TEST_F(KeyFileStoreTest, PersistAcrossClose) { |
| static const char kGroup[] = "string-group"; |
| static const char kKey1[] = "test-string"; |
| static const char kValue1[] = "foo"; |
| static const char kKey2[] = "empty-string"; |
| static const char kValue2[] = ""; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetString(kGroup, kKey1, kValue1)); |
| ASSERT_TRUE(store_->Close()); |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetString(kGroup, kKey2, kValue2)); |
| string value; |
| ASSERT_TRUE(store_->GetString(kGroup, kKey1, &value)); |
| ASSERT_EQ(kValue1, value); |
| ASSERT_TRUE(store_->GetString(kGroup, kKey2, &value)); |
| ASSERT_EQ(kValue2, value); |
| ASSERT_TRUE(store_->Close()); |
| } |
| |
| namespace { |
| class ReadOnlyKeyFileStore : public KeyFileStore { |
| public: |
| explicit ReadOnlyKeyFileStore(const base::FilePath& path) |
| : KeyFileStore(path) {} |
| bool Flush() override { return true; } |
| }; |
| |
| bool OpenCheckClose(const FilePath& path, |
| const string& group, |
| const string& key, |
| const string& expected_value) { |
| ReadOnlyKeyFileStore store(path); // Don't modify file owned by caller. |
| EXPECT_TRUE(store.Open()); |
| string value; |
| bool could_get = store.GetString(group, key, &value); |
| store.Close(); |
| return could_get && expected_value == value; |
| } |
| |
| TEST_F(KeyFileStoreTest, Flush) { |
| static const char kGroup[] = "string-group"; |
| static const char kKey1[] = "test-string"; |
| static const char kValue1[] = "foo"; |
| static const char kKey2[] = "empty-string"; |
| static const char kValue2[] = ""; |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetString(kGroup, kKey1, kValue1)); |
| ASSERT_TRUE(store_->Flush()); |
| ASSERT_TRUE(OpenCheckClose(test_file_, kGroup, kKey1, kValue1)); |
| |
| ASSERT_TRUE(store_->SetString(kGroup, kKey2, kValue2)); |
| ASSERT_TRUE(store_->Flush()); |
| ASSERT_TRUE(OpenCheckClose(test_file_, kGroup, kKey2, kValue2)); |
| |
| EXPECT_TRUE(store_->DeleteKey(kGroup, kKey1)); |
| ASSERT_TRUE(store_->Flush()); |
| ASSERT_FALSE(OpenCheckClose(test_file_, kGroup, kKey1, kValue1)); |
| } |
| } // namespace |
| |
| TEST_F(KeyFileStoreTest, EmptyFile) { |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_FALSE(store_->IsNonEmpty()); |
| } |
| |
| TEST_F(KeyFileStoreTest, SetHeader) { |
| ASSERT_TRUE(store_->Open()); |
| ASSERT_TRUE(store_->SetHeader("this is a test")); |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_TRUE(store_->IsNonEmpty()); |
| ASSERT_TRUE(store_->Open()); |
| } |
| |
| TEST_F(KeyFileStoreTest, Combo) { |
| static const char kGroupA[] = "square"; |
| static const char kGroupB[] = "circle"; |
| static const char kGroupC[] = "triangle"; |
| static const char kGroupX[] = "pentagon"; |
| static const char kKeyString[] = "color"; |
| static const char kKeyStringList[] = "alternative-colors"; |
| static const char kKeyInt[] = "area"; |
| static const char kKeyBool[] = "visible"; |
| static const char kValueStringA[] = "blue"; |
| static const char kValueStringB[] = "red"; |
| static const char kValueStringC[] = "yellow"; |
| static const char kValueStringCNew[] = "purple"; |
| const int kValueIntA = 5; |
| const int kValueIntB = 10; |
| const int kValueIntBNew = 333; |
| WriteKeyFile(base::StringPrintf("[%s]\n" |
| "%s=%s\n" |
| "%s=%s;%s\n" |
| "%s=%d\n" |
| "[%s]\n" |
| "%s=%s\n" |
| "%s=%s;%s\n" |
| "%s=%d\n" |
| "%s=true\n" |
| "[%s]\n" |
| "%s=%s\n" |
| "%s=false\n", |
| kGroupA, |
| kKeyString, kValueStringA, |
| kKeyStringList, kValueStringB, kValueStringC, |
| kKeyInt, kValueIntA, |
| kGroupB, |
| kKeyString, kValueStringB, |
| kKeyStringList, kValueStringA, kValueStringC, |
| kKeyInt, kValueIntB, |
| kKeyBool, |
| kGroupC, |
| kKeyString, kValueStringC, |
| kKeyBool)); |
| ASSERT_TRUE(store_->Open()); |
| |
| EXPECT_TRUE(store_->ContainsGroup(kGroupA)); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupB)); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupC)); |
| EXPECT_FALSE(store_->ContainsGroup(kGroupX)); |
| |
| set<string> groups = store_->GetGroups(); |
| EXPECT_EQ(3, groups.size()); |
| EXPECT_TRUE(ContainsKey(groups, kGroupA)); |
| EXPECT_TRUE(ContainsKey(groups, kGroupB)); |
| EXPECT_TRUE(ContainsKey(groups, kGroupC)); |
| EXPECT_FALSE(ContainsKey(groups, kGroupX)); |
| |
| { |
| string value; |
| EXPECT_TRUE(store_->GetString(kGroupB, kKeyString, &value)); |
| EXPECT_EQ(kValueStringB, value); |
| EXPECT_TRUE(store_->GetString(kGroupA, kKeyString, &value)); |
| EXPECT_EQ(kValueStringA, value); |
| EXPECT_TRUE(store_->GetString(kGroupC, kKeyString, &value)); |
| EXPECT_EQ(kValueStringC, value); |
| } |
| { |
| vector<string> value; |
| EXPECT_TRUE(store_->GetStringList(kGroupB, kKeyStringList, &value)); |
| ASSERT_EQ(2, value.size()); |
| EXPECT_EQ(kValueStringA, value[0]); |
| EXPECT_EQ(kValueStringC, value[1]); |
| EXPECT_TRUE(store_->GetStringList(kGroupA, kKeyStringList, &value)); |
| ASSERT_EQ(2, value.size()); |
| EXPECT_EQ(kValueStringB, value[0]); |
| EXPECT_EQ(kValueStringC, value[1]); |
| EXPECT_FALSE(store_->GetStringList(kGroupC, kKeyStringList, &value)); |
| } |
| { |
| int value = 0; |
| EXPECT_TRUE(store_->GetInt(kGroupB, kKeyInt, &value)); |
| EXPECT_EQ(kValueIntB, value); |
| EXPECT_TRUE(store_->GetInt(kGroupA, kKeyInt, &value)); |
| EXPECT_EQ(kValueIntA, value); |
| EXPECT_FALSE(store_->GetInt(kGroupC, kKeyInt, &value)); |
| } |
| { |
| bool value = false; |
| EXPECT_TRUE(store_->GetBool(kGroupB, kKeyBool, &value)); |
| EXPECT_TRUE(value); |
| EXPECT_TRUE(store_->GetBool(kGroupC, kKeyBool, &value)); |
| EXPECT_FALSE(value); |
| EXPECT_FALSE(store_->GetBool(kGroupA, kKeyBool, &value)); |
| } |
| |
| EXPECT_TRUE(store_->DeleteGroup(kGroupA)); |
| EXPECT_TRUE(store_->DeleteGroup(kGroupA)); |
| |
| EXPECT_FALSE(store_->ContainsGroup(kGroupA)); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupB)); |
| EXPECT_TRUE(store_->ContainsGroup(kGroupC)); |
| |
| groups = store_->GetGroups(); |
| EXPECT_EQ(2, groups.size()); |
| EXPECT_FALSE(ContainsKey(groups, kGroupA)); |
| EXPECT_TRUE(ContainsKey(groups, kGroupB)); |
| EXPECT_TRUE(ContainsKey(groups, kGroupC)); |
| |
| EXPECT_TRUE(store_->SetBool(kGroupB, kKeyBool, false)); |
| EXPECT_TRUE(store_->SetInt(kGroupB, kKeyInt, kValueIntBNew)); |
| EXPECT_TRUE(store_->SetString(kGroupC, kKeyString, kValueStringCNew)); |
| store_->SetStringList(kGroupB, |
| kKeyStringList, |
| vector<string>(1, kValueStringB)); |
| |
| EXPECT_TRUE(store_->DeleteKey(kGroupB, kKeyString)); |
| EXPECT_TRUE(store_->DeleteKey(kGroupB, kKeyString)); |
| |
| { |
| string value; |
| EXPECT_FALSE(store_->GetString(kGroupB, kKeyString, &value)); |
| EXPECT_FALSE(store_->GetString(kGroupA, kKeyString, &value)); |
| EXPECT_TRUE(store_->GetString(kGroupC, kKeyString, &value)); |
| EXPECT_EQ(kValueStringCNew, value); |
| } |
| { |
| vector<string> value; |
| EXPECT_TRUE(store_->GetStringList(kGroupB, kKeyStringList, &value)); |
| ASSERT_EQ(1, value.size()); |
| EXPECT_EQ(kValueStringB, value[0]); |
| EXPECT_FALSE(store_->GetStringList(kGroupA, kKeyStringList, &value)); |
| EXPECT_FALSE(store_->GetStringList(kGroupC, kKeyStringList, &value)); |
| } |
| { |
| int value = 0; |
| EXPECT_TRUE(store_->GetInt(kGroupB, kKeyInt, &value)); |
| EXPECT_EQ(kValueIntBNew, value); |
| EXPECT_FALSE(store_->GetInt(kGroupA, kKeyInt, &value)); |
| EXPECT_FALSE(store_->GetInt(kGroupC, kKeyInt, &value)); |
| } |
| { |
| bool value = false; |
| EXPECT_TRUE(store_->GetBool(kGroupB, kKeyBool, &value)); |
| EXPECT_FALSE(value); |
| EXPECT_TRUE(store_->GetBool(kGroupC, kKeyBool, &value)); |
| EXPECT_FALSE(value); |
| EXPECT_FALSE(store_->GetBool(kGroupA, kKeyBool, &value)); |
| } |
| |
| ASSERT_TRUE(store_->Close()); |
| EXPECT_EQ(base::StringPrintf("[%s]\n" |
| "%s=%s;\n" |
| "%s=%d\n" |
| "%s=false\n" |
| "\n" |
| "[%s]\n" |
| "%s=%s\n" |
| "%s=false\n", |
| kGroupB, |
| kKeyStringList, kValueStringB, |
| kKeyInt, kValueIntBNew, |
| kKeyBool, |
| kGroupC, |
| kKeyString, kValueStringCNew, |
| kKeyBool), |
| ReadKeyFile()); |
| } |
| |
| } // namespace shill |