1 /* 2 * Copyright (C) 2014 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 #define LOG_TAG "Properties_test" 18 19 #include <limits.h> 20 21 #include <iostream> 22 #include <sstream> 23 #include <string> 24 25 #include <android/log.h> 26 #include <android-base/macros.h> 27 #include <cutils/properties.h> 28 #include <gtest/gtest.h> 29 30 namespace android { 31 32 #define STRINGIFY_INNER(x) #x 33 #define STRINGIFY(x) STRINGIFY_INNER(x) 34 #define ASSERT_OK(x) ASSERT_EQ(0, (x)) 35 #define EXPECT_OK(x) EXPECT_EQ(0, (x)) 36 37 #define PROPERTY_TEST_KEY "libcutils.test.key" 38 #define PROPERTY_TEST_VALUE_DEFAULT "<<<default_value>>>" 39 40 template <typename T> 41 static std::string HexString(T value) { 42 std::stringstream ss; 43 ss << "0x" << std::hex << std::uppercase << value; 44 return ss.str(); 45 } 46 47 template <typename T> 48 static ::testing::AssertionResult AssertEqualHex(const char *mExpr, 49 const char *nExpr, 50 T m, 51 T n) { 52 if (m == n) { 53 return ::testing::AssertionSuccess(); 54 } 55 56 return ::testing::AssertionFailure() 57 << mExpr << " and " << nExpr << " (expected: " << HexString(m) << 58 ", actual: " << HexString(n) << ") are not equal"; 59 } 60 61 class PropertiesTest : public testing::Test { 62 public: 63 PropertiesTest() : mValue() {} 64 protected: 65 virtual void SetUp() { 66 EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL)); 67 } 68 69 virtual void TearDown() { 70 EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL)); 71 } 72 73 char mValue[PROPERTY_VALUE_MAX]; 74 75 template <typename T> 76 static std::string ToString(T value) { 77 std::stringstream ss; 78 ss << value; 79 80 return ss.str(); 81 } 82 83 // Return length of property read; value is written into mValue 84 int SetAndGetProperty(const char* value, const char* defaultValue = PROPERTY_TEST_VALUE_DEFAULT) { 85 EXPECT_OK(property_set(PROPERTY_TEST_KEY, value)) << "value: '" << value << "'"; 86 return property_get(PROPERTY_TEST_KEY, mValue, defaultValue); 87 } 88 89 void ResetValue(unsigned char c = 0xFF) { 90 for (size_t i = 0; i < arraysize(mValue); ++i) { 91 mValue[i] = (char) c; 92 } 93 } 94 }; 95 96 TEST_F(PropertiesTest, SetString) { 97 98 // Null key -> unsuccessful set 99 { 100 // Null key -> fails 101 EXPECT_GT(0, property_set(/*key*/NULL, PROPERTY_TEST_VALUE_DEFAULT)); 102 } 103 104 // Null value -> returns default value 105 { 106 // Null value -> OK , and it clears the value 107 EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL)); 108 ResetValue(); 109 110 // Since the value is null, default value will be returned 111 size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT); 112 EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len); 113 EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue); 114 } 115 116 // Trivial case => get returns what was set 117 { 118 size_t len = SetAndGetProperty("hello_world"); 119 EXPECT_EQ(strlen("hello_world"), len) << "hello_world key"; 120 EXPECT_STREQ("hello_world", mValue); 121 ResetValue(); 122 } 123 124 // Set to empty string => get returns default always 125 { 126 const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING"; 127 size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT); 128 EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key"; 129 EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue); 130 ResetValue(); 131 } 132 133 // Set to max length => get returns what was set 134 { 135 std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a'); 136 137 int len = SetAndGetProperty(maxLengthString.c_str()); 138 EXPECT_EQ(PROPERTY_VALUE_MAX-1, len) << "max length key"; 139 EXPECT_STREQ(maxLengthString.c_str(), mValue); 140 ResetValue(); 141 } 142 143 // Set to max length + 1 => set fails 144 { 145 const char* VALID_TEST_VALUE = "VALID_VALUE"; 146 ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE)); 147 148 std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a'); 149 150 // Expect that the value set fails since it's too long 151 EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str())); 152 size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT); 153 154 EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed"; 155 EXPECT_STREQ(VALID_TEST_VALUE, mValue); 156 ResetValue(); 157 } 158 } 159 160 TEST_F(PropertiesTest, GetString) { 161 162 // Try to use a default value that's too long => get truncates the value 163 { 164 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); 165 166 std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); 167 std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a'); 168 169 // Expect that the value is truncated since it's too long (by 1) 170 int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str()); 171 EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len); 172 EXPECT_STREQ(maxLengthString.c_str(), mValue); 173 ResetValue(); 174 } 175 176 // Try to use a default value that's the max length => get succeeds 177 { 178 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); 179 180 std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b'); 181 182 // Expect that the value matches maxLengthString 183 int len = property_get(PROPERTY_TEST_KEY, mValue, maxLengthString.c_str()); 184 EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len); 185 EXPECT_STREQ(maxLengthString.c_str(), mValue); 186 ResetValue(); 187 } 188 189 // Try to use a default value of length one => get succeeds 190 { 191 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); 192 193 std::string oneCharString = std::string(1, 'c'); 194 195 // Expect that the value matches oneCharString 196 int len = property_get(PROPERTY_TEST_KEY, mValue, oneCharString.c_str()); 197 EXPECT_EQ(1, len); 198 EXPECT_STREQ(oneCharString.c_str(), mValue); 199 ResetValue(); 200 } 201 202 // Try to use a default value of length zero => get succeeds 203 { 204 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); 205 206 std::string zeroCharString = std::string(0, 'd'); 207 208 // Expect that the value matches oneCharString 209 int len = property_get(PROPERTY_TEST_KEY, mValue, zeroCharString.c_str()); 210 EXPECT_EQ(0, len); 211 EXPECT_STREQ(zeroCharString.c_str(), mValue); 212 ResetValue(); 213 } 214 215 // Try to use a NULL default value => get returns 0 216 { 217 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); 218 219 // Expect a return value of 0 220 int len = property_get(PROPERTY_TEST_KEY, mValue, NULL); 221 EXPECT_EQ(0, len); 222 ResetValue(); 223 } 224 } 225 226 TEST_F(PropertiesTest, GetBool) { 227 /** 228 * TRUE 229 */ 230 const char *valuesTrue[] = { "1", "true", "y", "yes", "on", }; 231 for (size_t i = 0; i < arraysize(valuesTrue); ++i) { 232 ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i])); 233 bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false); 234 EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'"; 235 } 236 237 /** 238 * FALSE 239 */ 240 const char *valuesFalse[] = { "0", "false", "n", "no", "off", }; 241 for (size_t i = 0; i < arraysize(valuesFalse); ++i) { 242 ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i])); 243 bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true); 244 EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'"; 245 } 246 247 /** 248 * NEITHER 249 */ 250 const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ", 251 "+1", " 1 ", " true", " true ", " y ", " yes", "yes ", 252 "+0", "-0", "00", " 00 ", " false", "false ", 253 }; 254 for (size_t i = 0; i < arraysize(valuesNeither); ++i) { 255 ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesNeither[i])); 256 257 // The default value should always be used 258 bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true); 259 EXPECT_TRUE(val) << "Property should've been NEITHER (true) for string value: '" << valuesNeither[i] << "'"; 260 261 val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false); 262 EXPECT_FALSE(val) << "Property should've been NEITHER (false) for string value: '" << valuesNeither[i] << "'"; 263 } 264 } 265 266 TEST_F(PropertiesTest, GetInt64) { 267 const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD); 268 269 const std::string longMaxString = ToString(INT64_MAX); 270 const std::string longStringOverflow = longMaxString + "0"; 271 272 const std::string longMinString = ToString(INT64_MIN); 273 const std::string longStringUnderflow = longMinString + "0"; 274 275 const char* setValues[] = { 276 // base 10 277 "1", "2", "12345", "-1", "-2", "-12345", 278 // base 16 279 "0xFF", "0x0FF", "0xC0FFEE", 280 // base 8 281 "0", "01234", "07", 282 // corner cases 283 " 2", "2 ", "+0", "-0", " +0 ", longMaxString.c_str(), longMinString.c_str(), 284 // failing cases 285 NULL, "", " ", " ", "hello", " true ", "y", 286 longStringOverflow.c_str(), longStringUnderflow.c_str(), 287 }; 288 289 int64_t getValues[] = { 290 // base 10 291 1, 2, 12345, -1, -2, -12345, 292 // base 16 293 0xFF, 0x0FF, 0xC0FFEE, 294 // base 8 295 0, 01234, 07, 296 // corner cases 297 2, 2, 0, 0, 0, INT64_MAX, INT64_MIN, 298 // failing cases 299 DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, 300 DEFAULT_VALUE, DEFAULT_VALUE, 301 }; 302 303 ASSERT_EQ(arraysize(setValues), arraysize(getValues)); 304 305 for (size_t i = 0; i < arraysize(setValues); ++i) { 306 ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i])); 307 308 int64_t val = property_get_int64(PROPERTY_TEST_KEY, DEFAULT_VALUE); 309 EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'"; 310 } 311 } 312 313 TEST_F(PropertiesTest, GetInt32) { 314 const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF); 315 316 const std::string intMaxString = ToString(INT32_MAX); 317 const std::string intStringOverflow = intMaxString + "0"; 318 319 const std::string intMinString = ToString(INT32_MIN); 320 const std::string intStringUnderflow = intMinString + "0"; 321 322 const char* setValues[] = { 323 // base 10 324 "1", "2", "12345", "-1", "-2", "-12345", 325 // base 16 326 "0xFF", "0x0FF", "0xC0FFEE", "0Xf00", 327 // base 8 328 "0", "01234", "07", 329 // corner cases 330 " 2", "2 ", "+0", "-0", " +0 ", intMaxString.c_str(), intMinString.c_str(), 331 // failing cases 332 NULL, "", " ", " ", "hello", " true ", "y", 333 intStringOverflow.c_str(), intStringUnderflow.c_str(), 334 }; 335 336 int32_t getValues[] = { 337 // base 10 338 1, 2, 12345, -1, -2, -12345, 339 // base 16 340 0xFF, 0x0FF, 0xC0FFEE, 0Xf00, 341 // base 8 342 0, 01234, 07, 343 // corner cases 344 2, 2, 0, 0, 0, INT32_MAX, INT32_MIN, 345 // failing cases 346 DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, 347 DEFAULT_VALUE, DEFAULT_VALUE, 348 }; 349 350 ASSERT_EQ(arraysize(setValues), arraysize(getValues)); 351 352 for (size_t i = 0; i < arraysize(setValues); ++i) { 353 ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i])); 354 355 int32_t val = property_get_int32(PROPERTY_TEST_KEY, DEFAULT_VALUE); 356 EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'"; 357 } 358 } 359 360 } // namespace android 361