| Elliott Hughes | 1e88c8c | 2016-09-21 16:53:15 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2016 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 "android-base/properties.h" | 
 | 18 |  | 
 | 19 | #include <gtest/gtest.h> | 
 | 20 |  | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 21 | #include <atomic> | 
 | 22 | #include <chrono> | 
| Elliott Hughes | 1e88c8c | 2016-09-21 16:53:15 -0700 | [diff] [blame] | 23 | #include <string> | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 24 | #include <thread> | 
 | 25 |  | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 26 | #if !defined(_WIN32) | 
 | 27 | using namespace std::literals; | 
 | 28 | #endif | 
| Elliott Hughes | 1e88c8c | 2016-09-21 16:53:15 -0700 | [diff] [blame] | 29 |  | 
 | 30 | TEST(properties, smoke) { | 
 | 31 |   android::base::SetProperty("debug.libbase.property_test", "hello"); | 
 | 32 |  | 
 | 33 |   std::string s = android::base::GetProperty("debug.libbase.property_test", ""); | 
 | 34 |   ASSERT_EQ("hello", s); | 
 | 35 |  | 
 | 36 |   android::base::SetProperty("debug.libbase.property_test", "world"); | 
 | 37 |   s = android::base::GetProperty("debug.libbase.property_test", ""); | 
 | 38 |   ASSERT_EQ("world", s); | 
 | 39 |  | 
 | 40 |   s = android::base::GetProperty("this.property.does.not.exist", ""); | 
 | 41 |   ASSERT_EQ("", s); | 
 | 42 |  | 
 | 43 |   s = android::base::GetProperty("this.property.does.not.exist", "default"); | 
 | 44 |   ASSERT_EQ("default", s); | 
 | 45 | } | 
 | 46 |  | 
 | 47 | TEST(properties, empty) { | 
 | 48 |   // Because you can't delete a property, people "delete" them by | 
 | 49 |   // setting them to the empty string. In that case we'd want to | 
 | 50 |   // keep the default value (like cutils' property_get did). | 
 | 51 |   android::base::SetProperty("debug.libbase.property_test", ""); | 
 | 52 |   std::string s = android::base::GetProperty("debug.libbase.property_test", "default"); | 
 | 53 |   ASSERT_EQ("default", s); | 
 | 54 | } | 
 | 55 |  | 
 | 56 | static void CheckGetBoolProperty(bool expected, const std::string& value, bool default_value) { | 
 | 57 |   android::base::SetProperty("debug.libbase.property_test", value.c_str()); | 
 | 58 |   ASSERT_EQ(expected, android::base::GetBoolProperty("debug.libbase.property_test", default_value)); | 
 | 59 | } | 
 | 60 |  | 
 | 61 | TEST(properties, GetBoolProperty_true) { | 
 | 62 |   CheckGetBoolProperty(true, "1", false); | 
 | 63 |   CheckGetBoolProperty(true, "y", false); | 
 | 64 |   CheckGetBoolProperty(true, "yes", false); | 
 | 65 |   CheckGetBoolProperty(true, "on", false); | 
 | 66 |   CheckGetBoolProperty(true, "true", false); | 
 | 67 | } | 
 | 68 |  | 
 | 69 | TEST(properties, GetBoolProperty_false) { | 
 | 70 |   CheckGetBoolProperty(false, "0", true); | 
 | 71 |   CheckGetBoolProperty(false, "n", true); | 
 | 72 |   CheckGetBoolProperty(false, "no", true); | 
 | 73 |   CheckGetBoolProperty(false, "off", true); | 
 | 74 |   CheckGetBoolProperty(false, "false", true); | 
 | 75 | } | 
 | 76 |  | 
 | 77 | TEST(properties, GetBoolProperty_default) { | 
 | 78 |   CheckGetBoolProperty(true, "burp", true); | 
 | 79 |   CheckGetBoolProperty(false, "burp", false); | 
 | 80 | } | 
 | 81 |  | 
 | 82 | template <typename T> void CheckGetIntProperty() { | 
 | 83 |   // Positive and negative. | 
 | 84 |   android::base::SetProperty("debug.libbase.property_test", "-12"); | 
 | 85 |   EXPECT_EQ(T(-12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45)); | 
 | 86 |   android::base::SetProperty("debug.libbase.property_test", "12"); | 
 | 87 |   EXPECT_EQ(T(12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45)); | 
 | 88 |  | 
 | 89 |   // Default value. | 
 | 90 |   android::base::SetProperty("debug.libbase.property_test", ""); | 
 | 91 |   EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45)); | 
 | 92 |  | 
 | 93 |   // Bounds checks. | 
 | 94 |   android::base::SetProperty("debug.libbase.property_test", "0"); | 
 | 95 |   EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2)); | 
 | 96 |   android::base::SetProperty("debug.libbase.property_test", "1"); | 
 | 97 |   EXPECT_EQ(T(1), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2)); | 
 | 98 |   android::base::SetProperty("debug.libbase.property_test", "2"); | 
 | 99 |   EXPECT_EQ(T(2), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2)); | 
 | 100 |   android::base::SetProperty("debug.libbase.property_test", "3"); | 
 | 101 |   EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2)); | 
 | 102 | } | 
 | 103 |  | 
 | 104 | template <typename T> void CheckGetUintProperty() { | 
 | 105 |   // Positive. | 
 | 106 |   android::base::SetProperty("debug.libbase.property_test", "12"); | 
 | 107 |   EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 45)); | 
 | 108 |  | 
 | 109 |   // Default value. | 
 | 110 |   android::base::SetProperty("debug.libbase.property_test", ""); | 
 | 111 |   EXPECT_EQ(T(45), android::base::GetUintProperty<T>("debug.libbase.property_test", 45)); | 
 | 112 |  | 
 | 113 |   // Bounds checks. | 
 | 114 |   android::base::SetProperty("debug.libbase.property_test", "12"); | 
 | 115 |   EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 33, 22)); | 
 | 116 |   android::base::SetProperty("debug.libbase.property_test", "12"); | 
 | 117 |   EXPECT_EQ(T(5), android::base::GetUintProperty<T>("debug.libbase.property_test", 5, 10)); | 
 | 118 | } | 
 | 119 |  | 
 | 120 | TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); } | 
 | 121 | TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); } | 
 | 122 | TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); } | 
 | 123 | TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); } | 
 | 124 |  | 
 | 125 | TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); } | 
 | 126 | TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); } | 
 | 127 | TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); } | 
 | 128 | TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); } | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 129 |  | 
 | 130 | TEST(properties, WaitForProperty) { | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 131 | #if defined(__BIONIC__) | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 132 |   std::atomic<bool> flag{false}; | 
 | 133 |   std::thread thread([&]() { | 
 | 134 |     std::this_thread::sleep_for(100ms); | 
 | 135 |     android::base::SetProperty("debug.libbase.WaitForProperty_test", "a"); | 
 | 136 |     while (!flag) std::this_thread::yield(); | 
 | 137 |     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b"); | 
 | 138 |   }); | 
 | 139 |  | 
| Elliott Hughes | 03edc9f | 2017-02-16 17:14:10 -0800 | [diff] [blame] | 140 |   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s)); | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 141 |   flag = true; | 
| Elliott Hughes | 03edc9f | 2017-02-16 17:14:10 -0800 | [diff] [blame] | 142 |   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s)); | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 143 |   thread.join(); | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 144 | #else | 
 | 145 |   GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; | 
 | 146 | #endif | 
| Elliott Hughes | b30769a | 2017-02-10 19:02:51 -0800 | [diff] [blame] | 147 | } | 
| Elliott Hughes | 03edc9f | 2017-02-16 17:14:10 -0800 | [diff] [blame] | 148 |  | 
 | 149 | TEST(properties, WaitForProperty_timeout) { | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 150 | #if defined(__BIONIC__) | 
| Elliott Hughes | 03edc9f | 2017-02-16 17:14:10 -0800 | [diff] [blame] | 151 |   auto t0 = std::chrono::steady_clock::now(); | 
 | 152 |   ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_timeout_test", "a", | 
 | 153 |                                               200ms)); | 
 | 154 |   auto t1 = std::chrono::steady_clock::now(); | 
 | 155 |  | 
 | 156 |   ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms); | 
 | 157 |   // Upper bounds on timing are inherently flaky, but let's try... | 
 | 158 |   ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms); | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 159 | #else | 
 | 160 |   GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; | 
 | 161 | #endif | 
| Elliott Hughes | 03edc9f | 2017-02-16 17:14:10 -0800 | [diff] [blame] | 162 | } | 
| Keun-young Park | e2d986d | 2017-02-27 13:23:50 -0800 | [diff] [blame] | 163 |  | 
| Tom Cherry | 3d57294 | 2017-03-24 16:52:29 -0700 | [diff] [blame] | 164 | TEST(properties, WaitForProperty_MaxTimeout) { | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 165 | #if defined(__BIONIC__) | 
| Tom Cherry | 3d57294 | 2017-03-24 16:52:29 -0700 | [diff] [blame] | 166 |   std::atomic<bool> flag{false}; | 
 | 167 |   std::thread thread([&]() { | 
 | 168 |     android::base::SetProperty("debug.libbase.WaitForProperty_test", "a"); | 
 | 169 |     while (!flag) std::this_thread::yield(); | 
 | 170 |     std::this_thread::sleep_for(500ms); | 
 | 171 |     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b"); | 
 | 172 |   }); | 
 | 173 |  | 
 | 174 |   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s)); | 
 | 175 |   flag = true; | 
 | 176 |   // Test that this does not immediately return false due to overflow issues with the timeout. | 
 | 177 |   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b")); | 
 | 178 |   thread.join(); | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 179 | #else | 
 | 180 |   GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; | 
 | 181 | #endif | 
| Tom Cherry | 3d57294 | 2017-03-24 16:52:29 -0700 | [diff] [blame] | 182 | } | 
 | 183 |  | 
 | 184 | TEST(properties, WaitForProperty_NegativeTimeout) { | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 185 | #if defined(__BIONIC__) | 
| Tom Cherry | 3d57294 | 2017-03-24 16:52:29 -0700 | [diff] [blame] | 186 |   std::atomic<bool> flag{false}; | 
 | 187 |   std::thread thread([&]() { | 
 | 188 |     android::base::SetProperty("debug.libbase.WaitForProperty_test", "a"); | 
 | 189 |     while (!flag) std::this_thread::yield(); | 
 | 190 |     std::this_thread::sleep_for(500ms); | 
 | 191 |     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b"); | 
 | 192 |   }); | 
 | 193 |  | 
 | 194 |   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s)); | 
 | 195 |   flag = true; | 
 | 196 |   // Assert that this immediately returns with a negative timeout | 
 | 197 |   ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", -100ms)); | 
 | 198 |   thread.join(); | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 199 | #else | 
 | 200 |   GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; | 
 | 201 | #endif | 
| Tom Cherry | 3d57294 | 2017-03-24 16:52:29 -0700 | [diff] [blame] | 202 | } | 
 | 203 |  | 
| Keun-young Park | e2d986d | 2017-02-27 13:23:50 -0800 | [diff] [blame] | 204 | TEST(properties, WaitForPropertyCreation) { | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 205 | #if defined(__BIONIC__) | 
| Keun-young Park | e2d986d | 2017-02-27 13:23:50 -0800 | [diff] [blame] | 206 |   std::thread thread([&]() { | 
 | 207 |     std::this_thread::sleep_for(100ms); | 
 | 208 |     android::base::SetProperty("debug.libbase.WaitForPropertyCreation_test", "a"); | 
 | 209 |   }); | 
 | 210 |  | 
 | 211 |   ASSERT_TRUE(android::base::WaitForPropertyCreation( | 
 | 212 |           "debug.libbase.WaitForPropertyCreation_test", 1s)); | 
 | 213 |   thread.join(); | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 214 | #else | 
 | 215 |   GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; | 
 | 216 | #endif | 
| Keun-young Park | e2d986d | 2017-02-27 13:23:50 -0800 | [diff] [blame] | 217 | } | 
 | 218 |  | 
 | 219 | TEST(properties, WaitForPropertyCreation_timeout) { | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 220 | #if defined(__BIONIC__) | 
| Keun-young Park | e2d986d | 2017-02-27 13:23:50 -0800 | [diff] [blame] | 221 |   auto t0 = std::chrono::steady_clock::now(); | 
 | 222 |   ASSERT_FALSE(android::base::WaitForPropertyCreation( | 
 | 223 |           "debug.libbase.WaitForPropertyCreation_timeout_test", 200ms)); | 
 | 224 |   auto t1 = std::chrono::steady_clock::now(); | 
 | 225 |  | 
 | 226 |   ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms); | 
 | 227 |   // Upper bounds on timing are inherently flaky, but let's try... | 
 | 228 |   ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms); | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 229 | #else | 
 | 230 |   GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; | 
 | 231 | #endif | 
| Keun-young Park | e2d986d | 2017-02-27 13:23:50 -0800 | [diff] [blame] | 232 | } |