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 #include <string> 24 25 #if defined(__BIONIC__) 26 27 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 28 #include <sys/_system_properties.h> 29 30 extern void *__system_property_area__; 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_NE((prop_info *)NULL, pi); 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 = (int *)arg; 103 prop_info *pi; 104 pi = (prop_info *)__system_property_find("property"); 105 usleep(100000); 106 107 *flag = 1; 108 __system_property_update(pi, "value3", 6); 109 110 return NULL; 111 } 112 113 #endif // __BIONIC__ 114 115 TEST(properties, add) { 116 #if defined(__BIONIC__) 117 LocalPropertyTestState pa; 118 ASSERT_TRUE(pa.valid); 119 120 char propvalue[PROP_VALUE_MAX]; 121 122 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 123 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 124 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 125 126 ASSERT_EQ(6, __system_property_get("property", propvalue)); 127 ASSERT_STREQ(propvalue, "value1"); 128 129 ASSERT_EQ(6, __system_property_get("other_property", propvalue)); 130 ASSERT_STREQ(propvalue, "value2"); 131 132 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 133 ASSERT_STREQ(propvalue, "value3"); 134 #else // __BIONIC__ 135 GTEST_LOG_(INFO) << "This test does nothing.\n"; 136 #endif // __BIONIC__ 137 } 138 139 TEST(properties, update) { 140 #if defined(__BIONIC__) 141 LocalPropertyTestState pa; 142 ASSERT_TRUE(pa.valid); 143 144 char propvalue[PROP_VALUE_MAX]; 145 prop_info *pi; 146 147 ASSERT_EQ(0, __system_property_add("property", 8, "oldvalue1", 9)); 148 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 149 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 150 151 pi = (prop_info *)__system_property_find("property"); 152 ASSERT_NE((prop_info *)NULL, pi); 153 __system_property_update(pi, "value4", 6); 154 155 pi = (prop_info *)__system_property_find("other_property"); 156 ASSERT_NE((prop_info *)NULL, pi); 157 __system_property_update(pi, "newvalue5", 9); 158 159 pi = (prop_info *)__system_property_find("property_other"); 160 ASSERT_NE((prop_info *)NULL, pi); 161 __system_property_update(pi, "value6", 6); 162 163 ASSERT_EQ(6, __system_property_get("property", propvalue)); 164 ASSERT_STREQ(propvalue, "value4"); 165 166 ASSERT_EQ(9, __system_property_get("other_property", propvalue)); 167 ASSERT_STREQ(propvalue, "newvalue5"); 168 169 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 170 ASSERT_STREQ(propvalue, "value6"); 171 #else // __BIONIC__ 172 GTEST_LOG_(INFO) << "This test does nothing.\n"; 173 #endif // __BIONIC__ 174 } 175 176 TEST(properties, fill) { 177 #if defined(__BIONIC__) 178 LocalPropertyTestState pa; 179 ASSERT_TRUE(pa.valid); 180 char prop_name[PROP_NAME_MAX]; 181 char prop_value[PROP_VALUE_MAX]; 182 char prop_value_ret[PROP_VALUE_MAX]; 183 int count = 0; 184 int ret; 185 186 while (true) { 187 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", count); 188 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 189 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", count); 190 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 191 prop_name[PROP_NAME_MAX - 1] = 0; 192 prop_value[PROP_VALUE_MAX - 1] = 0; 193 194 ret = __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1); 195 if (ret < 0) 196 break; 197 198 count++; 199 } 200 201 // For historical reasons at least 247 properties must be supported 202 ASSERT_GE(count, 247); 203 204 for (int i = 0; i < count; i++) { 205 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i); 206 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 207 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i); 208 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 209 prop_name[PROP_NAME_MAX - 1] = 0; 210 prop_value[PROP_VALUE_MAX - 1] = 0; 211 memset(prop_value_ret, '\0', PROP_VALUE_MAX); 212 213 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret)); 214 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX)); 215 } 216 #else // __BIONIC__ 217 GTEST_LOG_(INFO) << "This test does nothing.\n"; 218 #endif // __BIONIC__ 219 } 220 221 TEST(properties, foreach) { 222 #if defined(__BIONIC__) 223 LocalPropertyTestState pa; 224 ASSERT_TRUE(pa.valid); 225 size_t count = 0; 226 227 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 228 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 229 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 230 231 ASSERT_EQ(0, __system_property_foreach(foreach_test_callback, &count)); 232 ASSERT_EQ(3U, count); 233 #else // __BIONIC__ 234 GTEST_LOG_(INFO) << "This test does nothing.\n"; 235 #endif // __BIONIC__ 236 } 237 238 TEST(properties, find_nth) { 239 #if defined(__BIONIC__) 240 LocalPropertyTestState pa; 241 ASSERT_TRUE(pa.valid); 242 243 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 244 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 245 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 246 247 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(0)); 248 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(1)); 249 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(2)); 250 251 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(3)); 252 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(4)); 253 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(5)); 254 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(100)); 255 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(200)); 256 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247)); 257 #else // __BIONIC__ 258 GTEST_LOG_(INFO) << "This test does nothing.\n"; 259 #endif // __BIONIC__ 260 } 261 262 TEST(properties, fill_hierarchical) { 263 #if defined(__BIONIC__) 264 LocalPropertyTestState pa; 265 ASSERT_TRUE(pa.valid); 266 char prop_name[PROP_NAME_MAX]; 267 char prop_value[PROP_VALUE_MAX]; 268 char prop_value_ret[PROP_VALUE_MAX]; 269 int ret; 270 271 for (int i = 0; i < 8; i++) { 272 for (int j = 0; j < 8; j++) { 273 for (int k = 0; k < 8; k++) { 274 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k); 275 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 276 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k); 277 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 278 prop_name[PROP_NAME_MAX - 1] = 0; 279 prop_value[PROP_VALUE_MAX - 1] = 0; 280 281 ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1)); 282 } 283 } 284 } 285 286 for (int i = 0; i < 8; i++) { 287 for (int j = 0; j < 8; j++) { 288 for (int k = 0; k < 8; k++) { 289 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k); 290 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 291 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k); 292 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 293 prop_name[PROP_NAME_MAX - 1] = 0; 294 prop_value[PROP_VALUE_MAX - 1] = 0; 295 memset(prop_value_ret, '\0', PROP_VALUE_MAX); 296 297 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret)); 298 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX)); 299 } 300 } 301 } 302 303 bool ok[8][8][8]; 304 memset(ok, 0, sizeof(ok)); 305 __system_property_foreach(hierarchical_test_callback, ok); 306 307 for (int i = 0; i < 8; i++) { 308 for (int j = 0; j < 8; j++) { 309 for (int k = 0; k < 8; k++) { 310 ASSERT_TRUE(ok[i][j][k]); 311 } 312 } 313 } 314 #else // __BIONIC__ 315 GTEST_LOG_(INFO) << "This test does nothing.\n"; 316 #endif // __BIONIC__ 317 } 318 319 TEST(properties, errors) { 320 #if defined(__BIONIC__) 321 LocalPropertyTestState pa; 322 ASSERT_TRUE(pa.valid); 323 char prop_value[PROP_NAME_MAX]; 324 325 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 326 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 327 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 328 329 ASSERT_EQ(0, __system_property_find("property1")); 330 ASSERT_EQ(0, __system_property_get("property1", prop_value)); 331 332 ASSERT_EQ(-1, __system_property_add("name", PROP_NAME_MAX, "value", 5)); 333 ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX)); 334 ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX)); 335 #else // __BIONIC__ 336 GTEST_LOG_(INFO) << "This test does nothing.\n"; 337 #endif // __BIONIC__ 338 } 339 340 TEST(properties, serial) { 341 #if defined(__BIONIC__) 342 LocalPropertyTestState pa; 343 ASSERT_TRUE(pa.valid); 344 const prop_info *pi; 345 unsigned int serial; 346 347 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 348 ASSERT_NE((const prop_info *)NULL, pi = __system_property_find("property")); 349 serial = __system_property_serial(pi); 350 ASSERT_EQ(0, __system_property_update((prop_info *)pi, "value2", 6)); 351 ASSERT_NE(serial, __system_property_serial(pi)); 352 #else // __BIONIC__ 353 GTEST_LOG_(INFO) << "This test does nothing.\n"; 354 #endif // __BIONIC__ 355 } 356 357 TEST(properties, wait) { 358 #if defined(__BIONIC__) 359 LocalPropertyTestState pa; 360 ASSERT_TRUE(pa.valid); 361 unsigned int serial; 362 prop_info *pi; 363 pthread_t t; 364 int flag = 0; 365 366 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 367 serial = __system_property_wait_any(0); 368 pi = (prop_info *)__system_property_find("property"); 369 ASSERT_NE((prop_info *)NULL, pi); 370 __system_property_update(pi, "value2", 6); 371 serial = __system_property_wait_any(serial); 372 373 ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag)); 374 ASSERT_EQ(flag, 0); 375 serial = __system_property_wait_any(serial); 376 ASSERT_EQ(flag, 1); 377 378 void* result; 379 ASSERT_EQ(0, pthread_join(t, &result)); 380 #else // __BIONIC__ 381 GTEST_LOG_(INFO) << "This test does nothing.\n"; 382 #endif // __BIONIC__ 383 } 384 385 class KilledByFault { 386 public: 387 explicit KilledByFault() {}; 388 bool operator()(int exit_status) const; 389 }; 390 391 bool KilledByFault::operator()(int exit_status) const { 392 return WIFSIGNALED(exit_status) && 393 (WTERMSIG(exit_status) == SIGSEGV || 394 WTERMSIG(exit_status) == SIGBUS || 395 WTERMSIG(exit_status) == SIGABRT); 396 } 397 398 class properties_DeathTest : public BionicDeathTest {}; 399 400 TEST_F(properties_DeathTest, read_only) { 401 #if defined(__BIONIC__) 402 403 // This test only makes sense if we're talking to the real system property service. 404 struct stat sb; 405 if (stat(PROP_FILENAME, &sb) == -1 && errno == ENOENT) { 406 return; 407 } 408 409 ASSERT_EXIT(__system_property_add("property", 8, "value", 5), KilledByFault(), ""); 410 #else // __BIONIC__ 411 GTEST_LOG_(INFO) << "This test does nothing.\n"; 412 #endif // __BIONIC__ 413 } 414