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