1 /* 2 * Copyright (C) 2017 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 19 #include <errno.h> 20 #include <sys/wait.h> 21 #include <unistd.h> 22 #include <sstream> 23 #include <string> 24 25 #if defined(__BIONIC__) 26 #include <sys/system_properties.h> 27 NanoTime()28 static uint64_t NanoTime() { 29 timespec now; 30 clock_gettime(CLOCK_MONOTONIC, &now); 31 return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec; 32 } 33 #endif 34 35 // Note that this test affects global state of the system 36 // this tests tries to mitigate this by using utime+pid 37 // prefix for the property name. It is still results in 38 // pollution of property service since properties cannot 39 // be removed. 40 // 41 // Note that there is also possibility to run into "out-of-memory" 42 // if this test if it is executed often enough without reboot. TEST(properties,smoke)43 TEST(properties, smoke) { 44 #if defined(__BIONIC__) 45 char propvalue[PROP_VALUE_MAX]; 46 47 std::stringstream ss; 48 ss << "debug.test." << getpid() << "." << NanoTime() << "."; 49 const std::string property_prefix = ss.str(); 50 const std::string property_name = property_prefix + "property1"; 51 52 // Set brand new property 53 ASSERT_EQ(0, __system_property_set(property_name.c_str(), "value1")); 54 ASSERT_EQ(6, __system_property_get(property_name.c_str(), propvalue)); 55 ASSERT_STREQ("value1", propvalue); 56 57 std::string long_value = "property-"; 58 for (size_t i = 0; i < PROP_VALUE_MAX; i++) { 59 long_value += "y"; 60 } 61 62 // Make sure that attempts to set invalid property value fails and preserves 63 // previous value. 64 propvalue[0] = '\0'; 65 ASSERT_EQ(-1, __system_property_set(property_name.c_str(), long_value.c_str())); 66 ASSERT_EQ(6, __system_property_get(property_name.c_str(), propvalue)); 67 ASSERT_STREQ("value1", propvalue); 68 69 // Update property 70 ASSERT_EQ(0, __system_property_set(property_name.c_str(), "value1-1")); 71 ASSERT_EQ(8, __system_property_get(property_name.c_str(), propvalue)); 72 ASSERT_STREQ("value1-1", propvalue); 73 74 75 // check that there is no limit on property name length 76 char suffix[1024]; 77 for (size_t i = 0; i < sizeof(suffix); i++) { 78 suffix[i] = 'x'; 79 } 80 81 suffix[sizeof(suffix)-1] = '\0'; 82 const std::string long_property_name = property_prefix + suffix; 83 84 ASSERT_EQ(0, __system_property_set(long_property_name.c_str(), "value2")); 85 ASSERT_EQ(6, __system_property_get(long_property_name.c_str(), propvalue)); 86 ASSERT_STREQ("value2", propvalue); 87 88 // test find and read_callback 89 const prop_info* pi = __system_property_find(property_name.c_str()); 90 ASSERT_TRUE(pi != nullptr); 91 92 std::string expected_name = property_name; 93 __system_property_read_callback(pi, 94 [](void* cookie, const char* name, const char* value, unsigned /*serial*/) { 95 const std::string* expected_name = static_cast<const std::string*>(cookie); 96 ASSERT_EQ(*expected_name, name); 97 ASSERT_STREQ("value1-1", value); 98 }, &expected_name); 99 100 pi = __system_property_find(long_property_name.c_str()); 101 ASSERT_TRUE(pi != nullptr); 102 103 expected_name = long_property_name; 104 __system_property_read_callback(pi, 105 [](void* cookie, const char* name, const char* value, unsigned /*serial*/) { 106 const std::string* expected_name = static_cast<const std::string*>(cookie); 107 ASSERT_EQ(*expected_name, name); 108 ASSERT_STREQ("value2", value); 109 }, &expected_name); 110 111 // Check that read() for long names still works but returns truncated version of the name 112 pi = __system_property_find(property_name.c_str()); 113 ASSERT_TRUE(pi != nullptr); 114 char legacy_name[PROP_NAME_MAX]; 115 expected_name = std::string(property_name.c_str(), PROP_NAME_MAX-1); 116 ASSERT_EQ(8, __system_property_read(pi, &legacy_name[0], propvalue)); 117 ASSERT_EQ(expected_name, legacy_name); 118 ASSERT_STREQ("value1-1", propvalue); 119 120 const prop_info* pi_long = __system_property_find(long_property_name.c_str()); 121 ASSERT_TRUE(pi != nullptr); 122 expected_name = std::string(long_property_name.c_str(), PROP_NAME_MAX-1); 123 ASSERT_EQ(6, __system_property_read(pi_long, &legacy_name[0], propvalue)); 124 ASSERT_EQ(expected_name, legacy_name); 125 ASSERT_STREQ("value2", propvalue); 126 #else // __BIONIC__ 127 GTEST_LOG_(INFO) << "This test does nothing.\n"; 128 #endif // __BIONIC__ 129 } 130 TEST(properties,empty_value)131 TEST(properties, empty_value) { 132 #if defined(__BIONIC__) 133 char propvalue[PROP_VALUE_MAX]; 134 135 std::stringstream ss; 136 ss << "debug.test." << getpid() << "." << NanoTime() << "." << "property_empty"; 137 const std::string property_name = ss.str(); 138 139 for (size_t i=0; i<1000; ++i) { 140 ASSERT_EQ(0, __system_property_set(property_name.c_str(), "")); 141 ASSERT_EQ(0, __system_property_get(property_name.c_str(), propvalue)); 142 ASSERT_STREQ("", propvalue); 143 } 144 145 #else // __BIONIC__ 146 GTEST_LOG_(INFO) << "This test does nothing.\n"; 147 #endif // __BIONIC__ 148 } 149