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 <unistd.h>
20 
21 #include <gtest/gtest.h>
22 
23 #include <atomic>
24 #include <chrono>
25 #include <string>
26 #include <thread>
27 
28 #if !defined(_WIN32)
29 using namespace std::literals;
30 #endif
31 
TEST(properties,smoke)32 TEST(properties, smoke) {
33   android::base::SetProperty("debug.libbase.property_test", "hello");
34 
35   std::string s = android::base::GetProperty("debug.libbase.property_test", "");
36   ASSERT_EQ("hello", s);
37 
38   android::base::SetProperty("debug.libbase.property_test", "world");
39   s = android::base::GetProperty("debug.libbase.property_test", "");
40   ASSERT_EQ("world", s);
41 
42   s = android::base::GetProperty("this.property.does.not.exist", "");
43   ASSERT_EQ("", s);
44 
45   s = android::base::GetProperty("this.property.does.not.exist", "default");
46   ASSERT_EQ("default", s);
47 }
48 
TEST(properties,too_long)49 TEST(properties, too_long) {
50 #if !defined(_WIN32)
51   if (getuid() != 0) {
52     GTEST_SKIP() << "Skipping test, must be run as root.";
53   }
54 #endif
55   // Properties have a fixed limit on the size of their value.
56   std::string key("debug.libbase.property_too_long");
57   std::string value(92, 'a');
58   ASSERT_FALSE(android::base::SetProperty(key, value));
59   ASSERT_EQ("missing", android::base::GetProperty(key, "missing"));
60 
61   // Except for "ro." properties, which can have arbitrarily-long values.
62   key = "ro." + key + std::to_string(time(nullptr));
63   ASSERT_TRUE(android::base::SetProperty(key, value));
64   ASSERT_EQ(value, android::base::GetProperty(key, "missing"));
65   // ...because you can't change them.
66   ASSERT_FALSE(android::base::SetProperty(key, "hello"));
67   ASSERT_EQ(value, android::base::GetProperty(key, "missing"));
68 }
69 
TEST(properties,empty_key)70 TEST(properties, empty_key) {
71   ASSERT_FALSE(android::base::SetProperty("", "hello"));
72   ASSERT_EQ("default", android::base::GetProperty("", "default"));
73 }
74 
TEST(properties,empty_value)75 TEST(properties, empty_value) {
76   // Because you can't delete a property, people "delete" them by
77   // setting them to the empty string. In that case we'd want to
78   // keep the default value (like cutils' property_get did).
79   ASSERT_TRUE(android::base::SetProperty("debug.libbase.property_empty_value", ""));
80   ASSERT_EQ("default", android::base::GetProperty("debug.libbase.property_empty_value", "default"));
81 }
82 
CheckGetBoolProperty(bool expected,const std::string & value,bool default_value)83 static void CheckGetBoolProperty(bool expected, const std::string& value, bool default_value) {
84   android::base::SetProperty("debug.libbase.property_test", value.c_str());
85   ASSERT_EQ(expected, android::base::GetBoolProperty("debug.libbase.property_test", default_value));
86 }
87 
TEST(properties,GetBoolProperty_true)88 TEST(properties, GetBoolProperty_true) {
89   CheckGetBoolProperty(true, "1", false);
90   CheckGetBoolProperty(true, "y", false);
91   CheckGetBoolProperty(true, "yes", false);
92   CheckGetBoolProperty(true, "on", false);
93   CheckGetBoolProperty(true, "true", false);
94 }
95 
TEST(properties,GetBoolProperty_false)96 TEST(properties, GetBoolProperty_false) {
97   CheckGetBoolProperty(false, "0", true);
98   CheckGetBoolProperty(false, "n", true);
99   CheckGetBoolProperty(false, "no", true);
100   CheckGetBoolProperty(false, "off", true);
101   CheckGetBoolProperty(false, "false", true);
102 }
103 
TEST(properties,GetBoolProperty_default)104 TEST(properties, GetBoolProperty_default) {
105   CheckGetBoolProperty(true, "burp", true);
106   CheckGetBoolProperty(false, "burp", false);
107 }
108 
CheckGetIntProperty()109 template <typename T> void CheckGetIntProperty() {
110   // Positive and negative.
111   android::base::SetProperty("debug.libbase.property_test", "-12");
112   EXPECT_EQ(T(-12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
113   android::base::SetProperty("debug.libbase.property_test", "12");
114   EXPECT_EQ(T(12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
115 
116   // Default value.
117   android::base::SetProperty("debug.libbase.property_test", "");
118   EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
119 
120   // Bounds checks.
121   android::base::SetProperty("debug.libbase.property_test", "0");
122   EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
123   android::base::SetProperty("debug.libbase.property_test", "1");
124   EXPECT_EQ(T(1), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
125   android::base::SetProperty("debug.libbase.property_test", "2");
126   EXPECT_EQ(T(2), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
127   android::base::SetProperty("debug.libbase.property_test", "3");
128   EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
129 }
130 
CheckGetUintProperty()131 template <typename T> void CheckGetUintProperty() {
132   // Positive.
133   android::base::SetProperty("debug.libbase.property_test", "12");
134   EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 45));
135 
136   // Default value.
137   android::base::SetProperty("debug.libbase.property_test", "");
138   EXPECT_EQ(T(45), android::base::GetUintProperty<T>("debug.libbase.property_test", 45));
139 
140   // Bounds checks.
141   android::base::SetProperty("debug.libbase.property_test", "12");
142   EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 33, 22));
143   android::base::SetProperty("debug.libbase.property_test", "12");
144   EXPECT_EQ(T(5), android::base::GetUintProperty<T>("debug.libbase.property_test", 5, 10));
145 }
146 
TEST(properties,GetIntProperty_int8_t)147 TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); }
TEST(properties,GetIntProperty_int16_t)148 TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); }
TEST(properties,GetIntProperty_int32_t)149 TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); }
TEST(properties,GetIntProperty_int64_t)150 TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); }
151 
TEST(properties,GetUintProperty_uint8_t)152 TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); }
TEST(properties,GetUintProperty_uint16_t)153 TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); }
TEST(properties,GetUintProperty_uint32_t)154 TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); }
TEST(properties,GetUintProperty_uint64_t)155 TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
156 
TEST(properties,WaitForProperty)157 TEST(properties, WaitForProperty) {
158 #if defined(__BIONIC__)
159   std::atomic<bool> flag{false};
160   std::thread thread([&]() {
161     std::this_thread::sleep_for(100ms);
162     android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
163     while (!flag) std::this_thread::yield();
164     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
165   });
166 
167   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
168   flag = true;
169   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s));
170   thread.join();
171 #else
172   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
173 #endif
174 }
175 
TEST(properties,WaitForProperty_timeout)176 TEST(properties, WaitForProperty_timeout) {
177 #if defined(__BIONIC__)
178   auto t0 = std::chrono::steady_clock::now();
179   ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_timeout_test", "a",
180                                               200ms));
181   auto t1 = std::chrono::steady_clock::now();
182 
183   ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms);
184   // Upper bounds on timing are inherently flaky, but let's try...
185   ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
186 #else
187   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
188 #endif
189 }
190 
TEST(properties,WaitForProperty_MaxTimeout)191 TEST(properties, WaitForProperty_MaxTimeout) {
192 #if defined(__BIONIC__)
193   std::atomic<bool> flag{false};
194   std::thread thread([&]() {
195     android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
196     while (!flag) std::this_thread::yield();
197     std::this_thread::sleep_for(500ms);
198     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
199   });
200 
201   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
202   flag = true;
203   // Test that this does not immediately return false due to overflow issues with the timeout.
204   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b"));
205   thread.join();
206 #else
207   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
208 #endif
209 }
210 
TEST(properties,WaitForProperty_NegativeTimeout)211 TEST(properties, WaitForProperty_NegativeTimeout) {
212 #if defined(__BIONIC__)
213   std::atomic<bool> flag{false};
214   std::thread thread([&]() {
215     android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
216     while (!flag) std::this_thread::yield();
217     std::this_thread::sleep_for(500ms);
218     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
219   });
220 
221   ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
222   flag = true;
223   // Assert that this immediately returns with a negative timeout
224   ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", -100ms));
225   thread.join();
226 #else
227   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
228 #endif
229 }
230 
TEST(properties,WaitForPropertyCreation)231 TEST(properties, WaitForPropertyCreation) {
232 #if defined(__BIONIC__)
233   std::thread thread([&]() {
234     std::this_thread::sleep_for(100ms);
235     android::base::SetProperty("debug.libbase.WaitForPropertyCreation_test", "a");
236   });
237 
238   ASSERT_TRUE(android::base::WaitForPropertyCreation(
239           "debug.libbase.WaitForPropertyCreation_test", 1s));
240   thread.join();
241 #else
242   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
243 #endif
244 }
245 
TEST(properties,WaitForPropertyCreation_timeout)246 TEST(properties, WaitForPropertyCreation_timeout) {
247 #if defined(__BIONIC__)
248   auto t0 = std::chrono::steady_clock::now();
249   ASSERT_FALSE(android::base::WaitForPropertyCreation(
250           "debug.libbase.WaitForPropertyCreation_timeout_test", 200ms));
251   auto t1 = std::chrono::steady_clock::now();
252 
253   ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms);
254   // Upper bounds on timing are inherently flaky, but let's try...
255   ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
256 #else
257   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
258 #endif
259 }
260 
TEST(properties,CachedProperty)261 TEST(properties, CachedProperty) {
262 #if defined(__BIONIC__)
263   android::base::CachedProperty cached_property("debug.libbase.CachedProperty_test");
264   bool changed;
265   cached_property.Get(&changed);
266 
267   android::base::SetProperty("debug.libbase.CachedProperty_test", "foo");
268   ASSERT_STREQ("foo", cached_property.Get(&changed));
269   ASSERT_TRUE(changed);
270 
271   ASSERT_STREQ("foo", cached_property.Get(&changed));
272   ASSERT_FALSE(changed);
273 
274   android::base::SetProperty("debug.libbase.CachedProperty_test", "bar");
275   ASSERT_STREQ("bar", cached_property.Get(&changed));
276   ASSERT_TRUE(changed);
277 
278   ASSERT_STREQ("bar", cached_property.Get(&changed));
279   ASSERT_FALSE(changed);
280 
281 #else
282   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
283 #endif
284 }
285