blob: 94ae690a919c5a4751e0c6abfe77b446aab15209 [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
19#include <gtest/gtest.h>
20
Elliott Hughes530448e2017-02-10 19:02:51 -080021#include <atomic>
22#include <chrono>
Elliott Hughes5a7788c2016-09-21 16:53:15 -070023#include <string>
Elliott Hughes530448e2017-02-10 19:02:51 -080024#include <thread>
25
Elliott Hughes083c2fe2018-05-24 18:00:39 -070026#if !defined(_WIN32)
27using namespace std::literals;
28#endif
Elliott Hughes5a7788c2016-09-21 16:53:15 -070029
30TEST(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
Elliott Hughesc9285852020-05-20 08:03:50 -070047TEST(properties, too_long) {
48 // Properties have a fixed limit on the size of their value.
49 std::string key("debug.libbase.property_too_long");
50 std::string value(92, 'a');
51 ASSERT_FALSE(android::base::SetProperty(key, value));
52 ASSERT_EQ("missing", android::base::GetProperty(key, "missing"));
53
54 // Except for "ro." properties, which can have arbitrarily-long values.
55 key = "ro." + key + std::to_string(time(nullptr));
56 ASSERT_TRUE(android::base::SetProperty(key, value));
57 ASSERT_EQ(value, android::base::GetProperty(key, "missing"));
58 // ...because you can't change them.
59 ASSERT_FALSE(android::base::SetProperty(key, "hello"));
60 ASSERT_EQ(value, android::base::GetProperty(key, "missing"));
61}
62
63TEST(properties, empty_key) {
64 ASSERT_FALSE(android::base::SetProperty("", "hello"));
65 ASSERT_EQ("default", android::base::GetProperty("", "default"));
66}
67
68TEST(properties, empty_value) {
Elliott Hughes5a7788c2016-09-21 16:53:15 -070069 // Because you can't delete a property, people "delete" them by
70 // setting them to the empty string. In that case we'd want to
71 // keep the default value (like cutils' property_get did).
Elliott Hughesc9285852020-05-20 08:03:50 -070072 ASSERT_TRUE(android::base::SetProperty("debug.libbase.property_empty_value", ""));
73 ASSERT_EQ("default", android::base::GetProperty("debug.libbase.property_empty_value", "default"));
Elliott Hughes5a7788c2016-09-21 16:53:15 -070074}
75
76static void CheckGetBoolProperty(bool expected, const std::string& value, bool default_value) {
77 android::base::SetProperty("debug.libbase.property_test", value.c_str());
78 ASSERT_EQ(expected, android::base::GetBoolProperty("debug.libbase.property_test", default_value));
79}
80
81TEST(properties, GetBoolProperty_true) {
82 CheckGetBoolProperty(true, "1", false);
83 CheckGetBoolProperty(true, "y", false);
84 CheckGetBoolProperty(true, "yes", false);
85 CheckGetBoolProperty(true, "on", false);
86 CheckGetBoolProperty(true, "true", false);
87}
88
89TEST(properties, GetBoolProperty_false) {
90 CheckGetBoolProperty(false, "0", true);
91 CheckGetBoolProperty(false, "n", true);
92 CheckGetBoolProperty(false, "no", true);
93 CheckGetBoolProperty(false, "off", true);
94 CheckGetBoolProperty(false, "false", true);
95}
96
97TEST(properties, GetBoolProperty_default) {
98 CheckGetBoolProperty(true, "burp", true);
99 CheckGetBoolProperty(false, "burp", false);
100}
101
102template <typename T> void CheckGetIntProperty() {
103 // Positive and negative.
104 android::base::SetProperty("debug.libbase.property_test", "-12");
105 EXPECT_EQ(T(-12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
106 android::base::SetProperty("debug.libbase.property_test", "12");
107 EXPECT_EQ(T(12), android::base::GetIntProperty<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::GetIntProperty<T>("debug.libbase.property_test", 45));
112
113 // Bounds checks.
114 android::base::SetProperty("debug.libbase.property_test", "0");
115 EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
116 android::base::SetProperty("debug.libbase.property_test", "1");
117 EXPECT_EQ(T(1), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
118 android::base::SetProperty("debug.libbase.property_test", "2");
119 EXPECT_EQ(T(2), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
120 android::base::SetProperty("debug.libbase.property_test", "3");
121 EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
122}
123
124template <typename T> void CheckGetUintProperty() {
125 // Positive.
126 android::base::SetProperty("debug.libbase.property_test", "12");
127 EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 45));
128
129 // Default value.
130 android::base::SetProperty("debug.libbase.property_test", "");
131 EXPECT_EQ(T(45), android::base::GetUintProperty<T>("debug.libbase.property_test", 45));
132
133 // Bounds checks.
134 android::base::SetProperty("debug.libbase.property_test", "12");
135 EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 33, 22));
136 android::base::SetProperty("debug.libbase.property_test", "12");
137 EXPECT_EQ(T(5), android::base::GetUintProperty<T>("debug.libbase.property_test", 5, 10));
138}
139
140TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); }
141TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); }
142TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); }
143TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); }
144
145TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); }
146TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); }
147TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); }
148TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
Elliott Hughes530448e2017-02-10 19:02:51 -0800149
150TEST(properties, WaitForProperty) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700151#if defined(__BIONIC__)
Elliott Hughes530448e2017-02-10 19:02:51 -0800152 std::atomic<bool> flag{false};
153 std::thread thread([&]() {
154 std::this_thread::sleep_for(100ms);
155 android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
156 while (!flag) std::this_thread::yield();
157 android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
158 });
159
Elliott Hughes81bcb212017-02-16 17:14:10 -0800160 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
Elliott Hughes530448e2017-02-10 19:02:51 -0800161 flag = true;
Elliott Hughes81bcb212017-02-16 17:14:10 -0800162 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s));
Elliott Hughes530448e2017-02-10 19:02:51 -0800163 thread.join();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700164#else
165 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
166#endif
Elliott Hughes530448e2017-02-10 19:02:51 -0800167}
Elliott Hughes81bcb212017-02-16 17:14:10 -0800168
169TEST(properties, WaitForProperty_timeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700170#if defined(__BIONIC__)
Elliott Hughes81bcb212017-02-16 17:14:10 -0800171 auto t0 = std::chrono::steady_clock::now();
172 ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_timeout_test", "a",
173 200ms));
174 auto t1 = std::chrono::steady_clock::now();
175
176 ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms);
177 // Upper bounds on timing are inherently flaky, but let's try...
178 ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700179#else
180 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
181#endif
Elliott Hughes81bcb212017-02-16 17:14:10 -0800182}
Keun-young Park16f70512017-02-27 13:23:50 -0800183
Tom Cherryd0516ca2017-03-24 16:52:29 -0700184TEST(properties, WaitForProperty_MaxTimeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700185#if defined(__BIONIC__)
Tom Cherryd0516ca2017-03-24 16:52:29 -0700186 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 // Test that this does not immediately return false due to overflow issues with the timeout.
197 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b"));
198 thread.join();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700199#else
200 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
201#endif
Tom Cherryd0516ca2017-03-24 16:52:29 -0700202}
203
204TEST(properties, WaitForProperty_NegativeTimeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700205#if defined(__BIONIC__)
Tom Cherryd0516ca2017-03-24 16:52:29 -0700206 std::atomic<bool> flag{false};
207 std::thread thread([&]() {
208 android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
209 while (!flag) std::this_thread::yield();
210 std::this_thread::sleep_for(500ms);
211 android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
212 });
213
214 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
215 flag = true;
216 // Assert that this immediately returns with a negative timeout
217 ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", -100ms));
218 thread.join();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700219#else
220 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
221#endif
Tom Cherryd0516ca2017-03-24 16:52:29 -0700222}
223
Keun-young Park16f70512017-02-27 13:23:50 -0800224TEST(properties, WaitForPropertyCreation) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700225#if defined(__BIONIC__)
Keun-young Park16f70512017-02-27 13:23:50 -0800226 std::thread thread([&]() {
227 std::this_thread::sleep_for(100ms);
228 android::base::SetProperty("debug.libbase.WaitForPropertyCreation_test", "a");
229 });
230
231 ASSERT_TRUE(android::base::WaitForPropertyCreation(
232 "debug.libbase.WaitForPropertyCreation_test", 1s));
233 thread.join();
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700234#else
235 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
236#endif
Keun-young Park16f70512017-02-27 13:23:50 -0800237}
238
239TEST(properties, WaitForPropertyCreation_timeout) {
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700240#if defined(__BIONIC__)
Keun-young Park16f70512017-02-27 13:23:50 -0800241 auto t0 = std::chrono::steady_clock::now();
242 ASSERT_FALSE(android::base::WaitForPropertyCreation(
243 "debug.libbase.WaitForPropertyCreation_timeout_test", 200ms));
244 auto t1 = std::chrono::steady_clock::now();
245
246 ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms);
247 // Upper bounds on timing are inherently flaky, but let's try...
248 ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
Elliott Hughes083c2fe2018-05-24 18:00:39 -0700249#else
250 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
251#endif
Keun-young Park16f70512017-02-27 13:23:50 -0800252}
Josh Gaoeb63a7e2020-02-26 14:57:20 -0800253
254TEST(properties, CachedProperty) {
255#if defined(__BIONIC__)
256 android::base::CachedProperty cached_property("debug.libbase.CachedProperty_test");
257 bool changed;
258 cached_property.Get(&changed);
259
260 android::base::SetProperty("debug.libbase.CachedProperty_test", "foo");
261 ASSERT_STREQ("foo", cached_property.Get(&changed));
262 ASSERT_TRUE(changed);
263
264 ASSERT_STREQ("foo", cached_property.Get(&changed));
265 ASSERT_FALSE(changed);
266
267 android::base::SetProperty("debug.libbase.CachedProperty_test", "bar");
268 ASSERT_STREQ("bar", cached_property.Get(&changed));
269 ASSERT_TRUE(changed);
270
271 ASSERT_STREQ("bar", cached_property.Get(&changed));
272 ASSERT_FALSE(changed);
273
274#else
275 GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
276#endif
277}