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 <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 
     27 extern void *__system_property_area__;
     28 
     29 struct 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     }
     59 public:
     60     bool valid;
     61 private:
     62     std::string pa_dirname;
     63     std::string pa_filename;
     64     void *old_pa;
     65 };
     66 
     67 TEST(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 
     87 TEST(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 
    120 TEST(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 
    161 static 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 
    168 TEST(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 
    181 TEST(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 
    201 static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
    202     bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
    203 
    204     char name[PROP_NAME_MAX];
    205     char value[PROP_VALUE_MAX];
    206 
    207     __system_property_read(pi, name, value);
    208 
    209     int name_i, name_j, name_k;
    210     int value_i, value_j, value_k;
    211     ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
    212     ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
    213     ASSERT_EQ(name_i, value_i);
    214     ASSERT_GE(name_i, 0);
    215     ASSERT_LT(name_i, 8);
    216     ASSERT_EQ(name_j, value_j);
    217     ASSERT_GE(name_j, 0);
    218     ASSERT_LT(name_j, 8);
    219     ASSERT_EQ(name_k, value_k);
    220     ASSERT_GE(name_k, 0);
    221     ASSERT_LT(name_k, 8);
    222 
    223     ok[name_i][name_j][name_k] = true;
    224 }
    225 
    226 TEST(properties, fill_hierarchical) {
    227     LocalPropertyTestState pa;
    228     ASSERT_TRUE(pa.valid);
    229     char prop_name[PROP_NAME_MAX];
    230     char prop_value[PROP_VALUE_MAX];
    231     char prop_value_ret[PROP_VALUE_MAX];
    232     int ret;
    233 
    234     for (int i = 0; i < 8; i++) {
    235         for (int j = 0; j < 8; j++) {
    236             for (int k = 0; k < 8; k++) {
    237                 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
    238                 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
    239                 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
    240                 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
    241                 prop_name[PROP_NAME_MAX - 1] = 0;
    242                 prop_value[PROP_VALUE_MAX - 1] = 0;
    243 
    244                 ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
    245             }
    246         }
    247     }
    248 
    249     for (int i = 0; i < 8; i++) {
    250         for (int j = 0; j < 8; j++) {
    251             for (int k = 0; k < 8; k++) {
    252                 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
    253                 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
    254                 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
    255                 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
    256                 prop_name[PROP_NAME_MAX - 1] = 0;
    257                 prop_value[PROP_VALUE_MAX - 1] = 0;
    258                 memset(prop_value_ret, '\0', PROP_VALUE_MAX);
    259 
    260                 ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret));
    261                 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
    262             }
    263         }
    264     }
    265 
    266     bool ok[8][8][8];
    267     memset(ok, 0, sizeof(ok));
    268     __system_property_foreach(hierarchical_test_callback, ok);
    269 
    270     for (int i = 0; i < 8; i++) {
    271         for (int j = 0; j < 8; j++) {
    272             for (int k = 0; k < 8; k++) {
    273                 ASSERT_TRUE(ok[i][j][k]);
    274             }
    275         }
    276     }
    277 }
    278 
    279 TEST(properties, errors) {
    280     LocalPropertyTestState pa;
    281     ASSERT_TRUE(pa.valid);
    282     char prop_value[PROP_NAME_MAX];
    283 
    284     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
    285     ASSERT_EQ(0, __system_property_add("other_property", 14, "value2", 6));
    286     ASSERT_EQ(0, __system_property_add("property_other", 14, "value3", 6));
    287 
    288     ASSERT_EQ(0, __system_property_find("property1"));
    289     ASSERT_EQ(0, __system_property_get("property1", prop_value));
    290 
    291     ASSERT_EQ(-1, __system_property_add("name", PROP_NAME_MAX, "value", 5));
    292     ASSERT_EQ(-1, __system_property_add("name", 4, "value", PROP_VALUE_MAX));
    293     ASSERT_EQ(-1, __system_property_update(NULL, "value", PROP_VALUE_MAX));
    294 }
    295 
    296 TEST(properties, serial) {
    297     LocalPropertyTestState pa;
    298     ASSERT_TRUE(pa.valid);
    299     const prop_info *pi;
    300     unsigned int serial;
    301 
    302     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
    303     ASSERT_NE((const prop_info *)NULL, pi = __system_property_find("property"));
    304     serial = __system_property_serial(pi);
    305     ASSERT_EQ(0, __system_property_update((prop_info *)pi, "value2", 6));
    306     ASSERT_NE(serial, __system_property_serial(pi));
    307 }
    308 
    309 static void *PropertyWaitHelperFn(void *arg)
    310 {
    311     int *flag = (int *)arg;
    312     prop_info *pi;
    313     pi = (prop_info *)__system_property_find("property");
    314     usleep(100000);
    315 
    316     *flag = 1;
    317     __system_property_update(pi, "value3", 6);
    318 
    319     return NULL;
    320 }
    321 
    322 TEST(properties, wait) {
    323     LocalPropertyTestState pa;
    324     ASSERT_TRUE(pa.valid);
    325     unsigned int serial;
    326     prop_info *pi;
    327     pthread_t t;
    328     int flag = 0;
    329 
    330     ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6));
    331     serial = __system_property_wait_any(0);
    332     pi = (prop_info *)__system_property_find("property");
    333     ASSERT_NE((prop_info *)NULL, pi);
    334     __system_property_update(pi, "value2", 6);
    335     serial = __system_property_wait_any(serial);
    336 
    337     ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag));
    338     ASSERT_EQ(flag, 0);
    339     serial = __system_property_wait_any(serial);
    340     ASSERT_EQ(flag, 1);
    341 
    342     void* result;
    343     ASSERT_EQ(0, pthread_join(t, &result));
    344 }
    345 
    346 class KilledByFault {
    347     public:
    348         explicit KilledByFault() {};
    349         bool operator()(int exit_status) const;
    350 };
    351 
    352 bool KilledByFault::operator()(int exit_status) const {
    353     return WIFSIGNALED(exit_status) &&
    354         (WTERMSIG(exit_status) == SIGSEGV ||
    355          WTERMSIG(exit_status) == SIGBUS ||
    356          WTERMSIG(exit_status) == SIGABRT);
    357 }
    358 
    359 TEST(properties_DeathTest, read_only) {
    360       ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    361       ASSERT_EXIT(__system_property_add("property", 8, "value", 5),
    362                   KilledByFault(), "");
    363 }
    364 #endif
    365