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 
123   PrefsInterface* common_prefs_;
124 };
125 
126 class PrefsTest : public BasePrefsTest {
127  protected:
SetUp()128   void SetUp() override {
129     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
130     prefs_dir_ = temp_dir_.GetPath();
131     ASSERT_TRUE(prefs_.Init(prefs_dir_));
132     common_prefs_ = &prefs_;
133   }
134 
SetValue(const string & key,const string & value)135   bool SetValue(const string& key, const string& value) {
136     return base::WriteFile(prefs_dir_.Append(key),
137                            value.data(),
138                            value.length()) == static_cast<int>(value.length());
139   }
140 
141   base::ScopedTempDir temp_dir_;
142   base::FilePath prefs_dir_;
143   Prefs prefs_;
144 };
145 
TEST(Prefs,Init)146 TEST(Prefs, Init) {
147   Prefs prefs;
148   const string ns1 = "ns1";
149   const string ns2A = "ns2A";
150   const string ns2B = "ns2B";
151   const string sub_pref = "sp";
152 
153   base::ScopedTempDir temp_dir;
154   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
155   auto ns1_path = temp_dir.GetPath().Append(ns1);
156   auto ns2A_path = ns1_path.Append(ns2A);
157   auto ns2B_path = ns1_path.Append(ns2B);
158   auto sub_pref_path = ns2A_path.Append(sub_pref);
159 
160   EXPECT_TRUE(base::CreateDirectory(ns2B_path));
161   EXPECT_TRUE(base::PathExists(ns2B_path));
162 
163   EXPECT_TRUE(base::CreateDirectory(sub_pref_path));
164   EXPECT_TRUE(base::PathExists(sub_pref_path));
165 
166   EXPECT_TRUE(base::PathExists(ns1_path));
167   ASSERT_TRUE(prefs.Init(temp_dir.GetPath()));
168   EXPECT_FALSE(base::PathExists(ns1_path));
169 }
170 
TEST_F(PrefsTest,GetFileNameForKey)171 TEST_F(PrefsTest, GetFileNameForKey) {
172   const char kAllvalidCharsKey[] =
173       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-";
174   base::FilePath path;
175   EXPECT_TRUE(prefs_.file_storage_.GetFileNameForKey(kAllvalidCharsKey, &path));
176   EXPECT_EQ(prefs_dir_.Append(kAllvalidCharsKey).value(), path.value());
177 }
178 
TEST_F(PrefsTest,GetFileNameForKeyBadCharacter)179 TEST_F(PrefsTest, GetFileNameForKeyBadCharacter) {
180   base::FilePath path;
181   EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("ABC abc", &path));
182 }
183 
TEST_F(PrefsTest,GetFileNameForKeyEmpty)184 TEST_F(PrefsTest, GetFileNameForKeyEmpty) {
185   base::FilePath path;
186   EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("", &path));
187 }
188 
TEST_F(PrefsTest,CreateSubKey)189 TEST_F(PrefsTest, CreateSubKey) {
190   const string name_space = "ns";
191   const string sub_pref1 = "sp1";
192   const string sub_pref2 = "sp2";
193   const string sub_key = "sk";
194 
195   EXPECT_EQ(PrefsInterface::CreateSubKey({name_space, sub_pref1, sub_key}),
196             "ns/sp1/sk");
197   EXPECT_EQ(PrefsInterface::CreateSubKey({name_space, sub_pref2, sub_key}),
198             "ns/sp2/sk");
199 }
200 
TEST_F(PrefsTest,GetString)201 TEST_F(PrefsTest, GetString) {
202   const string test_data = "test data";
203   ASSERT_TRUE(SetValue(kKey, test_data));
204   string value;
205   EXPECT_TRUE(prefs_.GetString(kKey, &value));
206   EXPECT_EQ(test_data, value);
207 }
208 
TEST_F(PrefsTest,GetStringBadKey)209 TEST_F(PrefsTest, GetStringBadKey) {
210   string value;
211   EXPECT_FALSE(prefs_.GetString(",bad", &value));
212 }
213 
TEST_F(PrefsTest,GetStringNonExistentKey)214 TEST_F(PrefsTest, GetStringNonExistentKey) {
215   string value;
216   EXPECT_FALSE(prefs_.GetString("non-existent-key", &value));
217 }
218 
TEST_F(PrefsTest,SetString)219 TEST_F(PrefsTest, SetString) {
220   const char kValue[] = "some test value\non 2 lines";
221   EXPECT_TRUE(prefs_.SetString(kKey, kValue));
222   string value;
223   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
224   EXPECT_EQ(kValue, value);
225 }
226 
TEST_F(PrefsTest,SetStringBadKey)227 TEST_F(PrefsTest, SetStringBadKey) {
228   const char kKeyWithDots[] = ".no-dots";
229   EXPECT_FALSE(prefs_.SetString(kKeyWithDots, "some value"));
230   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKeyWithDots)));
231 }
232 
TEST_F(PrefsTest,SetStringCreateDir)233 TEST_F(PrefsTest, SetStringCreateDir) {
234   const char kValue[] = "test value";
235   base::FilePath subdir = prefs_dir_.Append("subdir1").Append("subdir2");
236   EXPECT_TRUE(prefs_.Init(subdir));
237   EXPECT_TRUE(prefs_.SetString(kKey, kValue));
238   string value;
239   EXPECT_TRUE(base::ReadFileToString(subdir.Append(kKey), &value));
240   EXPECT_EQ(kValue, value);
241 }
242 
TEST_F(PrefsTest,SetStringDirCreationFailure)243 TEST_F(PrefsTest, SetStringDirCreationFailure) {
244   EXPECT_TRUE(prefs_.Init(base::FilePath("/dev/null")));
245   EXPECT_FALSE(prefs_.SetString(kKey, "test value"));
246 }
247 
TEST_F(PrefsTest,SetStringFileCreationFailure)248 TEST_F(PrefsTest, SetStringFileCreationFailure) {
249   base::CreateDirectory(prefs_dir_.Append(kKey));
250   EXPECT_FALSE(prefs_.SetString(kKey, "test value"));
251   EXPECT_TRUE(base::DirectoryExists(prefs_dir_.Append(kKey)));
252 }
253 
TEST_F(PrefsTest,GetInt64)254 TEST_F(PrefsTest, GetInt64) {
255   ASSERT_TRUE(SetValue(kKey, " \n 25 \t "));
256   int64_t value;
257   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
258   EXPECT_EQ(25, value);
259 }
260 
TEST_F(PrefsTest,GetInt64BadValue)261 TEST_F(PrefsTest, GetInt64BadValue) {
262   ASSERT_TRUE(SetValue(kKey, "30a"));
263   int64_t value;
264   EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
265 }
266 
TEST_F(PrefsTest,GetInt64Max)267 TEST_F(PrefsTest, GetInt64Max) {
268   ASSERT_TRUE(SetValue(
269       kKey,
270       base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::max())));
271   int64_t value;
272   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
273   EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
274 }
275 
TEST_F(PrefsTest,GetInt64Min)276 TEST_F(PrefsTest, GetInt64Min) {
277   ASSERT_TRUE(SetValue(
278       kKey,
279       base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::min())));
280   int64_t value;
281   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
282   EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
283 }
284 
TEST_F(PrefsTest,GetInt64Negative)285 TEST_F(PrefsTest, GetInt64Negative) {
286   ASSERT_TRUE(SetValue(kKey, " \t -100 \n "));
287   int64_t value;
288   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
289   EXPECT_EQ(-100, value);
290 }
291 
TEST_F(PrefsTest,GetInt64NonExistentKey)292 TEST_F(PrefsTest, GetInt64NonExistentKey) {
293   int64_t value;
294   EXPECT_FALSE(prefs_.GetInt64("random-key", &value));
295 }
296 
TEST_F(PrefsTest,SetInt64)297 TEST_F(PrefsTest, SetInt64) {
298   EXPECT_TRUE(prefs_.SetInt64(kKey, -123));
299   string value;
300   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
301   EXPECT_EQ("-123", value);
302 }
303 
TEST_F(PrefsTest,SetInt64BadKey)304 TEST_F(PrefsTest, SetInt64BadKey) {
305   const char kKeyWithSpaces[] = "s p a c e s";
306   EXPECT_FALSE(prefs_.SetInt64(kKeyWithSpaces, 20));
307   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKeyWithSpaces)));
308 }
309 
TEST_F(PrefsTest,SetInt64Max)310 TEST_F(PrefsTest, SetInt64Max) {
311   EXPECT_TRUE(prefs_.SetInt64(kKey, std::numeric_limits<int64_t>::max()));
312   string value;
313   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
314   EXPECT_EQ(base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::max()),
315             value);
316 }
317 
TEST_F(PrefsTest,SetInt64Min)318 TEST_F(PrefsTest, SetInt64Min) {
319   EXPECT_TRUE(prefs_.SetInt64(kKey, std::numeric_limits<int64_t>::min()));
320   string value;
321   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
322   EXPECT_EQ(base::StringPrintf("%" PRIi64, std::numeric_limits<int64_t>::min()),
323             value);
324 }
325 
TEST_F(PrefsTest,GetBooleanFalse)326 TEST_F(PrefsTest, GetBooleanFalse) {
327   ASSERT_TRUE(SetValue(kKey, " \n false \t "));
328   bool value;
329   EXPECT_TRUE(prefs_.GetBoolean(kKey, &value));
330   EXPECT_FALSE(value);
331 }
332 
TEST_F(PrefsTest,GetBooleanTrue)333 TEST_F(PrefsTest, GetBooleanTrue) {
334   const char kKey[] = "test-key";
335   ASSERT_TRUE(SetValue(kKey, " \t true \n "));
336   bool value;
337   EXPECT_TRUE(prefs_.GetBoolean(kKey, &value));
338   EXPECT_TRUE(value);
339 }
340 
TEST_F(PrefsTest,GetBooleanBadValue)341 TEST_F(PrefsTest, GetBooleanBadValue) {
342   const char kKey[] = "test-key";
343   ASSERT_TRUE(SetValue(kKey, "1"));
344   bool value;
345   EXPECT_FALSE(prefs_.GetBoolean(kKey, &value));
346 }
347 
TEST_F(PrefsTest,GetBooleanBadEmptyValue)348 TEST_F(PrefsTest, GetBooleanBadEmptyValue) {
349   const char kKey[] = "test-key";
350   ASSERT_TRUE(SetValue(kKey, ""));
351   bool value;
352   EXPECT_FALSE(prefs_.GetBoolean(kKey, &value));
353 }
354 
TEST_F(PrefsTest,GetBooleanNonExistentKey)355 TEST_F(PrefsTest, GetBooleanNonExistentKey) {
356   bool value;
357   EXPECT_FALSE(prefs_.GetBoolean("random-key", &value));
358 }
359 
TEST_F(PrefsTest,SetBooleanTrue)360 TEST_F(PrefsTest, SetBooleanTrue) {
361   const char kKey[] = "test-bool";
362   EXPECT_TRUE(prefs_.SetBoolean(kKey, true));
363   string value;
364   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
365   EXPECT_EQ("true", value);
366 }
367 
TEST_F(PrefsTest,SetBooleanFalse)368 TEST_F(PrefsTest, SetBooleanFalse) {
369   const char kKey[] = "test-bool";
370   EXPECT_TRUE(prefs_.SetBoolean(kKey, false));
371   string value;
372   EXPECT_TRUE(base::ReadFileToString(prefs_dir_.Append(kKey), &value));
373   EXPECT_EQ("false", value);
374 }
375 
TEST_F(PrefsTest,SetBooleanBadKey)376 TEST_F(PrefsTest, SetBooleanBadKey) {
377   const char kKey[] = "s p a c e s";
378   EXPECT_FALSE(prefs_.SetBoolean(kKey, true));
379   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(kKey)));
380 }
381 
TEST_F(PrefsTest,ExistsWorks)382 TEST_F(PrefsTest, ExistsWorks) {
383   // test that the key doesn't exist before we set it.
384   EXPECT_FALSE(prefs_.Exists(kKey));
385 
386   // test that the key exists after we set it.
387   ASSERT_TRUE(prefs_.SetInt64(kKey, 8));
388   EXPECT_TRUE(prefs_.Exists(kKey));
389 }
390 
TEST_F(PrefsTest,DeleteWorks)391 TEST_F(PrefsTest, DeleteWorks) {
392   // test that it's alright to delete a non-existent key.
393   EXPECT_TRUE(prefs_.Delete(kKey));
394 
395   // delete the key after we set it.
396   ASSERT_TRUE(prefs_.SetInt64(kKey, 0));
397   EXPECT_TRUE(prefs_.Delete(kKey));
398 
399   // make sure it doesn't exist anymore.
400   EXPECT_FALSE(prefs_.Exists(kKey));
401 }
402 
TEST_F(PrefsTest,SetDeleteSubKey)403 TEST_F(PrefsTest, SetDeleteSubKey) {
404   const string name_space = "ns";
405   const string sub_pref = "sp";
406   const string sub_key1 = "sk1";
407   const string sub_key2 = "sk2";
408   auto key1 = prefs_.CreateSubKey({name_space, sub_pref, sub_key1});
409   auto key2 = prefs_.CreateSubKey({name_space, sub_pref, sub_key2});
410   base::FilePath sub_pref_path = prefs_dir_.Append(name_space).Append(sub_pref);
411 
412   ASSERT_TRUE(prefs_.SetInt64(key1, 0));
413   ASSERT_TRUE(prefs_.SetInt64(key2, 0));
414   EXPECT_TRUE(base::PathExists(sub_pref_path.Append(sub_key1)));
415   EXPECT_TRUE(base::PathExists(sub_pref_path.Append(sub_key2)));
416 
417   ASSERT_TRUE(prefs_.Delete(key1));
418   EXPECT_FALSE(base::PathExists(sub_pref_path.Append(sub_key1)));
419   EXPECT_TRUE(base::PathExists(sub_pref_path.Append(sub_key2)));
420   ASSERT_TRUE(prefs_.Delete(key2));
421   EXPECT_FALSE(base::PathExists(sub_pref_path.Append(sub_key2)));
422   prefs_.Init(prefs_dir_);
423   EXPECT_FALSE(base::PathExists(prefs_dir_.Append(name_space)));
424 }
425 
426 class MockPrefsObserver : public PrefsInterface::ObserverInterface {
427  public:
428   MOCK_METHOD1(OnPrefSet, void(const string&));
429   MOCK_METHOD1(OnPrefDeleted, void(const string& key));
430 };
431 
TEST_F(PrefsTest,ObserversCalled)432 TEST_F(PrefsTest, ObserversCalled) {
433   MockPrefsObserver mock_obserser;
434   prefs_.AddObserver(kKey, &mock_obserser);
435 
436   EXPECT_CALL(mock_obserser, OnPrefSet(Eq(kKey)));
437   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
438   prefs_.SetString(kKey, "value");
439   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
440 
441   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
442   EXPECT_CALL(mock_obserser, OnPrefDeleted(Eq(kKey)));
443   prefs_.Delete(kKey);
444   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
445 
446   auto key1 = prefs_.CreateSubKey({"ns", "sp1", "key1"});
447   prefs_.AddObserver(key1, &mock_obserser);
448 
449   EXPECT_CALL(mock_obserser, OnPrefSet(key1));
450   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
451   prefs_.SetString(key1, "value");
452   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
453 
454   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
455   EXPECT_CALL(mock_obserser, OnPrefDeleted(Eq(key1)));
456   prefs_.Delete(key1);
457   testing::Mock::VerifyAndClearExpectations(&mock_obserser);
458 
459   prefs_.RemoveObserver(kKey, &mock_obserser);
460 }
461 
TEST_F(PrefsTest,OnlyCalledOnObservedKeys)462 TEST_F(PrefsTest, OnlyCalledOnObservedKeys) {
463   MockPrefsObserver mock_obserser;
464   const char kUnusedKey[] = "unused-key";
465   prefs_.AddObserver(kUnusedKey, &mock_obserser);
466 
467   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
468   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
469   prefs_.SetString(kKey, "value");
470   prefs_.Delete(kKey);
471 
472   prefs_.RemoveObserver(kUnusedKey, &mock_obserser);
473 }
474 
TEST_F(PrefsTest,RemovedObserversNotCalled)475 TEST_F(PrefsTest, RemovedObserversNotCalled) {
476   MockPrefsObserver mock_obserser_a, mock_obserser_b;
477   prefs_.AddObserver(kKey, &mock_obserser_a);
478   prefs_.AddObserver(kKey, &mock_obserser_b);
479   EXPECT_CALL(mock_obserser_a, OnPrefSet(_)).Times(2);
480   EXPECT_CALL(mock_obserser_b, OnPrefSet(_)).Times(1);
481   EXPECT_TRUE(prefs_.SetString(kKey, "value"));
482   prefs_.RemoveObserver(kKey, &mock_obserser_b);
483   EXPECT_TRUE(prefs_.SetString(kKey, "other value"));
484   prefs_.RemoveObserver(kKey, &mock_obserser_a);
485   EXPECT_TRUE(prefs_.SetString(kKey, "yet another value"));
486 }
487 
TEST_F(PrefsTest,UnsuccessfulCallsNotObserved)488 TEST_F(PrefsTest, UnsuccessfulCallsNotObserved) {
489   MockPrefsObserver mock_obserser;
490   const char kInvalidKey[] = "no spaces or .";
491   prefs_.AddObserver(kInvalidKey, &mock_obserser);
492 
493   EXPECT_CALL(mock_obserser, OnPrefSet(_)).Times(0);
494   EXPECT_CALL(mock_obserser, OnPrefDeleted(_)).Times(0);
495   EXPECT_FALSE(prefs_.SetString(kInvalidKey, "value"));
496   EXPECT_FALSE(prefs_.Delete(kInvalidKey));
497 
498   prefs_.RemoveObserver(kInvalidKey, &mock_obserser);
499 }
500 
TEST_F(PrefsTest,MultiNamespaceKeyTest)501 TEST_F(PrefsTest, MultiNamespaceKeyTest) {
502   MultiNamespaceKeyTest();
503 }
504 
505 class MemoryPrefsTest : public BasePrefsTest {
506  protected:
SetUp()507   void SetUp() override { common_prefs_ = &prefs_; }
508 
509   MemoryPrefs prefs_;
510 };
511 
TEST_F(MemoryPrefsTest,BasicTest)512 TEST_F(MemoryPrefsTest, BasicTest) {
513   EXPECT_FALSE(prefs_.Exists(kKey));
514   int64_t value = 0;
515   EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
516 
517   EXPECT_TRUE(prefs_.SetInt64(kKey, 1234));
518   EXPECT_TRUE(prefs_.Exists(kKey));
519   EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
520   EXPECT_EQ(1234, value);
521 
522   EXPECT_TRUE(prefs_.Delete(kKey));
523   EXPECT_FALSE(prefs_.Exists(kKey));
524   EXPECT_TRUE(prefs_.Delete(kKey));
525 
526   auto key = prefs_.CreateSubKey({"ns", "sp", "sk"});
527   ASSERT_TRUE(prefs_.SetInt64(key, 0));
528   EXPECT_TRUE(prefs_.Exists(key));
529   EXPECT_TRUE(prefs_.Delete(kKey));
530 }
531 
TEST_F(MemoryPrefsTest,MultiNamespaceKeyTest)532 TEST_F(MemoryPrefsTest, MultiNamespaceKeyTest) {
533   MultiNamespaceKeyTest();
534 }
535 
536 }  // namespace chromeos_update_engine
537