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