blob: 68875ef9c39d383abab5e7105428984fe1930ef7 [file] [log] [blame]
Alex Deymoedf1a2b2014-09-23 12:05:56 -07001// 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
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -07005#include <brillo/key_value_store.h>
Alex Deymoedf1a2b2014-09-23 12:05:56 -07006
7#include <map>
8#include <string>
Aaron Kemp35babde2015-02-25 11:08:20 -05009#include <vector>
Alex Deymoedf1a2b2014-09-23 12:05:56 -070010
11#include <base/files/file_util.h>
12#include <base/files/scoped_temp_dir.h>
Daniel Erat9ee4e712015-01-27 10:29:07 -070013#include <base/logging.h>
Alex Deymoedf1a2b2014-09-23 12:05:56 -070014#include <base/strings/string_util.h>
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -070015#include <brillo/map_utils.h>
Alex Deymoedf1a2b2014-09-23 12:05:56 -070016#include <gtest/gtest.h>
17
18using base::FilePath;
19using base::ReadFileToString;
20using std::map;
21using std::string;
Aaron Kemp35babde2015-02-25 11:08:20 -050022using std::vector;
Alex Deymoedf1a2b2014-09-23 12:05:56 -070023
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -070024namespace brillo {
Alex Deymoedf1a2b2014-09-23 12:05:56 -070025
26class KeyValueStoreTest : public ::testing::Test {
Alex Deymoedf1a2b2014-09-23 12:05:56 -070027 protected:
Daniel Erat9ee4e712015-01-27 10:29:07 -070028 // 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.
30 string GetNonemptyStringValue(const string& key) {
31 string value;
32 if (store_.GetString(key, &value))
33 CHECK(!value.empty());
34 return value;
35 }
36
Alex Deymoedf1a2b2014-09-23 12:05:56 -070037 KeyValueStore store_; // KeyValueStore under test.
38};
39
Alex Deymo665bc532015-06-26 19:34:26 -070040TEST_F(KeyValueStoreTest, LoadAndSaveFromFile) {
41 base::ScopedTempDir temp_dir_;
42 CHECK(temp_dir_.CreateUniqueTempDir());
Eric Carusoc1f7f7c2018-02-06 16:26:54 -080043 base::FilePath temp_file_ = temp_dir_.GetPath().Append("temp.conf");
44 base::FilePath saved_temp_file_ =
45 temp_dir_.GetPath().Append("saved_temp.conf");
Alex Deymo665bc532015-06-26 19:34:26 -070046
47 string blob = "A=B\n# Comment\n";
Alex Deymoedf1a2b2014-09-23 12:05:56 -070048 ASSERT_EQ(blob.size(), base::WriteFile(temp_file_, blob.data(), blob.size()));
Daniel Erat9ee4e712015-01-27 10:29:07 -070049 ASSERT_TRUE(store_.Load(temp_file_));
Alex Deymoedf1a2b2014-09-23 12:05:56 -070050
Alex Deymo665bc532015-06-26 19:34:26 -070051 string value;
52 EXPECT_TRUE(store_.GetString("A", &value));
53 EXPECT_EQ("B", value);
54
55 ASSERT_TRUE(store_.Save(saved_temp_file_));
Alex Deymoedf1a2b2014-09-23 12:05:56 -070056 string read_blob;
Alex Deymo665bc532015-06-26 19:34:26 -070057 ASSERT_TRUE(ReadFileToString(FilePath(saved_temp_file_), &read_blob));
Alex Deymoedf1a2b2014-09-23 12:05:56 -070058 EXPECT_EQ("A=B\n", read_blob);
59}
60
Alex Deymo665bc532015-06-26 19:34:26 -070061TEST_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}
Alex Deymoedf1a2b2014-09-23 12:05:56 -070066
Alex Deymo665bc532015-06-26 19:34:26 -070067TEST_F(KeyValueStoreTest, EmptyTest) {
68 EXPECT_TRUE(store_.LoadFromString(""));
69 EXPECT_EQ("", store_.SaveToString());
Alex Deymoedf1a2b2014-09-23 12:05:56 -070070}
71
72TEST_F(KeyValueStoreTest, LoadAndReloadTest) {
Alex Deymo665bc532015-06-26 19:34:26 -070073 EXPECT_TRUE(store_.LoadFromString(
74 "A=B\nC=\nFOO=BAR=BAZ\nBAR=BAX\nMISSING=NEWLINE"));
Alex Deymoedf1a2b2014-09-23 12:05:56 -070075
Alex Vakulenko05d29042015-01-13 09:39:25 -080076 map<string, string> expected = {{"A", "B"},
77 {"C", ""},
Alex Vakulenko05d29042015-01-13 09:39:25 -080078 {"FOO", "BAR=BAZ"},
79 {"BAR", "BAX"},
80 {"MISSING", "NEWLINE"}};
Alex Deymoedf1a2b2014-09-23 12:05:56 -070081
Daniel Erat9ee4e712015-01-27 10:29:07 -070082 // Test expected values.
Alex Deymoedf1a2b2014-09-23 12:05:56 -070083 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.
Alex Deymoedf1a2b2014-09-23 12:05:56 -070090 KeyValueStore new_store;
Alex Deymo665bc532015-06-26 19:34:26 -070091 ASSERT_TRUE(new_store.LoadFromString(store_.SaveToString()));
Alex Deymoedf1a2b2014-09-23 12:05:56 -070092
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
99TEST_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
112TEST_F(KeyValueStoreTest, BooleanParsingTest) {
113 string blob = "TRUE=true\nfalse=false\nvar=false\nDONT_SHOUT=TRUE\n";
Alex Deymo665bc532015-06-26 19:34:26 -0700114 EXPECT_TRUE(store_.LoadFromString(blob));
Alex Deymoedf1a2b2014-09-23 12:05:56 -0700115
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
Daniel Erat9ee4e712015-01-27 10:29:07 -0700123 // Test expected values.
Alex Deymoedf1a2b2014-09-23 12:05:56 -0700124 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
Daniel Erat9ee4e712015-01-27 10:29:07 -0700130TEST_F(KeyValueStoreTest, TrimWhitespaceAroundKey) {
Alex Deymo665bc532015-06-26 19:34:26 -0700131 EXPECT_TRUE(store_.LoadFromString(" a=1\nb =2\n c =3\n"));
Daniel Erat9ee4e712015-01-27 10:29:07 -0700132
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
147TEST_F(KeyValueStoreTest, IgnoreWhitespaceLine) {
Alex Deymo665bc532015-06-26 19:34:26 -0700148 EXPECT_TRUE(store_.LoadFromString("a=1\n \t \nb=2"));
Daniel Erat9ee4e712015-01-27 10:29:07 -0700149
150 EXPECT_EQ("1", GetNonemptyStringValue("a"));
151 EXPECT_EQ("2", GetNonemptyStringValue("b"));
152}
153
154TEST_F(KeyValueStoreTest, RejectEmptyKeys) {
Alex Deymo665bc532015-06-26 19:34:26 -0700155 EXPECT_FALSE(store_.LoadFromString("=1"));
156 EXPECT_FALSE(store_.LoadFromString(" =2"));
Daniel Erat9ee4e712015-01-27 10:29:07 -0700157
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
163TEST_F(KeyValueStoreTest, RejectBogusLines) {
Alex Deymo665bc532015-06-26 19:34:26 -0700164 EXPECT_FALSE(store_.LoadFromString("a=1\nbogus\nb=2"));
Daniel Erat9ee4e712015-01-27 10:29:07 -0700165}
166
167TEST_F(KeyValueStoreTest, MultilineValue) {
Alex Deymo665bc532015-06-26 19:34:26 -0700168 EXPECT_TRUE(store_.LoadFromString("a=foo\nb=bar\\\n baz \\ \nc=3\n"));
Daniel Erat9ee4e712015-01-27 10:29:07 -0700169
170 EXPECT_EQ("foo", GetNonemptyStringValue("a"));
171 EXPECT_EQ("bar baz \\ ", GetNonemptyStringValue("b"));
172 EXPECT_EQ("3", GetNonemptyStringValue("c"));
173}
174
175TEST_F(KeyValueStoreTest, UnterminatedMultilineValue) {
Alex Deymo665bc532015-06-26 19:34:26 -0700176 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"));
Daniel Erat9ee4e712015-01-27 10:29:07 -0700179}
180
Aaron Kemp35babde2015-02-25 11:08:20 -0500181TEST_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
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -0700193} // namespace brillo