blob: 1655528b71199d84a1bf2f32695378e24cd6a456 [file] [log] [blame]
Elliott Hughes5a7788c2016-09-21 16:53:15 -07001/*
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
Tom Cherryaa817612020-07-14 11:23:39 -070019#include <unistd.h>
20
Elliott Hughes5a7788c2016-09-21 16:53:15 -070021#include <gtest/gtest.h>
22
Elliott Hughes530448e2017-02-10 19:02:51 -080023#include <atomic>
24#include <chrono>
Elliott Hughes5a7788c2016-09-21 16:53:15 -070025#include <string>
Elliott Hughes530448e2017-02-10 19:02:51 -080026#include <thread>
27
Elliott Hughes083c2fe2018-05-24 18:00:39 -070028#if !defined(_WIN32)
29using namespace std::literals;
30#endif
Elliott Hughes5a7788c2016-09-21 16:53:15 -070031
32TEST(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
Elliott Hughesc9285852020-05-20 08:03:50 -070049TEST(properties, too_long) {
Tom Cherryaa817612020-07-14 11:23:39 -070050#if !defined(_WIN32)
51 if (getuid() != 0) {
52 GTEST_SKIP() << "Skipping test, must be run as root.";
53 }
54#endif
Elliott Hughesc9285852020-05-20 08:03:50 -070055 // 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
70TEST(properties, empty_key) {
71 ASSERT_FALSE(android::base::SetProperty("", "hello"));
72 ASSERT_EQ("default", android::base::GetProperty("", "default"));
73}
74
75TEST(properties, empty_value) {
Elliott Hughes5a7788c2016-09-21 16:53:15 -070076 // 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).
Elliott Hughesc9285852020-05-20 08:03:50 -070079 ASSERT_TRUE(android::base::SetProperty("debug.libbase.property_empty_value", ""));
80 ASSERT_EQ("default", android::base::GetProperty("debug.libbase.property_empty_value", "default"));
Elliott Hughes5a7788c2016-09-21 16:53:15 -070081}
82
83static 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
88TEST(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
96TEST(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
104TEST(properties, GetBoolProperty_default) {
105 CheckGetBoolProperty(true, "burp", true);
106 CheckGetBoolProperty(false, "burp", false);
107}
108
109template <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
131template <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
147TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); }
148TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); }
149TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); }
150TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); }
151
152TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); }
153TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); }
154TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); }
155TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
Elliott Hughes530448e2017-02-10 19:02:51 -0800156
157TEST(properties, WaitForProperty) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700158#if defined(__BIONIC__)
Elliott Hughes530448e2017-02-10 19:02:51 -0800159 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
Elliott Hughes81bcb212017-02-16 17:14:10 -0800167 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
Elliott Hughes530448e2017-02-10 19:02:51 -0800168 flag = true;
Elliott Hughes81bcb212017-02-16 17:14:10 -0800169 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s));
Elliott Hughes530448e2017-02-10 19:02:51 -0800170 thread.join();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700171#else
172 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
173#endif
Elliott Hughes530448e2017-02-10 19:02:51 -0800174}
Elliott Hughes81bcb212017-02-16 17:14:10 -0800175
176TEST(properties, WaitForProperty_timeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700177#if defined(__BIONIC__)
Elliott Hughes81bcb212017-02-16 17:14:10 -0800178 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);
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700186#else
187 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
188#endif
Elliott Hughes81bcb212017-02-16 17:14:10 -0800189}
Keun-young Park16f70512017-02-27 13:23:50 -0800190
Tom Cherryd0516ca2017-03-24 16:52:29 -0700191TEST(properties, WaitForProperty_MaxTimeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700192#if defined(__BIONIC__)
Tom Cherryd0516ca2017-03-24 16:52:29 -0700193 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();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700206#else
207 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
208#endif
Tom Cherryd0516ca2017-03-24 16:52:29 -0700209}
210
211TEST(properties, WaitForProperty_NegativeTimeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700212#if defined(__BIONIC__)
Tom Cherryd0516ca2017-03-24 16:52:29 -0700213 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();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700226#else
227 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
228#endif
Tom Cherryd0516ca2017-03-24 16:52:29 -0700229}
230
Keun-young Park16f70512017-02-27 13:23:50 -0800231TEST(properties, WaitForPropertyCreation) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700232#if defined(__BIONIC__)
Keun-young Park16f70512017-02-27 13:23:50 -0800233 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();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700241#else
242 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
243#endif
Keun-young Park16f70512017-02-27 13:23:50 -0800244}
245
246TEST(properties, WaitForPropertyCreation_timeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700247#if defined(__BIONIC__)
Keun-young Park16f70512017-02-27 13:23:50 -0800248 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);
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700256#else
257 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
258#endif
Keun-young Park16f70512017-02-27 13:23:50 -0800259}
Josh Gaoeb63a7e2020-02-26 14:57:20 -0800260
261TEST(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}