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