system_properties_test.cpp revision b27e200ad6170ba3163f5ae6ba581bdaabb2e696
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 20#if __BIONIC__ 21 22#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 23#include <sys/_system_properties.h> 24 25extern void *__system_property_area__; 26 27struct LocalPropertyTestState { 28 LocalPropertyTestState() { 29 old_pa = __system_property_area__; 30 pa = malloc(PA_SIZE); 31 __system_property_area_init(pa); 32 } 33 34 ~LocalPropertyTestState() { 35 __system_property_area__ = old_pa; 36 free(pa); 37 } 38private: 39 void *pa; 40 void *old_pa; 41}; 42 43TEST(properties, add) { 44 LocalPropertyTestState pa; 45 46 char propvalue[PROP_VALUE_MAX]; 47 48 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 49 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 50 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 51 52 ASSERT_EQ(6, __system_property_get("property", propvalue)); 53 ASSERT_STREQ(propvalue, "value1"); 54 55 ASSERT_EQ(6, __system_property_get("other_property", propvalue)); 56 ASSERT_STREQ(propvalue, "value2"); 57 58 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 59 ASSERT_STREQ(propvalue, "value3"); 60} 61 62TEST(properties, update) { 63 LocalPropertyTestState pa; 64 65 char propvalue[PROP_VALUE_MAX]; 66 prop_info *pi; 67 68 ASSERT_EQ(0, __system_property_add("property", 8, "oldvalue1", 9)); 69 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 70 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 71 72 pi = (prop_info *)__system_property_find("property"); 73 ASSERT_NE((prop_info *)NULL, pi); 74 __system_property_update(pi, "value4", 6); 75 76 pi = (prop_info *)__system_property_find("other_property"); 77 ASSERT_NE((prop_info *)NULL, pi); 78 __system_property_update(pi, "newvalue5", 9); 79 80 pi = (prop_info *)__system_property_find("property_other"); 81 ASSERT_NE((prop_info *)NULL, pi); 82 __system_property_update(pi, "value6", 6); 83 84 ASSERT_EQ(6, __system_property_get("property", propvalue)); 85 ASSERT_STREQ(propvalue, "value4"); 86 87 ASSERT_EQ(9, __system_property_get("other_property", propvalue)); 88 ASSERT_STREQ(propvalue, "newvalue5"); 89 90 ASSERT_EQ(6, __system_property_get("property_other", propvalue)); 91 ASSERT_STREQ(propvalue, "value6"); 92} 93 94// 247 = max # of properties supported by current implementation 95// (this should never go down) 96TEST(properties, fill_247) { 97 LocalPropertyTestState pa; 98 char prop_name[PROP_NAME_MAX]; 99 char prop_value[PROP_VALUE_MAX]; 100 char prop_value_ret[PROP_VALUE_MAX]; 101 int ret; 102 103 for (int i = 0; i < 247; i++) { 104 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i); 105 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 106 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i); 107 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 108 prop_name[PROP_NAME_MAX - 1] = 0; 109 prop_value[PROP_VALUE_MAX - 1] = 0; 110 111 ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1)); 112 } 113 114 for (int i = 0; i < 247; i++) { 115 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i); 116 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret); 117 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i); 118 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret); 119 prop_name[PROP_NAME_MAX - 1] = 0; 120 prop_value[PROP_VALUE_MAX - 1] = 0; 121 memset(prop_value_ret, '\0', PROP_VALUE_MAX); 122 123 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret)); 124 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX)); 125 } 126} 127 128TEST(properties, find_nth) { 129 LocalPropertyTestState pa; 130 131 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 132 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 133 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 134 135 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(0)); 136 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(1)); 137 ASSERT_NE((const prop_info *)NULL, __system_property_find_nth(2)); 138 139 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(3)); 140 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(4)); 141 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(5)); 142 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(100)); 143 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(200)); 144 ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247)); 145} 146 147TEST(properties, errors) { 148 LocalPropertyTestState pa; 149 char prop_value[PROP_NAME_MAX]; 150 151 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 152 ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6)); 153 ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6)); 154 155 ASSERT_EQ(0, __system_property_find("property1")); 156 ASSERT_EQ(0, __system_property_get("property1", prop_value)); 157 158 ASSERT_EQ(-1, __system_property_add("name", PROP_NAME_MAX, "value", 5)); 159 ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX)); 160 ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX)); 161} 162 163TEST(properties, serial) { 164 LocalPropertyTestState pa; 165 const prop_info *pi; 166 unsigned int serial; 167 168 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 169 ASSERT_NE((const prop_info *)NULL, pi = __system_property_find("property")); 170 serial = __system_property_serial(pi); 171 ASSERT_EQ(0, __system_property_update((prop_info *)pi, "value2", 6)); 172 ASSERT_NE(serial, __system_property_serial(pi)); 173} 174 175static void *PropertyWaitHelperFn(void *arg) 176{ 177 int *flag = (int *)arg; 178 prop_info *pi; 179 pi = (prop_info *)__system_property_find("property"); 180 usleep(100000); 181 182 *flag = 1; 183 __system_property_update(pi, "value3", 6); 184 185 return NULL; 186} 187 188TEST(properties, wait) { 189 LocalPropertyTestState pa; 190 unsigned int serial; 191 prop_info *pi; 192 pthread_t t; 193 int flag = 0; 194 195 ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); 196 serial = __system_property_wait_any(0); 197 pi = (prop_info *)__system_property_find("property"); 198 ASSERT_NE((prop_info *)NULL, pi); 199 __system_property_update(pi, "value2", 6); 200 serial = __system_property_wait_any(serial); 201 202 ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag)); 203 ASSERT_EQ(flag, 0); 204 serial = __system_property_wait_any(serial); 205 ASSERT_EQ(flag, 1); 206 207 void* result; 208 ASSERT_EQ(0, pthread_join(t, &result)); 209} 210 211class KilledByFault { 212 public: 213 explicit KilledByFault() {}; 214 bool operator()(int exit_status) const; 215}; 216 217bool KilledByFault::operator()(int exit_status) const { 218 return WIFSIGNALED(exit_status) && 219 (WTERMSIG(exit_status) == SIGSEGV || 220 WTERMSIG(exit_status) == SIGBUS || 221 WTERMSIG(exit_status) == SIGABRT); 222} 223 224TEST(properties_DeathTest, read_only) { 225 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 226 ASSERT_EXIT(__system_property_add("property", 8, "value", 5), 227 KilledByFault(), ""); 228} 229#endif 230