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 {
LocalPropertyTestStateLocalPropertyTestState33     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 
~LocalPropertyTestStateLocalPropertyTestState52     ~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 
foreach_test_callback(const prop_info * pi,void * cookie)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 
hierarchical_test_callback(const prop_info * pi,void * cookie)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 
PropertyWaitHelperFn(void * arg)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 
TEST(properties,add)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 
TEST(properties,update)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 
TEST(properties,fill)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 
TEST(properties,foreach)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 
TEST(properties,find_nth)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 
TEST(properties,fill_hierarchical)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 
TEST(properties,errors)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 
TEST(properties,serial)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 
TEST(properties,wait)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:
KilledByFault()387         explicit KilledByFault() {};
388         bool operator()(int exit_status) const;
389 };
390 
operator ()(int exit_status) const391 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 
TEST_F(properties_DeathTest,read_only)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