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