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
21 #include <atomic>
22 #include <chrono>
23 #include <string>
24 #include <thread>
25
26 #if !defined(_WIN32)
27 using namespace std::literals;
28 #endif
29
TEST(properties,smoke)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
TEST(properties,empty)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
CheckGetBoolProperty(bool expected,const std::string & value,bool default_value)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
TEST(properties,GetBoolProperty_true)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
TEST(properties,GetBoolProperty_false)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
TEST(properties,GetBoolProperty_default)77 TEST(properties, GetBoolProperty_default) {
78 CheckGetBoolProperty(true, "burp", true);
79 CheckGetBoolProperty(false, "burp", false);
80 }
81
CheckGetIntProperty()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
CheckGetUintProperty()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
TEST(properties,GetIntProperty_int8_t)120 TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); }
TEST(properties,GetIntProperty_int16_t)121 TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); }
TEST(properties,GetIntProperty_int32_t)122 TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); }
TEST(properties,GetIntProperty_int64_t)123 TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); }
124
TEST(properties,GetUintProperty_uint8_t)125 TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); }
TEST(properties,GetUintProperty_uint16_t)126 TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); }
TEST(properties,GetUintProperty_uint32_t)127 TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); }
TEST(properties,GetUintProperty_uint64_t)128 TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
129
TEST(properties,WaitForProperty)130 TEST(properties, WaitForProperty) {
131 #if defined(__BIONIC__)
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
140 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
141 flag = true;
142 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s));
143 thread.join();
144 #else
145 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
146 #endif
147 }
148
TEST(properties,WaitForProperty_timeout)149 TEST(properties, WaitForProperty_timeout) {
150 #if defined(__BIONIC__)
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);
159 #else
160 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
161 #endif
162 }
163
TEST(properties,WaitForProperty_MaxTimeout)164 TEST(properties, WaitForProperty_MaxTimeout) {
165 #if defined(__BIONIC__)
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();
179 #else
180 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
181 #endif
182 }
183
TEST(properties,WaitForProperty_NegativeTimeout)184 TEST(properties, WaitForProperty_NegativeTimeout) {
185 #if defined(__BIONIC__)
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();
199 #else
200 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
201 #endif
202 }
203
TEST(properties,WaitForPropertyCreation)204 TEST(properties, WaitForPropertyCreation) {
205 #if defined(__BIONIC__)
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();
214 #else
215 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
216 #endif
217 }
218
TEST(properties,WaitForPropertyCreation_timeout)219 TEST(properties, WaitForPropertyCreation_timeout) {
220 #if defined(__BIONIC__)
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);
229 #else
230 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
231 #endif
232 }
233
TEST(properties,CachedProperty)234 TEST(properties, CachedProperty) {
235 #if defined(__BIONIC__)
236 android::base::CachedProperty cached_property("debug.libbase.CachedProperty_test");
237 bool changed;
238 cached_property.Get(&changed);
239
240 android::base::SetProperty("debug.libbase.CachedProperty_test", "foo");
241 ASSERT_STREQ("foo", cached_property.Get(&changed));
242 ASSERT_TRUE(changed);
243
244 ASSERT_STREQ("foo", cached_property.Get(&changed));
245 ASSERT_FALSE(changed);
246
247 android::base::SetProperty("debug.libbase.CachedProperty_test", "bar");
248 ASSERT_STREQ("bar", cached_property.Get(&changed));
249 ASSERT_TRUE(changed);
250
251 ASSERT_STREQ("bar", cached_property.Get(&changed));
252 ASSERT_FALSE(changed);
253
254 #else
255 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
256 #endif
257 }
258