• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <brillo/key_value_store.h>
6 
7 #include <map>
8 #include <string>
9 #include <vector>
10 
11 #include <base/files/file_util.h>
12 #include <base/files/scoped_temp_dir.h>
13 #include <base/logging.h>
14 #include <base/strings/string_util.h>
15 #include <brillo/map_utils.h>
16 #include <gtest/gtest.h>
17 
18 using base::FilePath;
19 using base::ReadFileToString;
20 using std::map;
21 using std::string;
22 using std::vector;
23 
24 namespace brillo {
25 
26 class KeyValueStoreTest : public ::testing::Test {
27  protected:
28   // Returns the value from |store_| corresponding to |key|, or an empty string
29   // if the key is not present. Crashes if the store returns an empty value.
GetNonemptyStringValue(const string & key)30   string GetNonemptyStringValue(const string& key) {
31     string value;
32     if (store_.GetString(key, &value))
33       CHECK(!value.empty());
34     return value;
35   }
36 
37   KeyValueStore store_;  // KeyValueStore under test.
38 };
39 
TEST_F(KeyValueStoreTest,LoadAndSaveFromFile)40 TEST_F(KeyValueStoreTest, LoadAndSaveFromFile) {
41   base::ScopedTempDir temp_dir_;
42   CHECK(temp_dir_.CreateUniqueTempDir());
43   base::FilePath temp_file_ = temp_dir_.GetPath().Append("temp.conf");
44   base::FilePath saved_temp_file_ =
45       temp_dir_.GetPath().Append("saved_temp.conf");
46 
47   string blob = "A=B\n# Comment\n";
48   ASSERT_EQ(blob.size(), base::WriteFile(temp_file_, blob.data(), blob.size()));
49   ASSERT_TRUE(store_.Load(temp_file_));
50 
51   string value;
52   EXPECT_TRUE(store_.GetString("A", &value));
53   EXPECT_EQ("B", value);
54 
55   ASSERT_TRUE(store_.Save(saved_temp_file_));
56   string read_blob;
57   ASSERT_TRUE(ReadFileToString(FilePath(saved_temp_file_), &read_blob));
58   EXPECT_EQ("A=B\n", read_blob);
59 }
60 
TEST_F(KeyValueStoreTest,CommentsAreIgnored)61 TEST_F(KeyValueStoreTest, CommentsAreIgnored) {
62   EXPECT_TRUE(store_.LoadFromString(
63       "# comment\nA=B\n\n\n#another=comment\n  # leading spaces\n"));
64   EXPECT_EQ("A=B\n", store_.SaveToString());
65 }
66 
TEST_F(KeyValueStoreTest,EmptyTest)67 TEST_F(KeyValueStoreTest, EmptyTest) {
68   EXPECT_TRUE(store_.LoadFromString(""));
69   EXPECT_EQ("", store_.SaveToString());
70 }
71 
TEST_F(KeyValueStoreTest,LoadAndReloadTest)72 TEST_F(KeyValueStoreTest, LoadAndReloadTest) {
73   EXPECT_TRUE(store_.LoadFromString(
74       "A=B\nC=\nFOO=BAR=BAZ\nBAR=BAX\nMISSING=NEWLINE"));
75 
76   map<string, string> expected = {{"A", "B"},
77                                   {"C", ""},
78                                   {"FOO", "BAR=BAZ"},
79                                   {"BAR", "BAX"},
80                                   {"MISSING", "NEWLINE"}};
81 
82   // Test expected values.
83   string value;
84   for (const auto& it : expected) {
85     EXPECT_TRUE(store_.GetString(it.first, &value));
86     EXPECT_EQ(it.second, value) << "Testing key: " << it.first;
87   }
88 
89   // Save, load and test again.
90   KeyValueStore new_store;
91   ASSERT_TRUE(new_store.LoadFromString(store_.SaveToString()));
92 
93   for (const auto& it : expected) {
94     EXPECT_TRUE(new_store.GetString(it.first, &value)) << "key: " << it.first;
95     EXPECT_EQ(it.second, value) << "key: " << it.first;
96   }
97 }
98 
TEST_F(KeyValueStoreTest,SimpleBooleanTest)99 TEST_F(KeyValueStoreTest, SimpleBooleanTest) {
100   bool result;
101   EXPECT_FALSE(store_.GetBoolean("A", &result));
102 
103   store_.SetBoolean("A", true);
104   EXPECT_TRUE(store_.GetBoolean("A", &result));
105   EXPECT_TRUE(result);
106 
107   store_.SetBoolean("A", false);
108   EXPECT_TRUE(store_.GetBoolean("A", &result));
109   EXPECT_FALSE(result);
110 }
111 
TEST_F(KeyValueStoreTest,BooleanParsingTest)112 TEST_F(KeyValueStoreTest, BooleanParsingTest) {
113   string blob = "TRUE=true\nfalse=false\nvar=false\nDONT_SHOUT=TRUE\n";
114   EXPECT_TRUE(store_.LoadFromString(blob));
115 
116   map<string, bool> expected = {
117       {"TRUE", true}, {"false", false}, {"var", false}};
118   bool value;
119   EXPECT_FALSE(store_.GetBoolean("DONT_SHOUT", &value));
120   string str_value;
121   EXPECT_TRUE(store_.GetString("DONT_SHOUT", &str_value));
122 
123   // Test expected values.
124   for (const auto& it : expected) {
125     EXPECT_TRUE(store_.GetBoolean(it.first, &value)) << "key: " << it.first;
126     EXPECT_EQ(it.second, value) << "key: " << it.first;
127   }
128 }
129 
TEST_F(KeyValueStoreTest,TrimWhitespaceAroundKey)130 TEST_F(KeyValueStoreTest, TrimWhitespaceAroundKey) {
131   EXPECT_TRUE(store_.LoadFromString("  a=1\nb  =2\n c =3\n"));
132 
133   EXPECT_EQ("1", GetNonemptyStringValue("a"));
134   EXPECT_EQ("2", GetNonemptyStringValue("b"));
135   EXPECT_EQ("3", GetNonemptyStringValue("c"));
136 
137   // Keys should also be trimmed when setting new values.
138   store_.SetString(" foo ", "4");
139   EXPECT_EQ("4", GetNonemptyStringValue("foo"));
140 
141   store_.SetBoolean(" bar ", true);
142   bool value = false;
143   ASSERT_TRUE(store_.GetBoolean("bar", &value));
144   EXPECT_TRUE(value);
145 }
146 
TEST_F(KeyValueStoreTest,IgnoreWhitespaceLine)147 TEST_F(KeyValueStoreTest, IgnoreWhitespaceLine) {
148   EXPECT_TRUE(store_.LoadFromString("a=1\n \t \nb=2"));
149 
150   EXPECT_EQ("1", GetNonemptyStringValue("a"));
151   EXPECT_EQ("2", GetNonemptyStringValue("b"));
152 }
153 
TEST_F(KeyValueStoreTest,RejectEmptyKeys)154 TEST_F(KeyValueStoreTest, RejectEmptyKeys) {
155   EXPECT_FALSE(store_.LoadFromString("=1"));
156   EXPECT_FALSE(store_.LoadFromString(" =2"));
157 
158   // Trying to set an empty (after trimming) key should fail an assert.
159   EXPECT_DEATH(store_.SetString(" ", "3"), "");
160   EXPECT_DEATH(store_.SetBoolean(" ", "4"), "");
161 }
162 
TEST_F(KeyValueStoreTest,RejectBogusLines)163 TEST_F(KeyValueStoreTest, RejectBogusLines) {
164   EXPECT_FALSE(store_.LoadFromString("a=1\nbogus\nb=2"));
165 }
166 
TEST_F(KeyValueStoreTest,MultilineValue)167 TEST_F(KeyValueStoreTest, MultilineValue) {
168   EXPECT_TRUE(store_.LoadFromString("a=foo\nb=bar\\\n  baz \\ \nc=3\n"));
169 
170   EXPECT_EQ("foo", GetNonemptyStringValue("a"));
171   EXPECT_EQ("bar  baz \\ ", GetNonemptyStringValue("b"));
172   EXPECT_EQ("3", GetNonemptyStringValue("c"));
173 }
174 
TEST_F(KeyValueStoreTest,UnterminatedMultilineValue)175 TEST_F(KeyValueStoreTest, UnterminatedMultilineValue) {
176   EXPECT_FALSE(store_.LoadFromString("a=foo\\"));
177   EXPECT_FALSE(store_.LoadFromString("a=foo\\\n"));
178   EXPECT_FALSE(store_.LoadFromString("a=foo\\\n\n# blah\n"));
179 }
180 
TEST_F(KeyValueStoreTest,GetKeys)181 TEST_F(KeyValueStoreTest, GetKeys) {
182   map<string, string> entries = {
183     {"1", "apple"}, {"2", "banana"}, {"3", "cherry"}
184   };
185   for (const auto& it : entries) {
186     store_.SetString(it.first, it.second);
187   }
188 
189   vector<string> keys = GetMapKeysAsVector(entries);
190   EXPECT_EQ(keys, store_.GetKeys());
191 }
192 
193 }  // namespace brillo
194