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