OSDN Git Service

Merge "Fix greylist exception to account for linked namespaces" am: 6e528631d1 am...
[android-x86/bionic.git] / tests / system_properties_test.cpp
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
24 #include <string>
25 #include <thread>
26
27 #if defined(__BIONIC__)
28
29 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
30 #include <sys/_system_properties.h>
31
32 extern void *__system_property_area__;
33
34 struct LocalPropertyTestState {
35     LocalPropertyTestState() : valid(false) {
36         const char* ANDROID_DATA = getenv("ANDROID_DATA");
37         char dir_template[PATH_MAX];
38         snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", ANDROID_DATA);
39         char* dirname = mkdtemp(dir_template);
40         if (!dirname) {
41             fprintf(stderr, "making temp file for test state failed (is %s writable?): %s",
42                     dir_template, strerror(errno));
43             return;
44         }
45
46         pa_dirname = dirname;
47         pa_filename = pa_dirname + "/__properties__";
48
49         __system_property_set_filename(pa_filename.c_str());
50         __system_property_area_init();
51         valid = true;
52     }
53
54     ~LocalPropertyTestState() {
55         if (!valid) {
56             return;
57         }
58
59         __system_property_set_filename(PROP_FILENAME);
60         __system_properties_init();
61         unlink(pa_filename.c_str());
62         rmdir(pa_dirname.c_str());
63     }
64 public:
65     bool valid;
66 private:
67     std::string pa_dirname;
68     std::string pa_filename;
69 };
70
71 static void foreach_test_callback(const prop_info *pi, void* cookie) {
72     size_t *count = static_cast<size_t *>(cookie);
73
74     ASSERT_TRUE(pi != nullptr);
75     (*count)++;
76 }
77
78 static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
79     bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
80
81     char name[PROP_NAME_MAX];
82     char value[PROP_VALUE_MAX];
83
84     __system_property_read(pi, name, value);
85
86     int name_i, name_j, name_k;
87     int value_i, value_j, value_k;
88     ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
89     ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
90     ASSERT_EQ(name_i, value_i);
91     ASSERT_GE(name_i, 0);
92     ASSERT_LT(name_i, 8);
93     ASSERT_EQ(name_j, value_j);
94     ASSERT_GE(name_j, 0);
95     ASSERT_LT(name_j, 8);
96     ASSERT_EQ(name_k, value_k);
97     ASSERT_GE(name_k, 0);
98     ASSERT_LT(name_k, 8);
99
100     ok[name_i][name_j][name_k] = true;
101 }
102
103 static void* PropertyWaitHelperFn(void* arg) {
104     int* flag = static_cast<int*>(arg);
105     prop_info* pi = const_cast<prop_info*>(__system_property_find("property"));
106     usleep(100000);
107
108     *flag = 1;
109     __system_property_update(pi, "value3", 6);
110
111     return nullptr;
112 }
113
114 #endif // __BIONIC__
115
116 TEST(properties, __system_property_add) {
117 #if defined(__BIONIC__)
118     LocalPropertyTestState pa;
119     ASSERT_TRUE(pa.valid);
120
121     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
122     ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6));
123     ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6));
124
125     // check that there is no limit on property name length
126     char name[PROP_NAME_MAX + 11];
127     name[0] = 'p';
128     for (size_t i = 1; i < sizeof(name); i++) {
129       name[i] = 'x';
130     }
131
132     name[sizeof(name)-1] = '\0';
133     ASSERT_EQ(0, __system_property_add(name, strlen(name), "value", 5));
134
135     char propvalue[PROP_VALUE_MAX];
136     ASSERT_EQ(6, __system_property_get("property", propvalue));
137     ASSERT_STREQ(propvalue, "value1");
138
139     ASSERT_EQ(6, __system_property_get("other_property", propvalue));
140     ASSERT_STREQ(propvalue, "value2");
141
142     ASSERT_EQ(6, __system_property_get("property_other", propvalue));
143     ASSERT_STREQ(propvalue, "value3");
144
145     ASSERT_EQ(5, __system_property_get(name, propvalue));
146     ASSERT_STREQ(propvalue, "value");
147 #else // __BIONIC__
148     GTEST_LOG_(INFO) << "This test does nothing.\n";
149 #endif // __BIONIC__
150 }
151
152 TEST(properties, __system_property_update) {
153 #if defined(__BIONIC__)
154     LocalPropertyTestState pa;
155     ASSERT_TRUE(pa.valid);
156
157     ASSERT_EQ(0, __system_property_add("property", 8, "oldvalue1", 9));
158     ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6));
159     ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6));
160
161     const prop_info* pi = __system_property_find("property");
162     ASSERT_TRUE(pi != nullptr);
163     __system_property_update(const_cast<prop_info*>(pi), "value4", 6);
164
165     pi = __system_property_find("other_property");
166     ASSERT_TRUE(pi != nullptr);
167     __system_property_update(const_cast<prop_info*>(pi), "newvalue5", 9);
168
169     pi = __system_property_find("property_other");
170     ASSERT_TRUE(pi != nullptr);
171     __system_property_update(const_cast<prop_info*>(pi), "value6", 6);
172
173     char propvalue[PROP_VALUE_MAX];
174     ASSERT_EQ(6, __system_property_get("property", propvalue));
175     ASSERT_STREQ(propvalue, "value4");
176
177     ASSERT_EQ(9, __system_property_get("other_property", propvalue));
178     ASSERT_STREQ(propvalue, "newvalue5");
179
180     ASSERT_EQ(6, __system_property_get("property_other", propvalue));
181     ASSERT_STREQ(propvalue, "value6");
182 #else // __BIONIC__
183     GTEST_LOG_(INFO) << "This test does nothing.\n";
184 #endif // __BIONIC__
185 }
186
187 TEST(properties, fill) {
188 #if defined(__BIONIC__)
189     LocalPropertyTestState pa;
190     ASSERT_TRUE(pa.valid);
191     char prop_name[PROP_NAME_MAX];
192     char prop_value[PROP_VALUE_MAX];
193     char prop_value_ret[PROP_VALUE_MAX];
194     int count = 0;
195     int ret;
196
197     while (true) {
198         ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", count);
199         memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
200         ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", count);
201         memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
202         prop_name[PROP_NAME_MAX - 1] = 0;
203         prop_value[PROP_VALUE_MAX - 1] = 0;
204
205         ret = __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1);
206         if (ret < 0)
207             break;
208
209         count++;
210     }
211
212     // For historical reasons at least 247 properties must be supported
213     ASSERT_GE(count, 247);
214
215     for (int i = 0; i < count; i++) {
216         ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i);
217         memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
218         ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i);
219         memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
220         prop_name[PROP_NAME_MAX - 1] = 0;
221         prop_value[PROP_VALUE_MAX - 1] = 0;
222         memset(prop_value_ret, '\0', PROP_VALUE_MAX);
223
224         ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret));
225         ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
226     }
227 #else // __BIONIC__
228     GTEST_LOG_(INFO) << "This test does nothing.\n";
229 #endif // __BIONIC__
230 }
231
232 TEST(properties, __system_property_foreach) {
233 #if defined(__BIONIC__)
234     LocalPropertyTestState pa;
235     ASSERT_TRUE(pa.valid);
236
237     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
238     ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6));
239     ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6));
240
241     size_t count = 0;
242     ASSERT_EQ(0, __system_property_foreach(foreach_test_callback, &count));
243     ASSERT_EQ(3U, count);
244 #else // __BIONIC__
245     GTEST_LOG_(INFO) << "This test does nothing.\n";
246 #endif // __BIONIC__
247 }
248
249 TEST(properties, __system_property_find_nth) {
250 #if defined(__BIONIC__)
251     LocalPropertyTestState pa;
252     ASSERT_TRUE(pa.valid);
253
254     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
255     ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6));
256     ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6));
257
258     // This method is no longer supported and should result in abort
259     ASSERT_EXIT(__system_property_find_nth(0), testing::KilledBySignal(SIGABRT),
260                 "__system_property_find_nth is not supported since Android O,"
261                 " please use __system_property_foreach instead.");
262 #else // __BIONIC__
263     GTEST_LOG_(INFO) << "This test does nothing.\n";
264 #endif // __BIONIC__
265 }
266
267 TEST(properties, fill_hierarchical) {
268 #if defined(__BIONIC__)
269     LocalPropertyTestState pa;
270     ASSERT_TRUE(pa.valid);
271     char prop_name[PROP_NAME_MAX];
272     char prop_value[PROP_VALUE_MAX];
273     char prop_value_ret[PROP_VALUE_MAX];
274     int ret;
275
276     for (int i = 0; i < 8; i++) {
277         for (int j = 0; j < 8; j++) {
278             for (int k = 0; k < 8; k++) {
279                 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
280                 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
281                 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
282                 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
283                 prop_name[PROP_NAME_MAX - 1] = 0;
284                 prop_value[PROP_VALUE_MAX - 1] = 0;
285
286                 ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
287             }
288         }
289     }
290
291     for (int i = 0; i < 8; i++) {
292         for (int j = 0; j < 8; j++) {
293             for (int k = 0; k < 8; k++) {
294                 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
295                 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
296                 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
297                 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
298                 prop_name[PROP_NAME_MAX - 1] = 0;
299                 prop_value[PROP_VALUE_MAX - 1] = 0;
300                 memset(prop_value_ret, '\0', PROP_VALUE_MAX);
301
302                 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret));
303                 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
304             }
305         }
306     }
307
308     bool ok[8][8][8];
309     memset(ok, 0, sizeof(ok));
310     __system_property_foreach(hierarchical_test_callback, ok);
311
312     for (int i = 0; i < 8; i++) {
313         for (int j = 0; j < 8; j++) {
314             for (int k = 0; k < 8; k++) {
315                 ASSERT_TRUE(ok[i][j][k]);
316             }
317         }
318     }
319 #else // __BIONIC__
320     GTEST_LOG_(INFO) << "This test does nothing.\n";
321 #endif // __BIONIC__
322 }
323
324 TEST(properties, errors) {
325 #if defined(__BIONIC__)
326     LocalPropertyTestState pa;
327     ASSERT_TRUE(pa.valid);
328     char prop_value[PROP_NAME_MAX];
329
330     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
331     ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6));
332     ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6));
333
334     ASSERT_EQ(0, __system_property_find("property1"));
335     ASSERT_EQ(0, __system_property_get("property1", prop_value));
336
337     ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX));
338     ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX));
339 #else // __BIONIC__
340     GTEST_LOG_(INFO) << "This test does nothing.\n";
341 #endif // __BIONIC__
342 }
343
344 TEST(properties, __system_property_serial) {
345 #if defined(__BIONIC__)
346     LocalPropertyTestState pa;
347     ASSERT_TRUE(pa.valid);
348
349     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
350     const prop_info* pi = __system_property_find("property");
351     ASSERT_TRUE(pi != nullptr);
352     unsigned serial = __system_property_serial(pi);
353     ASSERT_EQ(0, __system_property_update(const_cast<prop_info*>(pi), "value2", 6));
354     ASSERT_NE(serial, __system_property_serial(pi));
355 #else // __BIONIC__
356     GTEST_LOG_(INFO) << "This test does nothing.\n";
357 #endif // __BIONIC__
358 }
359
360 TEST(properties, __system_property_wait_any) {
361 #if defined(__BIONIC__)
362     LocalPropertyTestState pa;
363     ASSERT_TRUE(pa.valid);
364
365     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
366     unsigned serial = __system_property_wait_any(0);
367
368     prop_info* pi = const_cast<prop_info*>(__system_property_find("property"));
369     ASSERT_TRUE(pi != nullptr);
370     __system_property_update(pi, "value2", 6);
371     serial = __system_property_wait_any(serial);
372
373     int flag = 0;
374     pthread_t t;
375     ASSERT_EQ(0, pthread_create(&t, nullptr, PropertyWaitHelperFn, &flag));
376     ASSERT_EQ(flag, 0);
377     serial = __system_property_wait_any(serial);
378     ASSERT_EQ(flag, 1);
379
380     ASSERT_EQ(0, pthread_join(t, nullptr));
381 #else // __BIONIC__
382     GTEST_LOG_(INFO) << "This test does nothing.\n";
383 #endif // __BIONIC__
384 }
385
386 TEST(properties, __system_property_wait) {
387 #if defined(__BIONIC__)
388     LocalPropertyTestState pa;
389     ASSERT_TRUE(pa.valid);
390
391     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
392
393     prop_info* pi = const_cast<prop_info*>(__system_property_find("property"));
394     ASSERT_TRUE(pi != nullptr);
395
396     unsigned serial = __system_property_serial(pi);
397
398     std::thread thread([]() {
399         prop_info* pi = const_cast<prop_info*>(__system_property_find("property"));
400         ASSERT_TRUE(pi != nullptr);
401
402         __system_property_update(pi, "value2", 6);
403     });
404
405     uint32_t new_serial;
406     __system_property_wait(pi, serial, &new_serial, nullptr);
407     ASSERT_GT(new_serial, serial);
408
409     char value[PROP_VALUE_MAX];
410     ASSERT_EQ(6, __system_property_get("property", value));
411     ASSERT_STREQ("value2", value);
412
413     thread.join();
414 #else // __BIONIC__
415     GTEST_LOG_(INFO) << "This test does nothing.\n";
416 #endif // __BIONIC__
417 }
418
419 class KilledByFault {
420     public:
421         explicit KilledByFault() {};
422         bool operator()(int exit_status) const;
423 };
424
425 bool KilledByFault::operator()(int exit_status) const {
426     return WIFSIGNALED(exit_status) &&
427         (WTERMSIG(exit_status) == SIGSEGV ||
428          WTERMSIG(exit_status) == SIGBUS ||
429          WTERMSIG(exit_status) == SIGABRT);
430 }
431
432 class properties_DeathTest : public BionicDeathTest {};
433
434 TEST_F(properties_DeathTest, read_only) {
435 #if defined(__BIONIC__)
436
437   // This test only makes sense if we're talking to the real system property service.
438   struct stat sb;
439   ASSERT_FALSE(stat(PROP_FILENAME, &sb) == -1 && errno == ENOENT);
440
441   ASSERT_EXIT(__system_property_add("property", 8, "value", 5), KilledByFault(), "");
442 #else // __BIONIC__
443   GTEST_LOG_(INFO) << "This test does nothing.\n";
444 #endif // __BIONIC__
445 }