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 
     24 #include <string>
     25 #include <thread>
     26 
     27 #include <android-base/test_utils.h>
     28 
     29 using namespace std::literals;
     30 
     31 #if defined(__BIONIC__)
     32 
     33 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     34 #include <sys/_system_properties.h>
     35 
     36 #include <system_properties/system_properties.h>
     37 
     38 class SystemPropertiesTest : public SystemProperties {
     39  public:
     40   SystemPropertiesTest() : SystemProperties(false) {
     41     valid_ = AreaInit(dir_.path, nullptr);
     42   }
     43   ~SystemPropertiesTest() {
     44     if (valid_) {
     45       contexts_->FreeAndUnmap();
     46     }
     47   }
     48 
     49   bool valid() const {
     50     return valid_;
     51   }
     52 
     53  private:
     54   TemporaryDir dir_;
     55   bool valid_;
     56 };
     57 
     58 static void foreach_test_callback(const prop_info *pi, void* cookie) {
     59     size_t *count = static_cast<size_t *>(cookie);
     60 
     61     ASSERT_TRUE(pi != nullptr);
     62     (*count)++;
     63 }
     64 
     65 static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
     66     bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
     67 
     68     char name[PROP_NAME_MAX];
     69     char value[PROP_VALUE_MAX];
     70 
     71     __system_property_read(pi, name, value);
     72 
     73     int name_i, name_j, name_k;
     74     int value_i, value_j, value_k;
     75     ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
     76     ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
     77     ASSERT_EQ(name_i, value_i);
     78     ASSERT_GE(name_i, 0);
     79     ASSERT_LT(name_i, 8);
     80     ASSERT_EQ(name_j, value_j);
     81     ASSERT_GE(name_j, 0);
     82     ASSERT_LT(name_j, 8);
     83     ASSERT_EQ(name_k, value_k);
     84     ASSERT_GE(name_k, 0);
     85     ASSERT_LT(name_k, 8);
     86 
     87     ok[name_i][name_j][name_k] = true;
     88 }
     89 
     90 #endif // __BIONIC__
     91 
     92 TEST(properties, __system_property_add) {
     93 #if defined(__BIONIC__)
     94     SystemPropertiesTest system_properties;
     95     ASSERT_TRUE(system_properties.valid());
     96 
     97     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
     98     ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
     99     ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
    100 
    101     // check that there is no limit on property name length
    102     char name[PROP_NAME_MAX + 11];
    103     name[0] = 'p';
    104     for (size_t i = 1; i < sizeof(name); i++) {
    105       name[i] = 'x';
    106     }
    107 
    108     name[sizeof(name)-1] = '\0';
    109     ASSERT_EQ(0, system_properties.Add(name, strlen(name), "value", 5));
    110 
    111     char propvalue[PROP_VALUE_MAX];
    112     ASSERT_EQ(6, system_properties.Get("property", propvalue));
    113     ASSERT_STREQ(propvalue, "value1");
    114 
    115     ASSERT_EQ(6, system_properties.Get("other_property", propvalue));
    116     ASSERT_STREQ(propvalue, "value2");
    117 
    118     ASSERT_EQ(6, system_properties.Get("property_other", propvalue));
    119     ASSERT_STREQ(propvalue, "value3");
    120 
    121     ASSERT_EQ(5, system_properties.Get(name, propvalue));
    122     ASSERT_STREQ(propvalue, "value");
    123 #else // __BIONIC__
    124     GTEST_LOG_(INFO) << "This test does nothing.\n";
    125 #endif // __BIONIC__
    126 }
    127 
    128 TEST(properties, __system_property_update) {
    129 #if defined(__BIONIC__)
    130     SystemPropertiesTest system_properties;
    131     ASSERT_TRUE(system_properties.valid());
    132 
    133     ASSERT_EQ(0, system_properties.Add("property", 8, "oldvalue1", 9));
    134     ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
    135     ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
    136 
    137     const prop_info* pi = system_properties.Find("property");
    138     ASSERT_TRUE(pi != nullptr);
    139     system_properties.Update(const_cast<prop_info*>(pi), "value4", 6);
    140 
    141     pi = system_properties.Find("other_property");
    142     ASSERT_TRUE(pi != nullptr);
    143     system_properties.Update(const_cast<prop_info*>(pi), "newvalue5", 9);
    144 
    145     pi = system_properties.Find("property_other");
    146     ASSERT_TRUE(pi != nullptr);
    147     system_properties.Update(const_cast<prop_info*>(pi), "value6", 6);
    148 
    149     char propvalue[PROP_VALUE_MAX];
    150     ASSERT_EQ(6, system_properties.Get("property", propvalue));
    151     ASSERT_STREQ(propvalue, "value4");
    152 
    153     ASSERT_EQ(9, system_properties.Get("other_property", propvalue));
    154     ASSERT_STREQ(propvalue, "newvalue5");
    155 
    156     ASSERT_EQ(6, system_properties.Get("property_other", propvalue));
    157     ASSERT_STREQ(propvalue, "value6");
    158 #else // __BIONIC__
    159     GTEST_LOG_(INFO) << "This test does nothing.\n";
    160 #endif // __BIONIC__
    161 }
    162 
    163 TEST(properties, fill) {
    164 #if defined(__BIONIC__)
    165     SystemPropertiesTest system_properties;
    166     ASSERT_TRUE(system_properties.valid());
    167 
    168     char prop_name[PROP_NAME_MAX];
    169     char prop_value[PROP_VALUE_MAX];
    170     char prop_value_ret[PROP_VALUE_MAX];
    171     int count = 0;
    172     int ret;
    173 
    174     while (true) {
    175         ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", count);
    176         memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
    177         ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", count);
    178         memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
    179         prop_name[PROP_NAME_MAX - 1] = 0;
    180         prop_value[PROP_VALUE_MAX - 1] = 0;
    181 
    182         ret = system_properties.Add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1);
    183         if (ret < 0)
    184             break;
    185 
    186         count++;
    187     }
    188 
    189     // For historical reasons at least 247 properties must be supported
    190     ASSERT_GE(count, 247);
    191 
    192     for (int i = 0; i < count; i++) {
    193         ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i);
    194         memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
    195         ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i);
    196         memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
    197         prop_name[PROP_NAME_MAX - 1] = 0;
    198         prop_value[PROP_VALUE_MAX - 1] = 0;
    199         memset(prop_value_ret, '\0', PROP_VALUE_MAX);
    200 
    201         ASSERT_EQ(PROP_VALUE_MAX - 1, system_properties.Get(prop_name, prop_value_ret));
    202         ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
    203     }
    204 #else // __BIONIC__
    205     GTEST_LOG_(INFO) << "This test does nothing.\n";
    206 #endif // __BIONIC__
    207 }
    208 
    209 TEST(properties, __system_property_foreach) {
    210 #if defined(__BIONIC__)
    211     SystemPropertiesTest system_properties;
    212     ASSERT_TRUE(system_properties.valid());
    213 
    214     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
    215     ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
    216     ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
    217 
    218     size_t count = 0;
    219     ASSERT_EQ(0, system_properties.Foreach(foreach_test_callback, &count));
    220     ASSERT_EQ(3U, count);
    221 #else // __BIONIC__
    222     GTEST_LOG_(INFO) << "This test does nothing.\n";
    223 #endif // __BIONIC__
    224 }
    225 
    226 TEST(properties, __system_property_find_nth) {
    227 #if defined(__BIONIC__)
    228     SystemPropertiesTest system_properties;
    229     ASSERT_TRUE(system_properties.valid());
    230 
    231     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
    232     ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
    233     ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
    234 
    235     char name[PROP_NAME_MAX];
    236     char value[PROP_VALUE_MAX];
    237     EXPECT_EQ(6, system_properties.Read(system_properties.FindNth(0), name, value));
    238     EXPECT_STREQ("property", name);
    239     EXPECT_STREQ("value1", value);
    240     EXPECT_EQ(6, system_properties.Read(system_properties.FindNth(1), name, value));
    241     EXPECT_STREQ("other_property", name);
    242     EXPECT_STREQ("value2", value);
    243     EXPECT_EQ(6, system_properties.Read(system_properties.FindNth(2), name, value));
    244     EXPECT_STREQ("property_other", name);
    245     EXPECT_STREQ("value3", value);
    246 
    247     for (unsigned i = 3; i < 1024; ++i) {
    248       ASSERT_TRUE(system_properties.FindNth(i) == nullptr);
    249     }
    250 #else // __BIONIC__
    251     GTEST_LOG_(INFO) << "This test does nothing.\n";
    252 #endif // __BIONIC__
    253 }
    254 
    255 TEST(properties, fill_hierarchical) {
    256 #if defined(__BIONIC__)
    257     SystemPropertiesTest system_properties;
    258     ASSERT_TRUE(system_properties.valid());
    259 
    260     char prop_name[PROP_NAME_MAX];
    261     char prop_value[PROP_VALUE_MAX];
    262     char prop_value_ret[PROP_VALUE_MAX];
    263     int ret;
    264 
    265     for (int i = 0; i < 8; i++) {
    266         for (int j = 0; j < 8; j++) {
    267             for (int k = 0; k < 8; k++) {
    268                 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
    269                 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
    270                 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
    271                 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
    272                 prop_name[PROP_NAME_MAX - 1] = 0;
    273                 prop_value[PROP_VALUE_MAX - 1] = 0;
    274 
    275                 ASSERT_EQ(0, system_properties.Add(
    276                     prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
    277             }
    278         }
    279     }
    280 
    281     for (int i = 0; i < 8; i++) {
    282         for (int j = 0; j < 8; j++) {
    283             for (int k = 0; k < 8; k++) {
    284                 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
    285                 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
    286                 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
    287                 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
    288                 prop_name[PROP_NAME_MAX - 1] = 0;
    289                 prop_value[PROP_VALUE_MAX - 1] = 0;
    290                 memset(prop_value_ret, '\0', PROP_VALUE_MAX);
    291 
    292                 ASSERT_EQ(PROP_VALUE_MAX - 1, system_properties.Get(prop_name, prop_value_ret));
    293                 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
    294             }
    295         }
    296     }
    297 
    298     bool ok[8][8][8];
    299     memset(ok, 0, sizeof(ok));
    300     system_properties.Foreach(hierarchical_test_callback, ok);
    301 
    302     for (int i = 0; i < 8; i++) {
    303         for (int j = 0; j < 8; j++) {
    304             for (int k = 0; k < 8; k++) {
    305                 ASSERT_TRUE(ok[i][j][k]);
    306             }
    307         }
    308     }
    309 #else // __BIONIC__
    310     GTEST_LOG_(INFO) << "This test does nothing.\n";
    311 #endif // __BIONIC__
    312 }
    313 
    314 TEST(properties, errors) {
    315 #if defined(__BIONIC__)
    316     SystemPropertiesTest system_properties;
    317     ASSERT_TRUE(system_properties.valid());
    318 
    319     char prop_value[PROP_NAME_MAX];
    320 
    321     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
    322     ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
    323     ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
    324 
    325     ASSERT_EQ(0, system_properties.Find("property1"));
    326     ASSERT_EQ(0, system_properties.Get("property1", prop_value));
    327 
    328     ASSERT_EQ(-1, system_properties.Add("name", 4, "value", PROP_VALUE_MAX));
    329     ASSERT_EQ(-1, system_properties.Update(NULL, "value", PROP_VALUE_MAX));
    330 #else // __BIONIC__
    331     GTEST_LOG_(INFO) << "This test does nothing.\n";
    332 #endif // __BIONIC__
    333 }
    334 
    335 TEST(properties, __system_property_serial) {
    336 #if defined(__BIONIC__)
    337     SystemPropertiesTest system_properties;
    338     ASSERT_TRUE(system_properties.valid());
    339 
    340     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
    341     const prop_info* pi = system_properties.Find("property");
    342     ASSERT_TRUE(pi != nullptr);
    343     unsigned serial = system_properties.Serial(pi);
    344     ASSERT_EQ(0, system_properties.Update(const_cast<prop_info*>(pi), "value2", 6));
    345     ASSERT_NE(serial, system_properties.Serial(pi));
    346 #else // __BIONIC__
    347     GTEST_LOG_(INFO) << "This test does nothing.\n";
    348 #endif // __BIONIC__
    349 }
    350 
    351 TEST(properties, __system_property_wait_any) {
    352 #if defined(__BIONIC__)
    353     SystemPropertiesTest system_properties;
    354     ASSERT_TRUE(system_properties.valid());
    355 
    356     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
    357     unsigned serial = system_properties.WaitAny(0);
    358 
    359     prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
    360     ASSERT_TRUE(pi != nullptr);
    361     system_properties.Update(pi, "value2", 6);
    362     serial = system_properties.WaitAny(serial);
    363 
    364     int flag = 0;
    365     std::thread thread([&system_properties, &flag]() {
    366         prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
    367         usleep(100000);
    368 
    369         flag = 1;
    370         system_properties.Update(pi, "value3", 6);
    371     });
    372     ASSERT_EQ(flag, 0);
    373     serial = system_properties.WaitAny(serial);
    374     ASSERT_EQ(flag, 1);
    375 
    376     thread.join();
    377 #else // __BIONIC__
    378     GTEST_LOG_(INFO) << "This test does nothing.\n";
    379 #endif // __BIONIC__
    380 }
    381 
    382 TEST(properties, __system_property_wait) {
    383 #if defined(__BIONIC__)
    384     SystemPropertiesTest system_properties;
    385     ASSERT_TRUE(system_properties.valid());
    386 
    387     ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
    388 
    389     prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
    390     ASSERT_TRUE(pi != nullptr);
    391 
    392     unsigned serial = system_properties.Serial(pi);
    393 
    394     std::thread thread([&system_properties]() {
    395         prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
    396         ASSERT_TRUE(pi != nullptr);
    397 
    398         system_properties.Update(pi, "value2", 6);
    399     });
    400 
    401     uint32_t new_serial;
    402     system_properties.Wait(pi, serial, &new_serial, nullptr);
    403     ASSERT_GT(new_serial, serial);
    404 
    405     char value[PROP_VALUE_MAX];
    406     ASSERT_EQ(6, system_properties.Get("property", value));
    407     ASSERT_STREQ("value2", value);
    408 
    409     thread.join();
    410 #else // __BIONIC__
    411     GTEST_LOG_(INFO) << "This test does nothing.\n";
    412 #endif // __BIONIC__
    413 }
    414 
    415 class KilledByFault {
    416     public:
    417         explicit KilledByFault() {};
    418         bool operator()(int exit_status) const;
    419 };
    420 
    421 bool KilledByFault::operator()(int exit_status) const {
    422     return WIFSIGNALED(exit_status) &&
    423         (WTERMSIG(exit_status) == SIGSEGV ||
    424          WTERMSIG(exit_status) == SIGBUS ||
    425          WTERMSIG(exit_status) == SIGABRT);
    426 }
    427 
    428 class properties_DeathTest : public BionicDeathTest {};
    429 
    430 TEST_F(properties_DeathTest, read_only) {
    431 #if defined(__BIONIC__)
    432 
    433   // This test only makes sense if we're talking to the real system property service.
    434   struct stat sb;
    435   ASSERT_FALSE(stat(PROP_FILENAME, &sb) == -1 && errno == ENOENT);
    436 
    437   ASSERT_EXIT(__system_property_add("property", 8, "value", 5), KilledByFault(), "");
    438 #else // __BIONIC__
    439   GTEST_LOG_(INFO) << "This test does nothing.\n";
    440 #endif // __BIONIC__
    441 }
    442 
    443 TEST(properties, __system_property_extra_long_read_only) {
    444 #if defined(__BIONIC__)
    445   SystemPropertiesTest system_properties;
    446   ASSERT_TRUE(system_properties.valid());
    447 
    448   std::vector<std::pair<std::string, std::string>> short_properties = {
    449     { "ro.0char", std::string() },
    450     { "ro.50char", std::string(50, 'x') },
    451     { "ro.91char", std::string(91, 'x') },
    452   };
    453 
    454   std::vector<std::pair<std::string, std::string>> long_properties = {
    455     { "ro.92char", std::string(92, 'x') },
    456     { "ro.93char", std::string(93, 'x') },
    457     { "ro.1000char", std::string(1000, 'x') },
    458   };
    459 
    460   for (const auto& property : short_properties) {
    461     const std::string& name = property.first;
    462     const std::string& value = property.second;
    463     ASSERT_EQ(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
    464   }
    465 
    466   for (const auto& property : long_properties) {
    467     const std::string& name = property.first;
    468     const std::string& value = property.second;
    469     ASSERT_EQ(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
    470   }
    471 
    472   auto check_with_legacy_read = [&system_properties](const std::string& name,
    473                                                      const std::string& expected_value) {
    474     char value[PROP_VALUE_MAX];
    475     EXPECT_EQ(static_cast<int>(expected_value.size()), system_properties.Get(name.c_str(), value))
    476         << name;
    477     EXPECT_EQ(expected_value, value) << name;
    478   };
    479 
    480   auto check_with_read_callback = [&system_properties](const std::string& name,
    481                                                        const std::string& expected_value) {
    482     const prop_info* pi = system_properties.Find(name.c_str());
    483     ASSERT_NE(nullptr, pi);
    484     std::string value;
    485     system_properties.ReadCallback(pi,
    486                                    [](void* cookie, const char*, const char* value, uint32_t) {
    487                                      auto* out_value = reinterpret_cast<std::string*>(cookie);
    488                                      *out_value = value;
    489                                    },
    490                                    &value);
    491     EXPECT_EQ(expected_value, value) << name;
    492   };
    493 
    494   for (const auto& property : short_properties) {
    495     const std::string& name = property.first;
    496     const std::string& value = property.second;
    497     check_with_legacy_read(name, value);
    498     check_with_read_callback(name, value);
    499   }
    500 
    501   constexpr static const char* kExtraLongLegacyError =
    502       "Must use __system_property_read_callback() to read";
    503   for (const auto& property : long_properties) {
    504     const std::string& name = property.first;
    505     const std::string& value = property.second;
    506     check_with_legacy_read(name, kExtraLongLegacyError);
    507     check_with_read_callback(name, value);
    508   }
    509 
    510 #else   // __BIONIC__
    511   GTEST_LOG_(INFO) << "This test does nothing.\n";
    512 #endif  // __BIONIC__
    513 }
    514 
    515 // pa_size is 128 * 1024 currently, if a property is longer then we expect it to fail gracefully.
    516 TEST(properties, __system_property_extra_long_read_only_too_long) {
    517 #if defined(__BIONIC__)
    518   SystemPropertiesTest system_properties;
    519   ASSERT_TRUE(system_properties.valid());
    520 
    521   auto name = "ro.super_long_property"s;
    522   auto value = std::string(128 * 1024 + 1, 'x');
    523   ASSERT_NE(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
    524 
    525 #else   // __BIONIC__
    526   GTEST_LOG_(INFO) << "This test does nothing.\n";
    527 #endif  // __BIONIC__
    528 }
    529