Home | History | Annotate | Download | only in tests
      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 {
     33     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 
     52     ~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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    387         explicit KilledByFault() {};
    388         bool operator()(int exit_status) const;
    389 };
    390 
    391 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 
    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