blob: efc01833abe2e03bb42aad912fdcc70e4aed1305 [file] [log] [blame]
Igor Murashkind4507e92014-04-08 11:22:42 -07001/*
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"
Igor Murashkind4507e92014-04-08 11:22:42 -070018
Igor Murashkind4507e92014-04-08 11:22:42 -070019#include <limits.h>
Igor Murashkind4507e92014-04-08 11:22:42 -070020
Mark Salyzyn23ed4c22016-09-28 13:33:27 -070021#include <iostream>
22#include <sstream>
23#include <string>
24
25#include <android/log.h>
Elliott Hughes749ae2d2016-06-28 14:48:45 -070026#include <android-base/macros.h>
Mark Salyzyn23ed4c22016-09-28 13:33:27 -070027#include <cutils/properties.h>
28#include <gtest/gtest.h>
Elliott Hughes749ae2d2016-06-28 14:48:45 -070029
Igor Murashkind4507e92014-04-08 11:22:42 -070030namespace android {
31
32#define STRINGIFY_INNER(x) #x
33#define STRINGIFY(x) STRINGIFY_INNER(x)
Igor Murashkind4507e92014-04-08 11:22:42 -070034#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
40template <typename T>
41static std::string HexString(T value) {
42 std::stringstream ss;
43 ss << "0x" << std::hex << std::uppercase << value;
44 return ss.str();
45}
46
47template <typename T>
48static ::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
61class PropertiesTest : public testing::Test {
62public:
63 PropertiesTest() : mValue() {}
64protected:
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) {
Elliott Hughes749ae2d2016-06-28 14:48:45 -070090 for (size_t i = 0; i < arraysize(mValue); ++i) {
Igor Murashkind4507e92014-04-08 11:22:42 -070091 mValue[i] = (char) c;
92 }
93 }
94};
95
S Vasudev Prasad100b08a2020-05-08 11:45:45 +053096TEST_F(PropertiesTest, property_set_null_key) {
Igor Murashkind4507e92014-04-08 11:22:42 -070097 // Null key -> unsuccessful set
S Vasudev Prasad100b08a2020-05-08 11:45:45 +053098 EXPECT_GT(0, property_set(/*key*/ NULL, PROPERTY_TEST_VALUE_DEFAULT));
99}
Igor Murashkind4507e92014-04-08 11:22:42 -0700100
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530101TEST_F(PropertiesTest, property_set_null_value) {
102 // Null value -> OK, and it clears the value
103 EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/ NULL));
104 ResetValue();
Igor Murashkind4507e92014-04-08 11:22:42 -0700105
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530106 // Since the value is null, default value will be returned
107 size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
108 EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len);
109 EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue);
110}
Igor Murashkind4507e92014-04-08 11:22:42 -0700111
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530112TEST_F(PropertiesTest, property_set) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700113 // Trivial case => get returns what was set
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530114 size_t len = SetAndGetProperty("hello_world");
115 EXPECT_EQ(strlen("hello_world"), len) << "hello_world key";
116 EXPECT_STREQ("hello_world", mValue);
117 ResetValue();
118}
Igor Murashkind4507e92014-04-08 11:22:42 -0700119
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530120TEST_F(PropertiesTest, property_set_empty) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700121 // Set to empty string => get returns default always
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530122 const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING";
123 size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT);
124 EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key";
125 EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue);
126 ResetValue();
127}
Igor Murashkind4507e92014-04-08 11:22:42 -0700128
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530129TEST_F(PropertiesTest, property_set_max_length) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700130 // Set to max length => get returns what was set
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530131 std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a');
Igor Murashkind4507e92014-04-08 11:22:42 -0700132
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530133 int len = SetAndGetProperty(maxLengthString.c_str());
134 EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len) << "max length key";
135 EXPECT_STREQ(maxLengthString.c_str(), mValue);
136 ResetValue();
137}
Igor Murashkind4507e92014-04-08 11:22:42 -0700138
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530139TEST_F(PropertiesTest, property_set_too_long) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700140 // Set to max length + 1 => set fails
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530141 const char* VALID_TEST_VALUE = "VALID_VALUE";
142 ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE));
Igor Murashkind4507e92014-04-08 11:22:42 -0700143
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530144 std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
Igor Murashkind4507e92014-04-08 11:22:42 -0700145
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530146 // Expect that the value set fails since it's too long
147 EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str()));
148 size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
Igor Murashkind4507e92014-04-08 11:22:42 -0700149
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530150 EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed";
151 EXPECT_STREQ(VALID_TEST_VALUE, mValue);
152 ResetValue();
Igor Murashkind4507e92014-04-08 11:22:42 -0700153}
154
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530155TEST_F(PropertiesTest, property_get_too_long) {
Myles Watsone67abec2016-12-22 09:05:18 -0800156 // Try to use a default value that's too long => get truncates the value
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530157 ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
Igor Murashkind4507e92014-04-08 11:22:42 -0700158
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530159 std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a');
160 std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
Igor Murashkind4507e92014-04-08 11:22:42 -0700161
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530162 // Expect that the value is truncated since it's too long (by 1)
163 int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str());
164 EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len);
165 EXPECT_STREQ(maxLengthString.c_str(), mValue);
166 ResetValue();
Igor Murashkind4507e92014-04-08 11:22:42 -0700167}
168
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530169TEST_F(PropertiesTest, property_get_default_too_long) {
170 // Try to use a default value that's the max length => get succeeds
171 ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
Igor Murashkind4507e92014-04-08 11:22:42 -0700172
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530173 std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b');
Igor Murashkind4507e92014-04-08 11:22:42 -0700174
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530175 // Expect that the value matches maxLengthString
176 int len = property_get(PROPERTY_TEST_KEY, mValue, maxLengthString.c_str());
177 EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len);
178 EXPECT_STREQ(maxLengthString.c_str(), mValue);
179 ResetValue();
180}
181
182TEST_F(PropertiesTest, property_get_default_okay) {
183 // Try to use a default value of length one => get succeeds
184 ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
185
186 std::string oneCharString = std::string(1, 'c');
187
188 // Expect that the value matches oneCharString
189 int len = property_get(PROPERTY_TEST_KEY, mValue, oneCharString.c_str());
190 EXPECT_EQ(1, len);
191 EXPECT_STREQ(oneCharString.c_str(), mValue);
192 ResetValue();
193}
194
195TEST_F(PropertiesTest, property_get_default_empty) {
196 // Try to use a default value of length zero => get succeeds
197 ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
198
199 std::string zeroCharString = std::string(0, 'd');
200
201 // Expect that the value matches oneCharString
202 int len = property_get(PROPERTY_TEST_KEY, mValue, zeroCharString.c_str());
203 EXPECT_EQ(0, len);
204 EXPECT_STREQ(zeroCharString.c_str(), mValue);
205 ResetValue();
206}
207
208TEST_F(PropertiesTest, property_get_default_NULL) {
209 // Try to use a NULL default value => get returns 0
210 ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
211
212 // Expect a return value of 0
213 int len = property_get(PROPERTY_TEST_KEY, mValue, NULL);
214 EXPECT_EQ(0, len);
215 ResetValue();
216}
217
218TEST_F(PropertiesTest, property_get_bool_0) {
219 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "0"));
220 ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true));
221}
222
223TEST_F(PropertiesTest, property_get_bool_1) {
224 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "1"));
225 ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false));
226}
227
228TEST_F(PropertiesTest, property_get_bool_false) {
229 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "false"));
230 ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true));
231}
232
233TEST_F(PropertiesTest, property_get_bool_n) {
234 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "n"));
235 ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true));
236}
237
238TEST_F(PropertiesTest, property_get_bool_no) {
239 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "no"));
240 ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true));
241}
242
243TEST_F(PropertiesTest, property_get_bool_off) {
244 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "off"));
245 ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true));
246}
247
248TEST_F(PropertiesTest, property_get_bool_on) {
249 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "on"));
250 ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false));
251}
252
253TEST_F(PropertiesTest, property_get_bool_true) {
254 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "true"));
255 ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false));
256}
257
258TEST_F(PropertiesTest, property_get_bool_y) {
259 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "y"));
260 ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false));
261}
262
263TEST_F(PropertiesTest, property_get_bool_yes) {
264 ASSERT_OK(property_set(PROPERTY_TEST_KEY, "yes"));
265 ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false));
266}
267
268TEST_F(PropertiesTest, property_get_bool_neither) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700269 const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ",
270 "+1", " 1 ", " true", " true ", " y ", " yes", "yes ",
271 "+0", "-0", "00", " 00 ", " false", "false ",
272 };
Elliott Hughes749ae2d2016-06-28 14:48:45 -0700273 for (size_t i = 0; i < arraysize(valuesNeither); ++i) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700274 ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesNeither[i]));
275
276 // The default value should always be used
277 bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
278 EXPECT_TRUE(val) << "Property should've been NEITHER (true) for string value: '" << valuesNeither[i] << "'";
279
280 val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
281 EXPECT_FALSE(val) << "Property should've been NEITHER (false) for string value: '" << valuesNeither[i] << "'";
282 }
283}
284
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530285TEST_F(PropertiesTest, property_get_int64) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700286 const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD);
287
288 const std::string longMaxString = ToString(INT64_MAX);
289 const std::string longStringOverflow = longMaxString + "0";
290
291 const std::string longMinString = ToString(INT64_MIN);
292 const std::string longStringUnderflow = longMinString + "0";
293
294 const char* setValues[] = {
295 // base 10
296 "1", "2", "12345", "-1", "-2", "-12345",
297 // base 16
298 "0xFF", "0x0FF", "0xC0FFEE",
299 // base 8
300 "0", "01234", "07",
301 // corner cases
302 " 2", "2 ", "+0", "-0", " +0 ", longMaxString.c_str(), longMinString.c_str(),
303 // failing cases
304 NULL, "", " ", " ", "hello", " true ", "y",
305 longStringOverflow.c_str(), longStringUnderflow.c_str(),
306 };
307
308 int64_t getValues[] = {
309 // base 10
310 1, 2, 12345, -1, -2, -12345,
311 // base 16
312 0xFF, 0x0FF, 0xC0FFEE,
313 // base 8
314 0, 01234, 07,
315 // corner cases
316 2, 2, 0, 0, 0, INT64_MAX, INT64_MIN,
317 // failing cases
318 DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
319 DEFAULT_VALUE, DEFAULT_VALUE,
320 };
321
Elliott Hughes749ae2d2016-06-28 14:48:45 -0700322 ASSERT_EQ(arraysize(setValues), arraysize(getValues));
Igor Murashkind4507e92014-04-08 11:22:42 -0700323
Elliott Hughes749ae2d2016-06-28 14:48:45 -0700324 for (size_t i = 0; i < arraysize(setValues); ++i) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700325 ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
326
327 int64_t val = property_get_int64(PROPERTY_TEST_KEY, DEFAULT_VALUE);
328 EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
329 }
330}
331
S Vasudev Prasad100b08a2020-05-08 11:45:45 +0530332TEST_F(PropertiesTest, property_get_int32) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700333 const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF);
334
335 const std::string intMaxString = ToString(INT32_MAX);
336 const std::string intStringOverflow = intMaxString + "0";
337
338 const std::string intMinString = ToString(INT32_MIN);
339 const std::string intStringUnderflow = intMinString + "0";
340
341 const char* setValues[] = {
342 // base 10
343 "1", "2", "12345", "-1", "-2", "-12345",
344 // base 16
345 "0xFF", "0x0FF", "0xC0FFEE", "0Xf00",
346 // base 8
347 "0", "01234", "07",
348 // corner cases
349 " 2", "2 ", "+0", "-0", " +0 ", intMaxString.c_str(), intMinString.c_str(),
350 // failing cases
351 NULL, "", " ", " ", "hello", " true ", "y",
352 intStringOverflow.c_str(), intStringUnderflow.c_str(),
353 };
354
355 int32_t getValues[] = {
356 // base 10
357 1, 2, 12345, -1, -2, -12345,
358 // base 16
359 0xFF, 0x0FF, 0xC0FFEE, 0Xf00,
360 // base 8
361 0, 01234, 07,
362 // corner cases
363 2, 2, 0, 0, 0, INT32_MAX, INT32_MIN,
364 // failing cases
365 DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
366 DEFAULT_VALUE, DEFAULT_VALUE,
367 };
368
Elliott Hughes749ae2d2016-06-28 14:48:45 -0700369 ASSERT_EQ(arraysize(setValues), arraysize(getValues));
Igor Murashkind4507e92014-04-08 11:22:42 -0700370
Elliott Hughes749ae2d2016-06-28 14:48:45 -0700371 for (size_t i = 0; i < arraysize(setValues); ++i) {
Igor Murashkind4507e92014-04-08 11:22:42 -0700372 ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
373
374 int32_t val = property_get_int32(PROPERTY_TEST_KEY, DEFAULT_VALUE);
375 EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
376 }
377}
378
379} // namespace android