system_properties_test.cpp revision 890aa0d937ae72473c84cc773e77d45e9288b0bc
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 205TEST(properties, errors) { 206 LocalPropertyTestState pa; 207 ASSERT_TRUE(pa.valid); 208 char prop_value[PROP_NAME_MAX]; 209 210 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 211 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 212 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 213 214 ASSERT_EQ(0, __system_property_find("property1")); 215 ASSERT_EQ(0, __system_property_get("property1", prop_value)); 216 217 ASSERT_EQ(-1, __system_property_add("name", PROP_NAME_MAX, "value", 5)); 218 ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX)); 219 ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX)); 220} 221 222TEST(properties, serial) { 223 LocalPropertyTestState pa; 224 ASSERT_TRUE(pa.valid); 225 const prop_info *pi; 226 unsigned int serial; 227 228 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 229 ASSERT_NE((const prop_info *)NULL, pi = __system_property_find("property")); 230 serial = __system_property_serial(pi); 231 ASSERT_EQ(0, __system_property_update((prop_info *)pi, "value2", 6)); 232 ASSERT_NE(serial, __system_property_serial(pi)); 233} 234 235static void *PropertyWaitHelperFn(void *arg) 236{ 237 int *flag = (int *)arg; 238 prop_info *pi; 239 pi = (prop_info *)__system_property_find("property"); 240 usleep(100000); 241 242 *flag = 1; 243 __system_property_update(pi, "value3", 6); 244 245 return NULL; 246} 247 248TEST(properties, wait) { 249 LocalPropertyTestState pa; 250 ASSERT_TRUE(pa.valid); 251 unsigned int serial; 252 prop_info *pi; 253 pthread_t t; 254 int flag = 0; 255 256 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 257 serial = __system_property_wait_any(0); 258 pi = (prop_info *)__system_property_find("property"); 259 ASSERT_NE((prop_info *)NULL, pi); 260 __system_property_update(pi, "value2", 6); 261 serial = __system_property_wait_any(serial); 262 263 ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag)); 264 ASSERT_EQ(flag, 0); 265 serial = __system_property_wait_any(serial); 266 ASSERT_EQ(flag, 1); 267 268 void* result; 269 ASSERT_EQ(0, pthread_join(t, &result)); 270} 271 272class KilledByFault { 273 public: 274 explicit KilledByFault() {}; 275 bool operator()(int exit_status) const; 276}; 277 278bool KilledByFault::operator()(int exit_status) const { 279 return WIFSIGNALED(exit_status) && 280 (WTERMSIG(exit_status) == SIGSEGV || 281 WTERMSIG(exit_status) == SIGBUS || 282 WTERMSIG(exit_status) == SIGABRT); 283} 284 285TEST(properties_DeathTest, read_only) { 286 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 287 ASSERT_EXIT(__system_property_add("property", 8, "value", 5), 288 KilledByFault(), ""); 289} 290#endif 291