1 /* 2 * Copyright (C) 2013 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 <gtest/gtest.h> 18 #include <sys/wait.h> 19 #include <errno.h> 20 #include <unistd.h> 21 #include <string> 22 23 #if defined(__BIONIC__) 24 25 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 26 #include <sys/_system_properties.h> 27 28 extern void *__system_property_area__; 29 30 struct LocalPropertyTestState { 31 LocalPropertyTestState() : valid(false) { 32 const char* ANDROID_DATA = getenv("ANDROID_DATA"); 33 char dir_template[PATH_MAX]; 34 snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", ANDROID_DATA); 35 char* dirname = mkdtemp(dir_template); 36 if (!dirname) { 37 fprintf(stderr, "making temp file for test state failed (is %s writable?): %s", 38 dir_template, strerror(errno)); 39 return; 40 } 41 42 old_pa = __system_property_area__; 43 __system_property_area__ = NULL; 44 45 pa_dirname = dirname; 46 pa_filename = pa_dirname + "/__properties__"; 47 48 __system_property_set_filename(pa_filename.c_str()); 49 __system_property_area_init(); 50 valid = true; 51 } 52 53 ~LocalPropertyTestState() { 54 if (!valid) { 55 return; 56 } 57 58 __system_property_area__ = old_pa; 59 60 __system_property_set_filename(PROP_FILENAME); 61 unlink(pa_filename.c_str()); 62 rmdir(pa_dirname.c_str()); 63 } 64 public: 65 bool valid; 66 private: 67 std::string pa_dirname; 68 std::string pa_filename; 69 void *old_pa; 70 }; 71 72 static void foreach_test_callback(const prop_info *pi, void* cookie) { 73 size_t *count = static_cast<size_t *>(cookie); 74 75 ASSERT_NE((prop_info *)NULL, pi); 76 (*count)++; 77 } 78 79 static void hierarchical_test_callback(const prop_info *pi, void *cookie) { 80 bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie); 81 82 char name[PROP_NAME_MAX]; 83 char value[PROP_VALUE_MAX]; 84 85 __system_property_read(pi, name, value); 86 87 int name_i, name_j, name_k; 88 int value_i, value_j, value_k; 89 ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k)); 90 ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k)); 91 ASSERT_EQ(name_i, value_i); 92 ASSERT_GE(name_i, 0); 93 ASSERT_LT(name_i, 8); 94 ASSERT_EQ(name_j, value_j); 95 ASSERT_GE(name_j, 0); 96 ASSERT_LT(name_j, 8); 97 ASSERT_EQ(name_k, value_k); 98 ASSERT_GE(name_k, 0); 99 ASSERT_LT(name_k, 8); 100 101 ok[name_i][name_j][name_k] = true; 102 } 103 104 static void *PropertyWaitHelperFn(void *arg) { 105 int *flag = (int *)arg; 106 prop_info *pi; 107 pi = (prop_info *)__system_property_find("property"); 108 usleep(100000); 109 110 *flag = 1; 111 __system_property_update(pi, "value3", 6); 112 113 return NULL; 114 } 115 116 #endif // __BIONIC__ 117 118 TEST(properties, add) { 119 #if defined(__BIONIC__) 120 LocalPropertyTestState pa; 121 ASSERT_TRUE(pa.valid); 122 123 char propvalue[PROP_VALUE_MAX]; 124 125 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 126 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 127 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 128 129 ASSERT_EQ(6, __system_property_get("property", propvalue)); 130 ASSERT_STREQ(propvalue, "value1"); 131 132 ASSERT_EQ(6, __system_property_get("other_property", propvalue)); 133 ASSERT_STREQ(propvalue, "value2"); 134 135 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 136 ASSERT_STREQ(propvalue, "value3"); 137 #else // __BIONIC__ 138 GTEST_LOG_(INFO) << "This test does nothing.\n"; 139 #endif // __BIONIC__ 140 } 141 142 TEST(properties, update) { 143 #if defined(__BIONIC__) 144 LocalPropertyTestState pa; 145 ASSERT_TRUE(pa.valid); 146 147 char propvalue[PROP_VALUE_MAX]; 148 prop_info *pi; 149 150 ASSERT_EQ(0, __system_property_add("property", 8, "oldvalue1", 9)); 151 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 152 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 153 154 pi = (prop_info *)__system_property_find("property"); 155 ASSERT_NE((prop_info *)NULL, pi); 156 __system_property_update(pi, "value4", 6); 157 158 pi = (prop_info *)__system_property_find("other_property"); 159 ASSERT_NE((prop_info *)NULL, pi); 160 __system_property_update(pi, "newvalue5", 9); 161 162 pi = (prop_info *)__system_property_find("property_other"); 163 ASSERT_NE((prop_info *)NULL, pi); 164 __system_property_update(pi, "value6", 6); 165 166 ASSERT_EQ(6, __system_property_get("property", propvalue)); 167 ASSERT_STREQ(propvalue, "value4"); 168 169 ASSERT_EQ(9, __system_property_get("other_property", propvalue)); 170 ASSERT_STREQ(propvalue, "newvalue5"); 171 172 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 173 ASSERT_STREQ(propvalue, "value6"); 174 #else // __BIONIC__ 175 GTEST_LOG_(INFO) << "This test does nothing.\n"; 176 #endif // __BIONIC__ 177 } 178 179 TEST(properties, fill) { 180 #if defined(__BIONIC__) 181 LocalPropertyTestState pa; 182 ASSERT_TRUE(pa.valid); 183 char prop_name[PROP_NAME_MAX]; 184 char prop_value[PROP_VALUE_MAX]; 185 char prop_value_ret[PROP_VALUE_MAX]; 186 int count = 0; 187 int ret; 188 189 while (true) { 190 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", count); 191 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 192 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", count); 193 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 194 prop_name[PROP_NAME_MAX - 1] = 0; 195 prop_value[PROP_VALUE_MAX - 1] = 0; 196 197 ret = __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1); 198 if (ret < 0) 199 break; 200 201 count++; 202 } 203 204 // For historical reasons at least 247 properties must be supported 205 ASSERT_GE(count, 247); 206 207 for (int i = 0; i < count; i++) { 208 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i); 209 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 210 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i); 211 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 212 prop_name[PROP_NAME_MAX - 1] = 0; 213 prop_value[PROP_VALUE_MAX - 1] = 0; 214 memset(prop_value_ret, '\0', PROP_VALUE_MAX); 215 216 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret)); 217 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX)); 218 } 219 #else // __BIONIC__ 220 GTEST_LOG_(INFO) << "This test does nothing.\n"; 221 #endif // __BIONIC__ 222 } 223 224 TEST(properties, foreach) { 225 #if defined(__BIONIC__) 226 LocalPropertyTestState pa; 227 ASSERT_TRUE(pa.valid); 228 size_t count = 0; 229 230 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 231 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 232 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 233 234 ASSERT_EQ(0, __system_property_foreach(foreach_test_callback, &count)); 235 ASSERT_EQ(3U, count); 236 #else // __BIONIC__ 237 GTEST_LOG_(INFO) << "This test does nothing.\n"; 238 #endif // __BIONIC__ 239 } 240 241 TEST(properties, find_nth) { 242 #if defined(__BIONIC__) 243 LocalPropertyTestState pa; 244 ASSERT_TRUE(pa.valid); 245 246 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 247 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 248 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 249 250 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(0)); 251 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(1)); 252 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(2)); 253 254 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(3)); 255 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(4)); 256 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(5)); 257 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(100)); 258 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(200)); 259 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247)); 260 #else // __BIONIC__ 261 GTEST_LOG_(INFO) << "This test does nothing.\n"; 262 #endif // __BIONIC__ 263 } 264 265 TEST(properties, fill_hierarchical) { 266 #if defined(__BIONIC__) 267 LocalPropertyTestState pa; 268 ASSERT_TRUE(pa.valid); 269 char prop_name[PROP_NAME_MAX]; 270 char prop_value[PROP_VALUE_MAX]; 271 char prop_value_ret[PROP_VALUE_MAX]; 272 int ret; 273 274 for (int i = 0; i < 8; i++) { 275 for (int j = 0; j < 8; j++) { 276 for (int k = 0; k < 8; k++) { 277 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k); 278 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 279 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k); 280 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 281 prop_name[PROP_NAME_MAX - 1] = 0; 282 prop_value[PROP_VALUE_MAX - 1] = 0; 283 284 ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1)); 285 } 286 } 287 } 288 289 for (int i = 0; i < 8; i++) { 290 for (int j = 0; j < 8; j++) { 291 for (int k = 0; k < 8; k++) { 292 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k); 293 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 294 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k); 295 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 296 prop_name[PROP_NAME_MAX - 1] = 0; 297 prop_value[PROP_VALUE_MAX - 1] = 0; 298 memset(prop_value_ret, '\0', PROP_VALUE_MAX); 299 300 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret)); 301 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX)); 302 } 303 } 304 } 305 306 bool ok[8][8][8]; 307 memset(ok, 0, sizeof(ok)); 308 __system_property_foreach(hierarchical_test_callback, ok); 309 310 for (int i = 0; i < 8; i++) { 311 for (int j = 0; j < 8; j++) { 312 for (int k = 0; k < 8; k++) { 313 ASSERT_TRUE(ok[i][j][k]); 314 } 315 } 316 } 317 #else // __BIONIC__ 318 GTEST_LOG_(INFO) << "This test does nothing.\n"; 319 #endif // __BIONIC__ 320 } 321 322 TEST(properties, errors) { 323 #if defined(__BIONIC__) 324 LocalPropertyTestState pa; 325 ASSERT_TRUE(pa.valid); 326 char prop_value[PROP_NAME_MAX]; 327 328 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 329 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 330 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 331 332 ASSERT_EQ(0, __system_property_find("property1")); 333 ASSERT_EQ(0, __system_property_get("property1", prop_value)); 334 335 ASSERT_EQ(-1, __system_property_add("name", PROP_NAME_MAX, "value", 5)); 336 ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX)); 337 ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX)); 338 #else // __BIONIC__ 339 GTEST_LOG_(INFO) << "This test does nothing.\n"; 340 #endif // __BIONIC__ 341 } 342 343 TEST(properties, serial) { 344 #if defined(__BIONIC__) 345 LocalPropertyTestState pa; 346 ASSERT_TRUE(pa.valid); 347 const prop_info *pi; 348 unsigned int serial; 349 350 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 351 ASSERT_NE((const prop_info *)NULL, pi = __system_property_find("property")); 352 serial = __system_property_serial(pi); 353 ASSERT_EQ(0, __system_property_update((prop_info *)pi, "value2", 6)); 354 ASSERT_NE(serial, __system_property_serial(pi)); 355 #else // __BIONIC__ 356 GTEST_LOG_(INFO) << "This test does nothing.\n"; 357 #endif // __BIONIC__ 358 } 359 360 TEST(properties, wait) { 361 #if defined(__BIONIC__) 362 LocalPropertyTestState pa; 363 ASSERT_TRUE(pa.valid); 364 unsigned int serial; 365 prop_info *pi; 366 pthread_t t; 367 int flag = 0; 368 369 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 370 serial = __system_property_wait_any(0); 371 pi = (prop_info *)__system_property_find("property"); 372 ASSERT_NE((prop_info *)NULL, pi); 373 __system_property_update(pi, "value2", 6); 374 serial = __system_property_wait_any(serial); 375 376 ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag)); 377 ASSERT_EQ(flag, 0); 378 serial = __system_property_wait_any(serial); 379 ASSERT_EQ(flag, 1); 380 381 void* result; 382 ASSERT_EQ(0, pthread_join(t, &result)); 383 #else // __BIONIC__ 384 GTEST_LOG_(INFO) << "This test does nothing.\n"; 385 #endif // __BIONIC__ 386 } 387 388 class KilledByFault { 389 public: 390 explicit KilledByFault() {}; 391 bool operator()(int exit_status) const; 392 }; 393 394 bool KilledByFault::operator()(int exit_status) const { 395 return WIFSIGNALED(exit_status) && 396 (WTERMSIG(exit_status) == SIGSEGV || 397 WTERMSIG(exit_status) == SIGBUS || 398 WTERMSIG(exit_status) == SIGABRT); 399 } 400 401 TEST(properties_DeathTest, read_only) { 402 #if defined(__BIONIC__) 403 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 404 405 // This test only makes sense if we're talking to the real system property service. 406 struct stat sb; 407 if (stat(PROP_FILENAME, &sb) == -1 && errno == ENOENT) { 408 return; 409 } 410 411 ASSERT_EXIT(__system_property_add("property", 8, "value", 5), KilledByFault(), ""); 412 #else // __BIONIC__ 413 GTEST_LOG_(INFO) << "This test does nothing.\n"; 414 #endif // __BIONIC__ 415 } 416