Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2014 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 #define LOG_TAG "Properties_test"
     18 
     19 #include <limits.h>
     20 
     21 #include <iostream>
     22 #include <sstream>
     23 #include <string>
     24 
     25 #include <android/log.h>
     26 #include <android-base/macros.h>
     27 #include <cutils/properties.h>
     28 #include <gtest/gtest.h>
     29 
     30 namespace android {
     31 
     32 #define STRINGIFY_INNER(x) #x
     33 #define STRINGIFY(x) STRINGIFY_INNER(x)
     34 #define ASSERT_OK(x) ASSERT_EQ(0, (x))
     35 #define EXPECT_OK(x) EXPECT_EQ(0, (x))
     36 
     37 #define PROPERTY_TEST_KEY "libcutils.test.key"
     38 #define PROPERTY_TEST_VALUE_DEFAULT "<<<default_value>>>"
     39 
     40 template <typename T>
     41 static std::string HexString(T value) {
     42     std::stringstream ss;
     43     ss << "0x" << std::hex << std::uppercase << value;
     44     return ss.str();
     45 }
     46 
     47 template <typename T>
     48 static ::testing::AssertionResult AssertEqualHex(const char *mExpr,
     49         const char *nExpr,
     50         T m,
     51         T n) {
     52     if (m == n) {
     53         return ::testing::AssertionSuccess();
     54     }
     55 
     56     return ::testing::AssertionFailure()
     57         << mExpr << " and " << nExpr << " (expected: " << HexString(m) <<
     58         ", actual: " << HexString(n) << ") are not equal";
     59 }
     60 
     61 class PropertiesTest : public testing::Test {
     62 public:
     63     PropertiesTest() : mValue() {}
     64 protected:
     65     virtual void SetUp() {
     66         EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
     67     }
     68 
     69     virtual void TearDown() {
     70         EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
     71     }
     72 
     73     char mValue[PROPERTY_VALUE_MAX];
     74 
     75     template <typename T>
     76     static std::string ToString(T value) {
     77         std::stringstream ss;
     78         ss << value;
     79 
     80         return ss.str();
     81     }
     82 
     83     // Return length of property read; value is written into mValue
     84     int SetAndGetProperty(const char* value, const char* defaultValue = PROPERTY_TEST_VALUE_DEFAULT) {
     85         EXPECT_OK(property_set(PROPERTY_TEST_KEY, value)) << "value: '" << value << "'";
     86         return property_get(PROPERTY_TEST_KEY, mValue, defaultValue);
     87     }
     88 
     89     void ResetValue(unsigned char c = 0xFF) {
     90         for (size_t i = 0; i < arraysize(mValue); ++i) {
     91             mValue[i] = (char) c;
     92         }
     93     }
     94 };
     95 
     96 TEST_F(PropertiesTest, SetString) {
     97 
     98     // Null key -> unsuccessful set
     99     {
    100         // Null key -> fails
    101         EXPECT_GT(0, property_set(/*key*/NULL, PROPERTY_TEST_VALUE_DEFAULT));
    102     }
    103 
    104     // Null value -> returns default value
    105     {
    106         // Null value -> OK , and it clears the value
    107         EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
    108         ResetValue();
    109 
    110         // Since the value is null, default value will be returned
    111         size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
    112         EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len);
    113         EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue);
    114     }
    115 
    116     // Trivial case => get returns what was set
    117     {
    118         size_t len = SetAndGetProperty("hello_world");
    119         EXPECT_EQ(strlen("hello_world"), len) << "hello_world key";
    120         EXPECT_STREQ("hello_world", mValue);
    121         ResetValue();
    122     }
    123 
    124     // Set to empty string => get returns default always
    125     {
    126         const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING";
    127         size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT);
    128         EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key";
    129         EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue);
    130         ResetValue();
    131     }
    132 
    133     // Set to max length => get returns what was set
    134     {
    135         std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a');
    136 
    137         int len = SetAndGetProperty(maxLengthString.c_str());
    138         EXPECT_EQ(PROPERTY_VALUE_MAX-1, len) << "max length key";
    139         EXPECT_STREQ(maxLengthString.c_str(), mValue);
    140         ResetValue();
    141     }
    142 
    143     // Set to max length + 1 => set fails
    144     {
    145         const char* VALID_TEST_VALUE = "VALID_VALUE";
    146         ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE));
    147 
    148         std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
    149 
    150         // Expect that the value set fails since it's too long
    151         EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str()));
    152         size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
    153 
    154         EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed";
    155         EXPECT_STREQ(VALID_TEST_VALUE, mValue);
    156         ResetValue();
    157     }
    158 }
    159 
    160 TEST_F(PropertiesTest, GetString) {
    161 
    162     // Try to use a default value that's too long => get truncates the value
    163     {
    164         ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
    165 
    166         std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a');
    167         std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
    168 
    169         // Expect that the value is truncated since it's too long (by 1)
    170         int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str());
    171         EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len);
    172         EXPECT_STREQ(maxLengthString.c_str(), mValue);
    173         ResetValue();
    174     }
    175 
    176     // Try to use a default value that's the max length => get succeeds
    177     {
    178         ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
    179 
    180         std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b');
    181 
    182         // Expect that the value matches maxLengthString
    183         int len = property_get(PROPERTY_TEST_KEY, mValue, maxLengthString.c_str());
    184         EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len);
    185         EXPECT_STREQ(maxLengthString.c_str(), mValue);
    186         ResetValue();
    187     }
    188 
    189     // Try to use a default value of length one => get succeeds
    190     {
    191         ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
    192 
    193         std::string oneCharString = std::string(1, 'c');
    194 
    195         // Expect that the value matches oneCharString
    196         int len = property_get(PROPERTY_TEST_KEY, mValue, oneCharString.c_str());
    197         EXPECT_EQ(1, len);
    198         EXPECT_STREQ(oneCharString.c_str(), mValue);
    199         ResetValue();
    200     }
    201 
    202     // Try to use a default value of length zero => get succeeds
    203     {
    204         ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
    205 
    206         std::string zeroCharString = std::string(0, 'd');
    207 
    208         // Expect that the value matches oneCharString
    209         int len = property_get(PROPERTY_TEST_KEY, mValue, zeroCharString.c_str());
    210         EXPECT_EQ(0, len);
    211         EXPECT_STREQ(zeroCharString.c_str(), mValue);
    212         ResetValue();
    213     }
    214 
    215     // Try to use a NULL default value => get returns 0
    216     {
    217         ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
    218 
    219         // Expect a return value of 0
    220         int len = property_get(PROPERTY_TEST_KEY, mValue, NULL);
    221         EXPECT_EQ(0, len);
    222         ResetValue();
    223     }
    224 }
    225 
    226 TEST_F(PropertiesTest, GetBool) {
    227     /**
    228      * TRUE
    229      */
    230     const char *valuesTrue[] = { "1", "true", "y", "yes", "on", };
    231     for (size_t i = 0; i < arraysize(valuesTrue); ++i) {
    232         ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i]));
    233         bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
    234         EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'";
    235     }
    236 
    237     /**
    238      * FALSE
    239      */
    240     const char *valuesFalse[] = { "0", "false", "n", "no", "off", };
    241     for (size_t i = 0; i < arraysize(valuesFalse); ++i) {
    242         ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i]));
    243         bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
    244         EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'";
    245     }
    246 
    247     /**
    248      * NEITHER
    249      */
    250     const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ",
    251             "+1", "  1  ", "  true", "  true  ", "  y  ", "  yes", "yes  ",
    252             "+0", "-0", "00", "  00  ", "  false", "false  ",
    253     };
    254     for (size_t i = 0; i < arraysize(valuesNeither); ++i) {
    255         ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesNeither[i]));
    256 
    257         // The default value should always be used
    258         bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
    259         EXPECT_TRUE(val) << "Property should've been NEITHER (true) for string value: '" << valuesNeither[i] << "'";
    260 
    261         val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
    262         EXPECT_FALSE(val) << "Property should've been NEITHER (false) for string value: '" << valuesNeither[i] << "'";
    263     }
    264 }
    265 
    266 TEST_F(PropertiesTest, GetInt64) {
    267     const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD);
    268 
    269     const std::string longMaxString = ToString(INT64_MAX);
    270     const std::string longStringOverflow = longMaxString + "0";
    271 
    272     const std::string longMinString = ToString(INT64_MIN);
    273     const std::string longStringUnderflow = longMinString + "0";
    274 
    275     const char* setValues[] = {
    276         // base 10
    277         "1", "2", "12345", "-1", "-2", "-12345",
    278         // base 16
    279         "0xFF", "0x0FF", "0xC0FFEE",
    280         // base 8
    281         "0", "01234", "07",
    282         // corner cases
    283         "       2", "2      ", "+0", "-0", "  +0   ", longMaxString.c_str(), longMinString.c_str(),
    284         // failing cases
    285         NULL, "", " ", "    ", "hello", "     true     ", "y",
    286         longStringOverflow.c_str(), longStringUnderflow.c_str(),
    287     };
    288 
    289     int64_t getValues[] = {
    290         // base 10
    291         1, 2, 12345, -1, -2, -12345,
    292         // base 16
    293         0xFF, 0x0FF, 0xC0FFEE,
    294         // base 8
    295         0, 01234, 07,
    296         // corner cases
    297         2, 2, 0, 0, 0, INT64_MAX, INT64_MIN,
    298         // failing cases
    299         DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
    300         DEFAULT_VALUE, DEFAULT_VALUE,
    301     };
    302 
    303     ASSERT_EQ(arraysize(setValues), arraysize(getValues));
    304 
    305     for (size_t i = 0; i < arraysize(setValues); ++i) {
    306         ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
    307 
    308         int64_t val = property_get_int64(PROPERTY_TEST_KEY, DEFAULT_VALUE);
    309         EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
    310     }
    311 }
    312 
    313 TEST_F(PropertiesTest, GetInt32) {
    314     const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF);
    315 
    316     const std::string intMaxString = ToString(INT32_MAX);
    317     const std::string intStringOverflow = intMaxString + "0";
    318 
    319     const std::string intMinString = ToString(INT32_MIN);
    320     const std::string intStringUnderflow = intMinString + "0";
    321 
    322     const char* setValues[] = {
    323         // base 10
    324         "1", "2", "12345", "-1", "-2", "-12345",
    325         // base 16
    326         "0xFF", "0x0FF", "0xC0FFEE", "0Xf00",
    327         // base 8
    328         "0", "01234", "07",
    329         // corner cases
    330         "       2", "2      ", "+0", "-0", "  +0   ", intMaxString.c_str(), intMinString.c_str(),
    331         // failing cases
    332         NULL, "", " ", "    ", "hello", "     true     ", "y",
    333         intStringOverflow.c_str(), intStringUnderflow.c_str(),
    334     };
    335 
    336     int32_t getValues[] = {
    337         // base 10
    338         1, 2, 12345, -1, -2, -12345,
    339         // base 16
    340         0xFF, 0x0FF, 0xC0FFEE, 0Xf00,
    341         // base 8
    342         0, 01234, 07,
    343         // corner cases
    344         2, 2, 0, 0, 0, INT32_MAX, INT32_MIN,
    345         // failing cases
    346         DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
    347         DEFAULT_VALUE, DEFAULT_VALUE,
    348     };
    349 
    350     ASSERT_EQ(arraysize(setValues), arraysize(getValues));
    351 
    352     for (size_t i = 0; i < arraysize(setValues); ++i) {
    353         ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
    354 
    355         int32_t val = property_get_int32(PROPERTY_TEST_KEY, DEFAULT_VALUE);
    356         EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
    357     }
    358 }
    359 
    360 } // namespace android
    361