• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <vector>
24 
25 #include <base/files/file_util.h>
26 #include <base/files/scoped_temp_dir.h>
27 #include <base/macros.h>
28 #include <base/strings/string_util.h>
29 #include <base/strings/stringprintf.h>
30 #include <gmock/gmock.h>
31 #include <gtest/gtest.h>
32 
33 using std::string;
34 using std::vector;
35 using testing::_;
36 using testing::ElementsAre;
37 using testing::Eq;
38 using testing::UnorderedElementsAre;
39 
40 namespace {
41 // Test key used along the tests.
42 const char kKey[] = "test-key";
43 }  // namespace
44 
45 namespace chromeos_update_engine {
46 
47 class BasePrefsTest : public ::testing::Test {
48  protected:
MultiNamespaceKeyTest()49   void MultiNamespaceKeyTest() {
50     ASSERT_TRUE(common_prefs_);
51     auto key0 = common_prefs_->CreateSubKey({"ns1", "key"});
52     // Corner case for "ns1".
53     auto key0corner = common_prefs_->CreateSubKey({"ns11", "key"});
54     auto key1A = common_prefs_->CreateSubKey({"ns1", "nsA", "keyA"});
55     auto key1B = common_prefs_->CreateSubKey({"ns1", "nsA", "keyB"});
56     auto key2 = common_prefs_->CreateSubKey({"ns1", "nsB", "key"});
57     // Corner case for "ns1/nsB".
58     auto key2corner = common_prefs_->CreateSubKey({"ns1", "nsB1", "key"});
59     EXPECT_FALSE(common_prefs_->Exists(key0));
60     EXPECT_FALSE(common_prefs_->Exists(key1A));
61     EXPECT_FALSE(common_prefs_->Exists(key1B));
62     EXPECT_FALSE(common_prefs_->Exists(key2));
63 
64     EXPECT_TRUE(common_prefs_->SetString(key0, ""));
65     EXPECT_TRUE(common_prefs_->SetString(key0corner, ""));
66     EXPECT_TRUE(common_prefs_->SetString(key1A, ""));
67     EXPECT_TRUE(common_prefs_->SetString(key1B, ""));
68     EXPECT_TRUE(common_prefs_->SetString(key2, ""));
69     EXPECT_TRUE(common_prefs_->SetString(key2corner, ""));
70 
71     EXPECT_TRUE(common_prefs_->Exists(key0));
72     EXPECT_TRUE(common_prefs_->Exists(key0corner));
73     EXPECT_TRUE(common_prefs_->Exists(key1A));
74     EXPECT_TRUE(common_prefs_->Exists(key1B));
75     EXPECT_TRUE(common_prefs_->Exists(key2));
76     EXPECT_TRUE(common_prefs_->Exists(key2corner));
77 
78     vector<string> keys2;
79     EXPECT_TRUE(common_prefs_->GetSubKeys("ns1/nsB/", &keys2));
80     EXPECT_THAT(keys2, ElementsAre(key2));
81     for (const auto& key : keys2)
82       EXPECT_TRUE(common_prefs_->Delete(key));
83     EXPECT_TRUE(common_prefs_->Exists(key0));
84     EXPECT_TRUE(common_prefs_->Exists(key0corner));
85     EXPECT_TRUE(common_prefs_->Exists(key1A));
86     EXPECT_TRUE(common_prefs_->Exists(key1B));
87     EXPECT_FALSE(common_prefs_->Exists(key2));
88     EXPECT_TRUE(common_prefs_->Exists(key2corner));
89 
90     vector<string> keys2corner;
91     EXPECT_TRUE(common_prefs_->GetSubKeys("ns1/nsB", &keys2corner));
92     EXPECT_THAT(keys2corner, ElementsAre(key2corner));
93     for (const auto& key : keys2corner)
94       EXPECT_TRUE(common_prefs_->Delete(key));
95     EXPECT_FALSE(common_prefs_->Exists(key2corner));
96 
97     vector<string> keys1;
98     EXPECT_TRUE(common_prefs_->GetSubKeys("ns1/nsA/", &keys1));
99     EXPECT_THAT(keys1, UnorderedElementsAre(key1A, key1B));
100     for (const auto& key : keys1)
101       EXPECT_TRUE(common_prefs_->Delete(key));
102     EXPECT_TRUE(common_prefs_->Exists(key0));
103     EXPECT_TRUE(common_prefs_->Exists(key0corner));
104     EXPECT_FALSE(common_prefs_->Exists(key1A));
105     EXPECT_FALSE(common_prefs_->Exists(key1B));
106 
107     vector<string> keys0;
108     EXPECT_TRUE(common_prefs_->GetSubKeys("ns1/", &keys0));
109     EXPECT_THAT(keys0, ElementsAre(key0));
110     for (const auto& key : keys0)
111       EXPECT_TRUE(common_prefs_->Delete(key));
112     EXPECT_FALSE(common_prefs_->Exists(key0));
113     EXPECT_TRUE(common_prefs_->Exists(key0corner));
114 
115     vector<string> keys0corner;
116     EXPECT_TRUE(common_prefs_->GetSubKeys("ns1", &keys0corner));
117     EXPECT_THAT(keys0corner, ElementsAre(key0corner));
118     for (const auto& key : keys0corner)
119       EXPECT_TRUE(common_prefs_->Delete(key));
120     EXPECT_FALSE(common_prefs_->Exists(key0corner));
121 
122     // Test sub directory namespace.
123     const string kDlcPrefsSubDir = "foo-dir";
124     key1A = common_prefs_->CreateSubKey({kDlcPrefsSubDir, "dlc1", "keyA"});
125     EXPECT_TRUE(common_prefs_->SetString(key1A, "fp_1A"));
126     key1B = common_prefs_->CreateSubKey({kDlcPrefsSubDir, "dlc1", "keyB"});
127     EXPECT_TRUE(common_prefs_->SetString(key1B, "fp_1B"));
128     auto key2A = common_prefs_->CreateSubKey({kDlcPrefsSubDir, "dlc2", "keyA"});
129     EXPECT_TRUE(common_prefs_->SetString(key2A, "fp_A2"));
130 
131     vector<string> fpKeys;
132     EXPECT_TRUE(common_prefs_->GetSubKeys(kDlcPrefsSubDir, &fpKeys));
133     EXPECT_EQ(fpKeys.size(), 3UL);
134     EXPECT_TRUE(common_prefs_->Delete(fpKeys[0]));
135     EXPECT_TRUE(common_prefs_->Delete(fpKeys[1]));
136     EXPECT_TRUE(common_prefs_->Delete(fpKeys[2]));
137     EXPECT_FALSE(common_prefs_->Exists(key1A));
138   }
139 
140   PrefsInterface* common_prefs_;
141 };
142 
143 class PrefsTest : public BasePrefsTest {
144  protected:
SetUp()145   void SetUp() override {
146     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
147     prefs_dir_ = temp_dir_.GetPath();
148     ASSERT_TRUE(prefs_.Init(prefs_dir_));
149     common_prefs_ = &prefs_;
150   }
151 
SetValue(const string & key,const string & value)152   bool SetValue(const string& key, const string& value) {
153     return base::WriteFile(prefs_dir_.Append(key),
154                            value.data(),
155                            value.length()) == static_cast<int>(value.length());
156   }
157 
158   base::ScopedTempDir temp_dir_;
159   base::FilePath prefs_dir_;
160   Prefs prefs_;
161 };
162 
TEST(Prefs,Init)163 TEST(Prefs, Init) {
164   Prefs prefs;
165   const string ns1 = "ns1";
166   const string ns2A = "ns2A";
167   const string ns2B = "ns2B";
168   const string sub_pref = "sp";
169 
170   base::ScopedTempDir temp_dir;
171   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
172   auto ns1_path = temp_dir.GetPath().Append(ns1);
173   auto ns2A_path = ns1_path.Append(ns2A);
174   auto ns2B_path = ns1_path.Append(ns2B);
175   auto sub_pref_path = ns2A_path.Append(sub_pref);
176 
177   EXPECT_TRUE(base::CreateDirectory(ns2B_path));
178   EXPECT_TRUE(base::PathExists(ns2B_path));
179 
180   EXPECT_TRUE(base::CreateDirectory(sub_pref_path));
181   EXPECT_TRUE(base::PathExists(sub_pref_path));
182 
183   EXPECT_TRUE(base::PathExists(ns1_path));
184   ASSERT_TRUE(prefs.Init(temp_dir.GetPath()));
185   EXPECT_FALSE(base::PathExists(ns1_path));
186 }
187 
TEST_F(PrefsTest,GetFileNameForKey)188 TEST_F(PrefsTest, GetFileNameForKey) {
189   const char kAllvalidCharsKey[] =
190       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-";
191   base::FilePath path;
192   EXPECT_TRUE(prefs_.file_storage_.GetFileNameForKey(kAllvalidCharsKey, &path));
193   EXPECT_EQ(prefs_dir_.Append(kAllvalidCharsKey).value(), path.value());
194 }
195 
TEST_F(PrefsTest,GetFileNameForKeyBadCharacter)196 TEST_F(PrefsTest, GetFileNameForKeyBadCharacter) {
197   base::FilePath path;
198   EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("ABC abc", &path));
199 }
200 
TEST_F(PrefsTest,GetFileNameForKeyEmpty)201 TEST_F(PrefsTest, GetFileNameForKeyEmpty) {
202   base::FilePath path;
203   EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("", &path));
204 }
205 
TEST_F(PrefsTest,CreateSubKey)206 TEST_F(PrefsTest, CreateSubKey) {
207   const string name_space = "ns";
208   const string sub_pref1 = "sp1";
209   const string sub_pref2 = "sp2";
210   const string sub_key = "sk";
211 
212   EXPECT_EQ(PrefsInterface::CreateSubKey({name_space, sub_pref1, sub_key}),
213             "ns/sp1/sk");
214   EXPECT_EQ(PrefsInterface::CreateSubKey({name_space, sub_pref2, sub_key}),
215             "ns/sp2/sk");
216 }
217 
TEST_F(PrefsTest,GetString)218 TEST_F(PrefsTest, GetString) {
219   const string test_data = "test data";
220   ASSERT_TRUE(SetValue(kKey, test_data));
221   string value;
222   EXPECT_TRUE(prefs_.GetString(kKey, &value));
223   EXPECT_EQ(test_data, value);
224 }
225 
TEST_F(PrefsTest,GetStringBadKey)226 TEST_F(PrefsTest, GetStringBadKey) {
227   string value;
228   EXPECT_FALSE(prefs_.GetString(",bad", &value));
229 }
230 
TEST_F(PrefsTest,GetStringNonExistentKey)231 TEST_F(PrefsTest, GetStringNonExistentKey) {
232   string value;
233   EXPECT_FALSE(prefs_.GetString("non-existent-key", &value));
234 }
235 
TEST_F(PrefsTest,SetString)236 TEST_F(PrefsTest, SetString) {
237   const char kValue[] = "some test value\non 2 lines";
238   EXPECT_TRUE(prefs_.SetString(kKey, kValue));
239   string value;
240   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
241   EXPECT_EQ(kValue, value);
242 }
243 
TEST_F(PrefsTest,SetStringBadKey)244 TEST_F(PrefsTest, SetStringBadKey) {
245   const char kKeyWithDots[] = ".no-dots";
246   EXPECT_FALSE(prefs_.SetString(kKeyWithDots, "some value"));
247   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKeyWithDots)));
248 }
249 
TEST_F(PrefsTest,SetStringCreateDir)250 TEST_F(PrefsTest, SetStringCreateDir) {
251   const char kValue[] = "test value";
252   base::FilePath subdir = prefs_dir_.Append("subdir1").Append("subdir2");
253   EXPECT_TRUE(prefs_.Init(subdir));
254   EXPECT_TRUE(prefs_.SetString(kKey, kValue));
255   string value;
256   EXPECT_TRUE(base::ReadFileToString(subdir.Append(kKey), &value));
257   EXPECT_EQ(kValue, value);
258 }
259 
TEST_F(PrefsTest,SetStringDirCreationFailure)260 TEST_F(PrefsTest, SetStringDirCreationFailure) {
261   EXPECT_TRUE(prefs_.Init(base::FilePath("/dev/null")));
262   EXPECT_FALSE(prefs_.SetString(kKey, "test value"));
263 }
264 
TEST_F(PrefsTest,SetStringFileCreationFailure)265 TEST_F(PrefsTest, SetStringFileCreationFailure) {
266   base::CreateDirectory(prefs_dir_.Append(kKey));
267   EXPECT_FALSE(prefs_.SetString(kKey, "test value"));
268   EXPECT_TRUE(base::DirectoryExists(prefs_dir_.Append(kKey)));
269 }
270 
TEST_F(PrefsTest,GetInt64)271 TEST_F(PrefsTest, GetInt64) {
272   ASSERT_TRUE(SetValue(kKey, " \n 25 \t "));
273   int64_t value;
274   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
275   EXPECT_EQ(25, value);
276 }
277 
TEST_F(PrefsTest,GetInt64BadValue)278 TEST_F(PrefsTest, GetInt64BadValue) {
279   ASSERT_TRUE(SetValue(kKey, "30a"));
280   int64_t value;
281   EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
282 }
283 
TEST_F(PrefsTest,GetInt64Max)284 TEST_F(PrefsTest, GetInt64Max) {
285   ASSERT_TRUE(SetValue(
286       kKey,
287       base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::max())));
288   int64_t value;
289   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
290   EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
291 }
292 
TEST_F(PrefsTest,GetInt64Min)293 TEST_F(PrefsTest, GetInt64Min) {
294   ASSERT_TRUE(SetValue(
295       kKey,
296       base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::min())));
297   int64_t value;
298   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
299   EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
300 }
301 
TEST_F(PrefsTest,GetInt64Negative)302 TEST_F(PrefsTest, GetInt64Negative) {
303   ASSERT_TRUE(SetValue(kKey, " \t -100 \n "));
304   int64_t value;
305   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
306   EXPECT_EQ(-100, value);
307 }
308 
TEST_F(PrefsTest,GetInt64NonExistentKey)309 TEST_F(PrefsTest, GetInt64NonExistentKey) {
310   int64_t value;
311   EXPECT_FALSE(prefs_.GetInt64("random-key", &value));
312 }
313 
TEST_F(PrefsTest,SetInt64)314 TEST_F(PrefsTest, SetInt64) {
315   EXPECT_TRUE(prefs_.SetInt64(kKey, -123));
316   string value;
317   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
318   EXPECT_EQ("-123", value);
319 }
320 
TEST_F(PrefsTest,SetInt64BadKey)321 TEST_F(PrefsTest, SetInt64BadKey) {
322   const char kKeyWithSpaces[] = "s p a c e s";
323   EXPECT_FALSE(prefs_.SetInt64(kKeyWithSpaces, 20));
324   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKeyWithSpaces)));
325 }
326 
TEST_F(PrefsTest,SetInt64Max)327 TEST_F(PrefsTest, SetInt64Max) {
328   EXPECT_TRUE(prefs_.SetInt64(kKey, std::numeric_limits<int64_t>::max()));
329   string value;
330   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
331   EXPECT_EQ(base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::max()),
332             value);
333 }
334 
TEST_F(PrefsTest,SetInt64Min)335 TEST_F(PrefsTest, SetInt64Min) {
336   EXPECT_TRUE(prefs_.SetInt64(kKey, std::numeric_limits<int64_t>::min()));
337   string value;
338   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
339   EXPECT_EQ(base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::min()),
340             value);
341 }
342 
TEST_F(PrefsTest,GetBooleanFalse)343 TEST_F(PrefsTest, GetBooleanFalse) {
344   ASSERT_TRUE(SetValue(kKey, " \n false \t "));
345   bool value;
346   EXPECT_TRUE(prefs_.GetBoolean(kKey, &value));
347   EXPECT_FALSE(value);
348 }
349 
TEST_F(PrefsTest,GetBooleanTrue)350 TEST_F(PrefsTest, GetBooleanTrue) {
351   const char kKey[] = "test-key";
352   ASSERT_TRUE(SetValue(kKey, " \t true \n "));
353   bool value;
354   EXPECT_TRUE(prefs_.GetBoolean(kKey, &value));
355   EXPECT_TRUE(value);
356 }
357 
TEST_F(PrefsTest,GetBooleanBadValue)358 TEST_F(PrefsTest, GetBooleanBadValue) {
359   const char kKey[] = "test-key";
360   ASSERT_TRUE(SetValue(kKey, "1"));
361   bool value;
362   EXPECT_FALSE(prefs_.GetBoolean(kKey, &value));
363 }
364 
TEST_F(PrefsTest,GetBooleanBadEmptyValue)365 TEST_F(PrefsTest, GetBooleanBadEmptyValue) {
366   const char kKey[] = "test-key";
367   ASSERT_TRUE(SetValue(kKey, ""));
368   bool value;
369   EXPECT_FALSE(prefs_.GetBoolean(kKey, &value));
370 }
371 
TEST_F(PrefsTest,GetBooleanNonExistentKey)372 TEST_F(PrefsTest, GetBooleanNonExistentKey) {
373   bool value;
374   EXPECT_FALSE(prefs_.GetBoolean("random-key", &value));
375 }
376 
TEST_F(PrefsTest,SetBooleanTrue)377 TEST_F(PrefsTest, SetBooleanTrue) {
378   const char kKey[] = "test-bool";
379   EXPECT_TRUE(prefs_.SetBoolean(kKey, true));
380   string value;
381   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
382   EXPECT_EQ("true", value);
383 }
384 
TEST_F(PrefsTest,SetBooleanFalse)385 TEST_F(PrefsTest, SetBooleanFalse) {
386   const char kKey[] = "test-bool";
387   EXPECT_TRUE(prefs_.SetBoolean(kKey, false));
388   string value;
389   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
390   EXPECT_EQ("false", value);
391 }
392 
TEST_F(PrefsTest,SetBooleanBadKey)393 TEST_F(PrefsTest, SetBooleanBadKey) {
394   const char kKey[] = "s p a c e s";
395   EXPECT_FALSE(prefs_.SetBoolean(kKey, true));
396   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKey)));
397 }
398 
TEST_F(PrefsTest,ExistsWorks)399 TEST_F(PrefsTest, ExistsWorks) {
400   // test that the key doesn't exist before we set it.
401   EXPECT_FALSE(prefs_.Exists(kKey));
402 
403   // test that the key exists after we set it.
404   ASSERT_TRUE(prefs_.SetInt64(kKey, 8));
405   EXPECT_TRUE(prefs_.Exists(kKey));
406 }
407 
TEST_F(PrefsTest,DeleteWorks)408 TEST_F(PrefsTest, DeleteWorks) {
409   // test that it's alright to delete a non-existent key.
410   EXPECT_TRUE(prefs_.Delete(kKey));
411 
412   // delete the key after we set it.
413   ASSERT_TRUE(prefs_.SetInt64(kKey, 0));
414   EXPECT_TRUE(prefs_.Delete(kKey));
415 
416   // make sure it doesn't exist anymore.
417   EXPECT_FALSE(prefs_.Exists(kKey));
418 }
419 
TEST_F(PrefsTest,SetDeleteSubKey)420 TEST_F(PrefsTest, SetDeleteSubKey) {
421   const string name_space = "ns";
422   const string sub_pref = "sp";
423   const string sub_key1 = "sk1";
424   const string sub_key2 = "sk2";
425   auto key1 = prefs_.CreateSubKey({name_space, sub_pref, sub_key1});
426   auto key2 = prefs_.CreateSubKey({name_space, sub_pref, sub_key2});
427   base::FilePath sub_pref_path = prefs_dir_.Append(name_space).Append(sub_pref);
428 
429   ASSERT_TRUE(prefs_.SetInt64(key1, 0));
430   ASSERT_TRUE(prefs_.SetInt64(key2, 0));
431   EXPECT_TRUE(base::PathExists(sub_pref_path.Append(sub_key1)));
432   EXPECT_TRUE(base::PathExists(sub_pref_path.Append(sub_key2)));
433 
434   ASSERT_TRUE(prefs_.Delete(key1));
435   EXPECT_FALSE(base::PathExists(sub_pref_path.Append(sub_key1)));
436   EXPECT_TRUE(base::PathExists(sub_pref_path.Append(sub_key2)));
437   ASSERT_TRUE(prefs_.Delete(key2));
438   EXPECT_FALSE(base::PathExists(sub_pref_path.Append(sub_key2)));
439   prefs_.Init(prefs_dir_);
440   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(name_space)));
441 }
442 
TEST_F(PrefsTest,DeletePrefs)443 TEST_F(PrefsTest, DeletePrefs) {
444   const string kPrefsSubDir = "foo-dir";
445   const string kFpKey = "kPrefFp";
446   const string kNotFpKey = "NotkPrefFp";
447   const string kOtherKey = "kPrefNotFp";
448 
449   EXPECT_TRUE(prefs_.SetString(kFpKey, "3.000"));
450   EXPECT_TRUE(prefs_.SetString(kOtherKey, "not_fp_val"));
451 
452   auto key1_fp = prefs_.CreateSubKey({kPrefsSubDir, "id-1", kFpKey});
453   EXPECT_TRUE(prefs_.SetString(key1_fp, "3.7"));
454   auto key_not_fp = prefs_.CreateSubKey({kPrefsSubDir, "id-1", kOtherKey});
455   EXPECT_TRUE(prefs_.SetString(key_not_fp, "not_fp_val"));
456   auto key2_fp = prefs_.CreateSubKey({kPrefsSubDir, "id-2", kFpKey});
457   EXPECT_TRUE(prefs_.SetString(key2_fp, "3.9"));
458   auto key3_fp = prefs_.CreateSubKey({kPrefsSubDir, "id-3", kFpKey});
459   EXPECT_TRUE(prefs_.SetString(key3_fp, "3.45"));
460 
461   // Pref key does not match full subkey at end, should not delete.
462   auto key_middle_fp = prefs_.CreateSubKey({kPrefsSubDir, kFpKey, kOtherKey});
463   EXPECT_TRUE(prefs_.SetString(key_middle_fp, "not_fp_val"));
464   auto key_end_not_fp = prefs_.CreateSubKey({kPrefsSubDir, "id-1", kNotFpKey});
465   EXPECT_TRUE(prefs_.SetString(key_end_not_fp, "not_fp_val"));
466 
467   // Delete key in platform and one namespace.
468   prefs_.Delete(kFpKey, {kPrefsSubDir});
469 
470   EXPECT_FALSE(prefs_.Exists(kFpKey));
471   EXPECT_FALSE(prefs_.Exists(key1_fp));
472   EXPECT_FALSE(prefs_.Exists(key2_fp));
473   EXPECT_FALSE(prefs_.Exists(key3_fp));
474 
475   // Check other keys are not deleted.
476   EXPECT_TRUE(prefs_.Exists(kOtherKey));
477   EXPECT_TRUE(prefs_.Exists(key_not_fp));
478   EXPECT_TRUE(prefs_.Exists(key_middle_fp));
479   EXPECT_TRUE(prefs_.Exists(key_end_not_fp));
480 }
481 
TEST_F(PrefsTest,DeleteMultipleNamespaces)482 TEST_F(PrefsTest, DeleteMultipleNamespaces) {
483   const string kFirstSubDir = "foo-dir";
484   const string kSecondarySubDir = "bar-dir";
485   const string kTertiarySubDir = "ter-dir";
486   const string kFpKey = "kPrefFp";
487 
488   EXPECT_TRUE(prefs_.SetString(kFpKey, "3.000"));
489   // Set pref key in different namespaces.
490   auto key1_fp = prefs_.CreateSubKey({kFirstSubDir, "id-1", kFpKey});
491   EXPECT_TRUE(prefs_.SetString(key1_fp, "3.7"));
492   auto key2_fp = prefs_.CreateSubKey({kSecondarySubDir, "id-3", kFpKey});
493   EXPECT_TRUE(prefs_.SetString(key2_fp, "7.45"));
494   auto key3_fp = prefs_.CreateSubKey({kTertiarySubDir, "id-3", kFpKey});
495   EXPECT_TRUE(prefs_.SetString(key3_fp, "7.45"));
496 
497   // Delete key in platform and given namespaces.
498   prefs_.Delete(kFpKey, {kFirstSubDir, kSecondarySubDir});
499 
500   EXPECT_FALSE(prefs_.Exists(kFpKey));
501   EXPECT_FALSE(prefs_.Exists(key1_fp));
502   EXPECT_FALSE(prefs_.Exists(key2_fp));
503 
504   // Tertiary namespace not given to delete. Key should still exist.
505   EXPECT_TRUE(prefs_.Exists(key3_fp));
506 }
507 
508 class MockPrefsObserver : public PrefsInterface::ObserverInterface {
509  public:
510   MOCK_METHOD1(OnPrefSet, void(const string&));
511   MOCK_METHOD1(OnPrefDeleted, void(const string& key));
512 };
513 
TEST_F(PrefsTest,ObserversCalled)514 TEST_F(PrefsTest, ObserversCalled) {
515   MockPrefsObserver mock_obserser;
516   prefs_.AddObserver(kKey, &mock_obserser);
517 
518   EXPECT_CALL(mock_obserser, OnPrefSet(Eq(kKey)));
519   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
520   prefs_.SetString(kKey, "value");
521   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
522 
523   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
524   EXPECT_CALL(mock_obserser, OnPrefDeleted(Eq(kKey)));
525   prefs_.Delete(kKey);
526   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
527 
528   auto key1 = prefs_.CreateSubKey({"ns", "sp1", "key1"});
529   prefs_.AddObserver(key1, &mock_obserser);
530 
531   EXPECT_CALL(mock_obserser, OnPrefSet(key1));
532   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
533   prefs_.SetString(key1, "value");
534   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
535 
536   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
537   EXPECT_CALL(mock_obserser, OnPrefDeleted(Eq(key1)));
538   prefs_.Delete(key1);
539   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
540 
541   prefs_.RemoveObserver(kKey, &mock_obserser);
542 }
543 
TEST_F(PrefsTest,OnlyCalledOnObservedKeys)544 TEST_F(PrefsTest, OnlyCalledOnObservedKeys) {
545   MockPrefsObserver mock_obserser;
546   const char kUnusedKey[] = "unused-key";
547   prefs_.AddObserver(kUnusedKey, &mock_obserser);
548 
549   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
550   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
551   prefs_.SetString(kKey, "value");
552   prefs_.Delete(kKey);
553 
554   prefs_.RemoveObserver(kUnusedKey, &mock_obserser);
555 }
556 
TEST_F(PrefsTest,RemovedObserversNotCalled)557 TEST_F(PrefsTest, RemovedObserversNotCalled) {
558   MockPrefsObserver mock_obserser_a, mock_obserser_b;
559   prefs_.AddObserver(kKey, &mock_obserser_a);
560   prefs_.AddObserver(kKey, &mock_obserser_b);
561   EXPECT_CALL(mock_obserser_a, OnPrefSet(_)).Times(2);
562   EXPECT_CALL(mock_obserser_b, OnPrefSet(_)).Times(1);
563   EXPECT_TRUE(prefs_.SetString(kKey, "value"));
564   prefs_.RemoveObserver(kKey, &mock_obserser_b);
565   EXPECT_TRUE(prefs_.SetString(kKey, "other value"));
566   prefs_.RemoveObserver(kKey, &mock_obserser_a);
567   EXPECT_TRUE(prefs_.SetString(kKey, "yet another value"));
568 }
569 
TEST_F(PrefsTest,UnsuccessfulCallsNotObserved)570 TEST_F(PrefsTest, UnsuccessfulCallsNotObserved) {
571   MockPrefsObserver mock_obserser;
572   const char kInvalidKey[] = "no spaces or .";
573   prefs_.AddObserver(kInvalidKey, &mock_obserser);
574 
575   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
576   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
577   EXPECT_FALSE(prefs_.SetString(kInvalidKey, "value"));
578   EXPECT_FALSE(prefs_.Delete(kInvalidKey));
579 
580   prefs_.RemoveObserver(kInvalidKey, &mock_obserser);
581 }
582 
TEST_F(PrefsTest,MultiNamespaceKeyTest)583 TEST_F(PrefsTest, MultiNamespaceKeyTest) {
584   MultiNamespaceKeyTest();
585 }
586 
587 class MemoryPrefsTest : public BasePrefsTest {
588  protected:
SetUp()589   void SetUp() override { common_prefs_ = &prefs_; }
590 
591   MemoryPrefs prefs_;
592 };
593 
TEST_F(MemoryPrefsTest,BasicTest)594 TEST_F(MemoryPrefsTest, BasicTest) {
595   EXPECT_FALSE(prefs_.Exists(kKey));
596   int64_t value = 0;
597   EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
598 
599   EXPECT_TRUE(prefs_.SetInt64(kKey, 1234));
600   EXPECT_TRUE(prefs_.Exists(kKey));
601   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
602   EXPECT_EQ(1234, value);
603 
604   EXPECT_TRUE(prefs_.Delete(kKey));
605   EXPECT_FALSE(prefs_.Exists(kKey));
606   EXPECT_TRUE(prefs_.Delete(kKey));
607 
608   auto key = prefs_.CreateSubKey({"ns", "sp", "sk"});
609   ASSERT_TRUE(prefs_.SetInt64(key, 0));
610   EXPECT_TRUE(prefs_.Exists(key));
611   EXPECT_TRUE(prefs_.Delete(kKey));
612 }
613 
TEST_F(MemoryPrefsTest,MultiNamespaceKeyTest)614 TEST_F(MemoryPrefsTest, MultiNamespaceKeyTest) {
615   MultiNamespaceKeyTest();
616 }
617 
618 }  // namespace chromeos_update_engine
619