system_properties_test.cpp revision bd6dc6a8864a1997eb8608030ac816740169c463
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_area__; 28 29struct LocalPropertyTestState { 30 LocalPropertyTestState() : valid(false) { 31 char dir_template[] = "/data/local/tmp/prop-XXXXXX"; 32 char *dirname = mkdtemp(dir_template); 33 if (!dirname) { 34 perror("making temp file for test state failed (is /data/local/tmp writable?)"); 35 return; 36 } 37 38 old_pa = __system_property_area__; 39 __system_property_area__ = NULL; 40 41 pa_dirname = dirname; 42 pa_filename = pa_dirname + "/__properties__"; 43 44 __system_property_set_filename(pa_filename.c_str()); 45 __system_property_area_init(); 46 valid = true; 47 } 48 49 ~LocalPropertyTestState() { 50 if (!valid) 51 return; 52 53 __system_property_area__ = old_pa; 54 55 __system_property_set_filename(PROP_FILENAME); 56 unlink(pa_filename.c_str()); 57 rmdir(pa_dirname.c_str()); 58 } 59public: 60 bool valid; 61private: 62 std::string pa_dirname; 63 std::string pa_filename; 64 void *old_pa; 65}; 66 67TEST(properties, add) { 68 LocalPropertyTestState pa; 69 ASSERT_TRUE(pa.valid); 70 71 char propvalue[PROP_VALUE_MAX]; 72 73 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 74 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 75 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 76 77 ASSERT_EQ(6, __system_property_get("property", propvalue)); 78 ASSERT_STREQ(propvalue, "value1"); 79 80 ASSERT_EQ(6, __system_property_get("other_property", propvalue)); 81 ASSERT_STREQ(propvalue, "value2"); 82 83 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 84 ASSERT_STREQ(propvalue, "value3"); 85} 86 87TEST(properties, update) { 88 LocalPropertyTestState pa; 89 ASSERT_TRUE(pa.valid); 90 91 char propvalue[PROP_VALUE_MAX]; 92 prop_info *pi; 93 94 ASSERT_EQ(0, __system_property_add("property", 8, "oldvalue1", 9)); 95 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 96 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 97 98 pi = (prop_info *)__system_property_find("property"); 99 ASSERT_NE((prop_info *)NULL, pi); 100 __system_property_update(pi, "value4", 6); 101 102 pi = (prop_info *)__system_property_find("other_property"); 103 ASSERT_NE((prop_info *)NULL, pi); 104 __system_property_update(pi, "newvalue5", 9); 105 106 pi = (prop_info *)__system_property_find("property_other"); 107 ASSERT_NE((prop_info *)NULL, pi); 108 __system_property_update(pi, "value6", 6); 109 110 ASSERT_EQ(6, __system_property_get("property", propvalue)); 111 ASSERT_STREQ(propvalue, "value4"); 112 113 ASSERT_EQ(9, __system_property_get("other_property", propvalue)); 114 ASSERT_STREQ(propvalue, "newvalue5"); 115 116 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 117 ASSERT_STREQ(propvalue, "value6"); 118} 119 120TEST(properties, fill) { 121 LocalPropertyTestState pa; 122 ASSERT_TRUE(pa.valid); 123 char prop_name[PROP_NAME_MAX]; 124 char prop_value[PROP_VALUE_MAX]; 125 char prop_value_ret[PROP_VALUE_MAX]; 126 int count = 0; 127 int ret; 128 129 while (true) { 130 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", count); 131 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 132 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", count); 133 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 134 prop_name[PROP_NAME_MAX - 1] = 0; 135 prop_value[PROP_VALUE_MAX - 1] = 0; 136 137 ret = __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1); 138 if (ret < 0) 139 break; 140 141 count++; 142 } 143 144 // For historical reasons at least 247 properties must be supported 145 ASSERT_GE(count, 247); 146 147 for (int i = 0; i < count; i++) { 148 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i); 149 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 150 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i); 151 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 152 prop_name[PROP_NAME_MAX - 1] = 0; 153 prop_value[PROP_VALUE_MAX - 1] = 0; 154 memset(prop_value_ret, '\0', PROP_VALUE_MAX); 155 156 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret)); 157 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX)); 158 } 159} 160 161static void foreach_test_callback(const prop_info *pi, void* cookie) { 162 size_t *count = static_cast<size_t *>(cookie); 163 164 ASSERT_NE((prop_info *)NULL, pi); 165 (*count)++; 166} 167 168TEST(properties, foreach) { 169 LocalPropertyTestState pa; 170 ASSERT_TRUE(pa.valid); 171 size_t count = 0; 172 173 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 174 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 175 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 176 177 ASSERT_EQ(0, __system_property_foreach(foreach_test_callback, &count)); 178 ASSERT_EQ(3U, count); 179} 180 181TEST(properties, find_nth) { 182 LocalPropertyTestState pa; 183 ASSERT_TRUE(pa.valid); 184 185 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 186 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 187 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 188 189 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(0)); 190 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(1)); 191 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(2)); 192 193 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(3)); 194 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(4)); 195 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(5)); 196 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(100)); 197 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(200)); 198 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247)); 199} 200 201TEST(properties, errors) { 202 LocalPropertyTestState pa; 203 ASSERT_TRUE(pa.valid); 204 char prop_value[PROP_NAME_MAX]; 205 206 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 207 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 208 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 209 210 ASSERT_EQ(0, __system_property_find("property1")); 211 ASSERT_EQ(0, __system_property_get("property1", prop_value)); 212 213 ASSERT_EQ(-1, __system_property_add("name", PROP_NAME_MAX, "value", 5)); 214 ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX)); 215 ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX)); 216} 217 218TEST(properties, serial) { 219 LocalPropertyTestState pa; 220 ASSERT_TRUE(pa.valid); 221 const prop_info *pi; 222 unsigned int serial; 223 224 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 225 ASSERT_NE((const prop_info *)NULL, pi = __system_property_find("property")); 226 serial = __system_property_serial(pi); 227 ASSERT_EQ(0, __system_property_update((prop_info *)pi, "value2", 6)); 228 ASSERT_NE(serial, __system_property_serial(pi)); 229} 230 231static void *PropertyWaitHelperFn(void *arg) 232{ 233 int *flag = (int *)arg; 234 prop_info *pi; 235 pi = (prop_info *)__system_property_find("property"); 236 usleep(100000); 237 238 *flag = 1; 239 __system_property_update(pi, "value3", 6); 240 241 return NULL; 242} 243 244TEST(properties, wait) { 245 LocalPropertyTestState pa; 246 ASSERT_TRUE(pa.valid); 247 unsigned int serial; 248 prop_info *pi; 249 pthread_t t; 250 int flag = 0; 251 252 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 253 serial = __system_property_wait_any(0); 254 pi = (prop_info *)__system_property_find("property"); 255 ASSERT_NE((prop_info *)NULL, pi); 256 __system_property_update(pi, "value2", 6); 257 serial = __system_property_wait_any(serial); 258 259 ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag)); 260 ASSERT_EQ(flag, 0); 261 serial = __system_property_wait_any(serial); 262 ASSERT_EQ(flag, 1); 263 264 void* result; 265 ASSERT_EQ(0, pthread_join(t, &result)); 266} 267 268class KilledByFault { 269 public: 270 explicit KilledByFault() {}; 271 bool operator()(int exit_status) const; 272}; 273 274bool KilledByFault::operator()(int exit_status) const { 275 return WIFSIGNALED(exit_status) && 276 (WTERMSIG(exit_status) == SIGSEGV || 277 WTERMSIG(exit_status) == SIGBUS || 278 WTERMSIG(exit_status) == SIGABRT); 279} 280 281TEST(properties_DeathTest, read_only) { 282 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 283 ASSERT_EXIT(__system_property_add("property", 8, "value", 5), 284 KilledByFault(), ""); 285} 286#endif 287