blob: de5f3dcfa90afabd2c9ec9220c4b5e4179a0d61d [file] [log] [blame]
Elliott Hughes1e88c8c2016-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 Hughesb30769a2017-02-10 19:02:51 -080021#include <atomic>
22#include <chrono>
Elliott Hughes1e88c8c2016-09-21 16:53:15 -070023#include <string>
Elliott Hughesb30769a2017-02-10 19:02:51 -080024#include <thread>
25
26using namespace std::chrono_literals;
Elliott Hughes1e88c8c2016-09-21 16:53:15 -070027
28TEST(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
45TEST(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
54static 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
59TEST(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
67TEST(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
75TEST(properties, GetBoolProperty_default) {
76 CheckGetBoolProperty(true, "burp", true);
77 CheckGetBoolProperty(false, "burp", false);
78}
79
80template <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
102template <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
118TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); }
119TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); }
120TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); }
121TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); }
122
123TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); }
124TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); }
125TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); }
126TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
Elliott Hughesb30769a2017-02-10 19:02:51 -0800127
128TEST(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 Hughes03edc9f2017-02-16 17:14:10 -0800137 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
Elliott Hughesb30769a2017-02-10 19:02:51 -0800138 flag = true;
Elliott Hughes03edc9f2017-02-16 17:14:10 -0800139 ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s));
Elliott Hughesb30769a2017-02-10 19:02:51 -0800140 thread.join();
141}
Elliott Hughes03edc9f2017-02-16 17:14:10 -0800142
143TEST(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 Parke2d986d2017-02-27 13:23:50 -0800153
Tom Cherry3d572942017-03-24 16:52:29 -0700154TEST(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
170TEST(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 Parke2d986d2017-02-27 13:23:50 -0800186TEST(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
197TEST(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}