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 "update_engine/common/prefs.h"
18
19 #include <inttypes.h>
20
21 #include <limits>
22 #include <string>
23
24 #include <base/files/file_util.h>
25 #include <base/macros.h>
26 #include <base/strings/string_util.h>
27 #include <base/strings/stringprintf.h>
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30
31 using std::string;
32 using testing::Eq;
33 using testing::_;
34
35 namespace {
36 // Test key used along the tests.
37 const char kKey[] = "test-key";
38 }
39
40 namespace chromeos_update_engine {
41
42 class PrefsTest : public ::testing::Test {
43 protected:
SetUp()44 void SetUp() override {
45 ASSERT_TRUE(base::CreateNewTempDirectory("auprefs", &prefs_dir_));
46 ASSERT_TRUE(prefs_.Init(prefs_dir_));
47 }
48
TearDown()49 void TearDown() override {
50 base::DeleteFile(prefs_dir_, true); // recursive
51 }
52
SetValue(const string & key,const string & value)53 bool SetValue(const string& key, const string& value) {
54 return base::WriteFile(prefs_dir_.Append(key), value.data(),
55 value.length()) == static_cast<int>(value.length());
56 }
57
58 base::FilePath prefs_dir_;
59 Prefs prefs_;
60 };
61
TEST_F(PrefsTest,GetFileNameForKey)62 TEST_F(PrefsTest, GetFileNameForKey) {
63 const char kAllvalidCharsKey[] =
64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-";
65 base::FilePath path;
66 EXPECT_TRUE(prefs_.file_storage_.GetFileNameForKey(kAllvalidCharsKey, &path));
67 EXPECT_EQ(prefs_dir_.Append(kAllvalidCharsKey).value(), path.value());
68 }
69
TEST_F(PrefsTest,GetFileNameForKeyBadCharacter)70 TEST_F(PrefsTest, GetFileNameForKeyBadCharacter) {
71 base::FilePath path;
72 EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("ABC abc", &path));
73 }
74
TEST_F(PrefsTest,GetFileNameForKeyEmpty)75 TEST_F(PrefsTest, GetFileNameForKeyEmpty) {
76 base::FilePath path;
77 EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("", &path));
78 }
79
TEST_F(PrefsTest,GetString)80 TEST_F(PrefsTest, GetString) {
81 const string test_data = "test data";
82 ASSERT_TRUE(SetValue(kKey, test_data));
83 string value;
84 EXPECT_TRUE(prefs_.GetString(kKey, &value));
85 EXPECT_EQ(test_data, value);
86 }
87
TEST_F(PrefsTest,GetStringBadKey)88 TEST_F(PrefsTest, GetStringBadKey) {
89 string value;
90 EXPECT_FALSE(prefs_.GetString(",bad", &value));
91 }
92
TEST_F(PrefsTest,GetStringNonExistentKey)93 TEST_F(PrefsTest, GetStringNonExistentKey) {
94 string value;
95 EXPECT_FALSE(prefs_.GetString("non-existent-key", &value));
96 }
97
TEST_F(PrefsTest,SetString)98 TEST_F(PrefsTest, SetString) {
99 const char kValue[] = "some test value\non 2 lines";
100 EXPECT_TRUE(prefs_.SetString(kKey, kValue));
101 string value;
102 EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
103 EXPECT_EQ(kValue, value);
104 }
105
TEST_F(PrefsTest,SetStringBadKey)106 TEST_F(PrefsTest, SetStringBadKey) {
107 const char kKeyWithDots[] = ".no-dots";
108 EXPECT_FALSE(prefs_.SetString(kKeyWithDots, "some value"));
109 EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKeyWithDots)));
110 }
111
TEST_F(PrefsTest,SetStringCreateDir)112 TEST_F(PrefsTest, SetStringCreateDir) {
113 const char kValue[] = "test value";
114 base::FilePath subdir = prefs_dir_.Append("subdir1").Append("subdir2");
115 EXPECT_TRUE(prefs_.Init(subdir));
116 EXPECT_TRUE(prefs_.SetString(kKey, kValue));
117 string value;
118 EXPECT_TRUE(base::ReadFileToString(subdir.Append(kKey), &value));
119 EXPECT_EQ(kValue, value);
120 }
121
TEST_F(PrefsTest,SetStringDirCreationFailure)122 TEST_F(PrefsTest, SetStringDirCreationFailure) {
123 EXPECT_TRUE(prefs_.Init(base::FilePath("/dev/null")));
124 EXPECT_FALSE(prefs_.SetString(kKey, "test value"));
125 }
126
TEST_F(PrefsTest,SetStringFileCreationFailure)127 TEST_F(PrefsTest, SetStringFileCreationFailure) {
128 base::CreateDirectory(prefs_dir_.Append(kKey));
129 EXPECT_FALSE(prefs_.SetString(kKey, "test value"));
130 EXPECT_TRUE(base::DirectoryExists(prefs_dir_.Append(kKey)));
131 }
132
TEST_F(PrefsTest,GetInt64)133 TEST_F(PrefsTest, GetInt64) {
134 ASSERT_TRUE(SetValue(kKey, " \n 25 \t "));
135 int64_t value;
136 EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
137 EXPECT_EQ(25, value);
138 }
139
TEST_F(PrefsTest,GetInt64BadValue)140 TEST_F(PrefsTest, GetInt64BadValue) {
141 ASSERT_TRUE(SetValue(kKey, "30a"));
142 int64_t value;
143 EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
144 }
145
TEST_F(PrefsTest,GetInt64Max)146 TEST_F(PrefsTest, GetInt64Max) {
147 ASSERT_TRUE(SetValue(kKey, base::StringPrintf(
148 "%" PRIi64, std::numeric_limits<int64_t>::max())));
149 int64_t value;
150 EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
151 EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
152 }
153
TEST_F(PrefsTest,GetInt64Min)154 TEST_F(PrefsTest, GetInt64Min) {
155 ASSERT_TRUE(SetValue(kKey, base::StringPrintf(
156 "%" PRIi64, std::numeric_limits<int64_t>::min())));
157 int64_t value;
158 EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
159 EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
160 }
161
TEST_F(PrefsTest,GetInt64Negative)162 TEST_F(PrefsTest, GetInt64Negative) {
163 ASSERT_TRUE(SetValue(kKey, " \t -100 \n "));
164 int64_t value;
165 EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
166 EXPECT_EQ(-100, value);
167 }
168
TEST_F(PrefsTest,GetInt64NonExistentKey)169 TEST_F(PrefsTest, GetInt64NonExistentKey) {
170 int64_t value;
171 EXPECT_FALSE(prefs_.GetInt64("random-key", &value));
172 }
173
TEST_F(PrefsTest,SetInt64)174 TEST_F(PrefsTest, SetInt64) {
175 EXPECT_TRUE(prefs_.SetInt64(kKey, -123));
176 string value;
177 EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
178 EXPECT_EQ("-123", value);
179 }
180
TEST_F(PrefsTest,SetInt64BadKey)181 TEST_F(PrefsTest, SetInt64BadKey) {
182 const char kKeyWithSpaces[] = "s p a c e s";
183 EXPECT_FALSE(prefs_.SetInt64(kKeyWithSpaces, 20));
184 EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKeyWithSpaces)));
185 }
186
TEST_F(PrefsTest,SetInt64Max)187 TEST_F(PrefsTest, SetInt64Max) {
188 EXPECT_TRUE(prefs_.SetInt64(kKey, std::numeric_limits<int64_t>::max()));
189 string value;
190 EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
191 EXPECT_EQ(base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::max()),
192 value);
193 }
194
TEST_F(PrefsTest,SetInt64Min)195 TEST_F(PrefsTest, SetInt64Min) {
196 EXPECT_TRUE(prefs_.SetInt64(kKey, std::numeric_limits<int64_t>::min()));
197 string value;
198 EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
199 EXPECT_EQ(base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::min()),
200 value);
201 }
202
TEST_F(PrefsTest,GetBooleanFalse)203 TEST_F(PrefsTest, GetBooleanFalse) {
204 ASSERT_TRUE(SetValue(kKey, " \n false \t "));
205 bool value;
206 EXPECT_TRUE(prefs_.GetBoolean(kKey, &value));
207 EXPECT_FALSE(value);
208 }
209
TEST_F(PrefsTest,GetBooleanTrue)210 TEST_F(PrefsTest, GetBooleanTrue) {
211 const char kKey[] = "test-key";
212 ASSERT_TRUE(SetValue(kKey, " \t true \n "));
213 bool value;
214 EXPECT_TRUE(prefs_.GetBoolean(kKey, &value));
215 EXPECT_TRUE(value);
216 }
217
TEST_F(PrefsTest,GetBooleanBadValue)218 TEST_F(PrefsTest, GetBooleanBadValue) {
219 const char kKey[] = "test-key";
220 ASSERT_TRUE(SetValue(kKey, "1"));
221 bool value;
222 EXPECT_FALSE(prefs_.GetBoolean(kKey, &value));
223 }
224
TEST_F(PrefsTest,GetBooleanBadEmptyValue)225 TEST_F(PrefsTest, GetBooleanBadEmptyValue) {
226 const char kKey[] = "test-key";
227 ASSERT_TRUE(SetValue(kKey, ""));
228 bool value;
229 EXPECT_FALSE(prefs_.GetBoolean(kKey, &value));
230 }
231
TEST_F(PrefsTest,GetBooleanNonExistentKey)232 TEST_F(PrefsTest, GetBooleanNonExistentKey) {
233 bool value;
234 EXPECT_FALSE(prefs_.GetBoolean("random-key", &value));
235 }
236
TEST_F(PrefsTest,SetBooleanTrue)237 TEST_F(PrefsTest, SetBooleanTrue) {
238 const char kKey[] = "test-bool";
239 EXPECT_TRUE(prefs_.SetBoolean(kKey, true));
240 string value;
241 EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
242 EXPECT_EQ("true", value);
243 }
244
TEST_F(PrefsTest,SetBooleanFalse)245 TEST_F(PrefsTest, SetBooleanFalse) {
246 const char kKey[] = "test-bool";
247 EXPECT_TRUE(prefs_.SetBoolean(kKey, false));
248 string value;
249 EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
250 EXPECT_EQ("false", value);
251 }
252
TEST_F(PrefsTest,SetBooleanBadKey)253 TEST_F(PrefsTest, SetBooleanBadKey) {
254 const char kKey[] = "s p a c e s";
255 EXPECT_FALSE(prefs_.SetBoolean(kKey, true));
256 EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKey)));
257 }
258
TEST_F(PrefsTest,ExistsWorks)259 TEST_F(PrefsTest, ExistsWorks) {
260 // test that the key doesn't exist before we set it.
261 EXPECT_FALSE(prefs_.Exists(kKey));
262
263 // test that the key exists after we set it.
264 ASSERT_TRUE(prefs_.SetInt64(kKey, 8));
265 EXPECT_TRUE(prefs_.Exists(kKey));
266 }
267
TEST_F(PrefsTest,DeleteWorks)268 TEST_F(PrefsTest, DeleteWorks) {
269 // test that it's alright to delete a non-existent key.
270 EXPECT_TRUE(prefs_.Delete(kKey));
271
272 // delete the key after we set it.
273 ASSERT_TRUE(prefs_.SetInt64(kKey, 0));
274 EXPECT_TRUE(prefs_.Delete(kKey));
275
276 // make sure it doesn't exist anymore.
277 EXPECT_FALSE(prefs_.Exists(kKey));
278 }
279
280 class MockPrefsObserver : public PrefsInterface::ObserverInterface {
281 public:
282 MOCK_METHOD1(OnPrefSet, void(const string&));
283 MOCK_METHOD1(OnPrefDeleted, void(const string& key));
284 };
285
TEST_F(PrefsTest,ObserversCalled)286 TEST_F(PrefsTest, ObserversCalled) {
287 MockPrefsObserver mock_obserser;
288 prefs_.AddObserver(kKey, &mock_obserser);
289
290 EXPECT_CALL(mock_obserser, OnPrefSet(Eq(kKey)));
291 EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
292 prefs_.SetString(kKey, "value");
293 testing::Mock::VerifyAndClearExpectations(&mock_obserser);
294
295 EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
296 EXPECT_CALL(mock_obserser, OnPrefDeleted(Eq(kKey)));
297 prefs_.Delete(kKey);
298 testing::Mock::VerifyAndClearExpectations(&mock_obserser);
299
300 prefs_.RemoveObserver(kKey, &mock_obserser);
301 }
302
TEST_F(PrefsTest,OnlyCalledOnObservedKeys)303 TEST_F(PrefsTest, OnlyCalledOnObservedKeys) {
304 MockPrefsObserver mock_obserser;
305 const char kUnusedKey[] = "unused-key";
306 prefs_.AddObserver(kUnusedKey, &mock_obserser);
307
308 EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
309 EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
310 prefs_.SetString(kKey, "value");
311 prefs_.Delete(kKey);
312
313 prefs_.RemoveObserver(kUnusedKey, &mock_obserser);
314 }
315
TEST_F(PrefsTest,RemovedObserversNotCalled)316 TEST_F(PrefsTest, RemovedObserversNotCalled) {
317 MockPrefsObserver mock_obserser_a, mock_obserser_b;
318 prefs_.AddObserver(kKey, &mock_obserser_a);
319 prefs_.AddObserver(kKey, &mock_obserser_b);
320 EXPECT_CALL(mock_obserser_a, OnPrefSet(_)).Times(2);
321 EXPECT_CALL(mock_obserser_b, OnPrefSet(_)).Times(1);
322 EXPECT_TRUE(prefs_.SetString(kKey, "value"));
323 prefs_.RemoveObserver(kKey, &mock_obserser_b);
324 EXPECT_TRUE(prefs_.SetString(kKey, "other value"));
325 prefs_.RemoveObserver(kKey, &mock_obserser_a);
326 EXPECT_TRUE(prefs_.SetString(kKey, "yet another value"));
327 }
328
TEST_F(PrefsTest,UnsuccessfulCallsNotObserved)329 TEST_F(PrefsTest, UnsuccessfulCallsNotObserved) {
330 MockPrefsObserver mock_obserser;
331 const char kInvalidKey[] = "no spaces or .";
332 prefs_.AddObserver(kInvalidKey, &mock_obserser);
333
334 EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
335 EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
336 EXPECT_FALSE(prefs_.SetString(kInvalidKey, "value"));
337 EXPECT_FALSE(prefs_.Delete(kInvalidKey));
338
339 prefs_.RemoveObserver(kInvalidKey, &mock_obserser);
340 }
341
342 class MemoryPrefsTest : public ::testing::Test {
343 protected:
344 MemoryPrefs prefs_;
345 };
346
TEST_F(MemoryPrefsTest,BasicTest)347 TEST_F(MemoryPrefsTest, BasicTest) {
348 EXPECT_FALSE(prefs_.Exists(kKey));
349 int64_t value = 0;
350 EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
351
352 EXPECT_TRUE(prefs_.SetInt64(kKey, 1234));
353 EXPECT_TRUE(prefs_.Exists(kKey));
354 EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
355 EXPECT_EQ(1234, value);
356
357 EXPECT_TRUE(prefs_.Delete(kKey));
358 EXPECT_FALSE(prefs_.Exists(kKey));
359 EXPECT_FALSE(prefs_.Delete(kKey));
360 }
361
362 } // namespace chromeos_update_engine
363