diff options
-rw-r--r-- | health/2.0/vts/functional/Android.bp | 25 | ||||
-rw-r--r-- | health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp | 248 | ||||
-rw-r--r-- | health/Android.bp | 1 |
3 files changed, 274 insertions, 0 deletions
diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp new file mode 100644 index 00000000..4ad01b98 --- /dev/null +++ b/health/2.0/vts/functional/Android.bp | |||
@@ -0,0 +1,25 @@ | |||
1 | // | ||
2 | // Copyright (C) 2017 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 | cc_test { | ||
18 | name: "VtsHalHealthV2_0TargetTest", | ||
19 | defaults: ["VtsHalTargetTestDefaults"], | ||
20 | srcs: ["VtsHalHealthV2_0TargetTest.cpp"], | ||
21 | static_libs: [ | ||
22 | "android.hardware.health@1.0", | ||
23 | "android.hardware.health@2.0", | ||
24 | ], | ||
25 | } | ||
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp new file mode 100644 index 00000000..8abed0c5 --- /dev/null +++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 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 | #define LOG_TAG "mHealthhidl_hal_test" | ||
18 | |||
19 | #include <mutex> | ||
20 | |||
21 | #include <VtsHalHidlTargetTestBase.h> | ||
22 | #include <android-base/logging.h> | ||
23 | #include <android/hardware/health/2.0/IHealth.h> | ||
24 | #include <android/hardware/health/2.0/types.h> | ||
25 | |||
26 | using ::testing::AssertionFailure; | ||
27 | using ::testing::AssertionResult; | ||
28 | using ::testing::AssertionSuccess; | ||
29 | using ::testing::VtsHalHidlTargetTestBase; | ||
30 | using ::testing::VtsHalHidlTargetTestEnvBase; | ||
31 | |||
32 | namespace android { | ||
33 | namespace hardware { | ||
34 | namespace health { | ||
35 | namespace V2_0 { | ||
36 | |||
37 | using V1_0::BatteryStatus; | ||
38 | using V1_0::HealthInfo; | ||
39 | |||
40 | // Test environment for graphics.composer | ||
41 | class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase { | ||
42 | public: | ||
43 | // get the test environment singleton | ||
44 | static HealthHidlEnvironment* Instance() { | ||
45 | static HealthHidlEnvironment* instance = new HealthHidlEnvironment; | ||
46 | return instance; | ||
47 | } | ||
48 | |||
49 | virtual void registerTestServices() override { registerTestService<IHealth>(); } | ||
50 | |||
51 | private: | ||
52 | HealthHidlEnvironment() {} | ||
53 | |||
54 | GTEST_DISALLOW_COPY_AND_ASSIGN_(HealthHidlEnvironment); | ||
55 | }; | ||
56 | |||
57 | class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase { | ||
58 | public: | ||
59 | virtual void SetUp() override { | ||
60 | std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName<IHealth>(); | ||
61 | LOG(INFO) << "get service with name:" << serviceName; | ||
62 | ASSERT_FALSE(serviceName.empty()); | ||
63 | mHealth = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>(serviceName); | ||
64 | ASSERT_NE(mHealth, nullptr); | ||
65 | } | ||
66 | |||
67 | sp<IHealth> mHealth; | ||
68 | }; | ||
69 | |||
70 | class Callback : public IHealthInfoCallback { | ||
71 | using Function = std::function<void(const HealthInfo&)>; | ||
72 | |||
73 | public: | ||
74 | Callback(const Function& f) : mInternal(f) {} | ||
75 | Return<void> healthInfoChanged(const HealthInfo& info) override { | ||
76 | std::unique_lock<std::mutex> lock(mMutex); | ||
77 | if (mInternal) mInternal(info); | ||
78 | return Void(); | ||
79 | } | ||
80 | void clear() { | ||
81 | std::unique_lock<std::mutex> lock(mMutex); | ||
82 | mInternal = nullptr; | ||
83 | } | ||
84 | |||
85 | private: | ||
86 | std::mutex mMutex; | ||
87 | Function mInternal; | ||
88 | }; | ||
89 | |||
90 | #define ASSERT_OK(r) ASSERT_TRUE(isOk(r)) | ||
91 | #define EXPECT_OK(r) EXPECT_TRUE(isOk(r)) | ||
92 | template <typename T> | ||
93 | AssertionResult isOk(const Return<T>& r) { | ||
94 | return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description()); | ||
95 | } | ||
96 | |||
97 | #define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r)) | ||
98 | // Both isOk() and Result::SUCCESS | ||
99 | AssertionResult isAllOk(const Return<Result>& r) { | ||
100 | if (!r.isOk()) { | ||
101 | return AssertionFailure() << r.description(); | ||
102 | } | ||
103 | if (static_cast<Result>(r) != Result::SUCCESS) { | ||
104 | return AssertionFailure() << toString(static_cast<Result>(r)); | ||
105 | } | ||
106 | return AssertionSuccess(); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Test whether callbacks work. Tested functions are IHealth::registerCallback, | ||
111 | * unregisterCallback, and update. | ||
112 | */ | ||
113 | TEST_F(HealthHidlTest, Callbacks) { | ||
114 | using namespace std::chrono_literals; | ||
115 | |||
116 | std::mutex mutex; | ||
117 | std::condition_variable cv; | ||
118 | bool firstCallbackInvoked = false; | ||
119 | bool secondCallbackInvoked = false; | ||
120 | |||
121 | sp<Callback> firstCallback = new Callback([&](const auto&) { | ||
122 | std::unique_lock<std::mutex> lk(mutex); | ||
123 | firstCallbackInvoked = true; | ||
124 | }); | ||
125 | |||
126 | sp<Callback> secondCallback = new Callback([&](const auto&) { | ||
127 | std::unique_lock<std::mutex> lk(mutex); | ||
128 | secondCallbackInvoked = true; | ||
129 | cv.notify_all(); | ||
130 | }); | ||
131 | |||
132 | ASSERT_ALL_OK(mHealth->registerCallback(firstCallback)); | ||
133 | ASSERT_ALL_OK(mHealth->registerCallback(secondCallback)); | ||
134 | |||
135 | // assert that the first callback is invoked when update is called. | ||
136 | { | ||
137 | std::unique_lock<std::mutex> lk(mutex); | ||
138 | firstCallbackInvoked = false; | ||
139 | secondCallbackInvoked = false; | ||
140 | } | ||
141 | |||
142 | ASSERT_ALL_OK(mHealth->update()); | ||
143 | |||
144 | { | ||
145 | std::unique_lock<std::mutex> lk(mutex); | ||
146 | EXPECT_TRUE(cv.wait_for(lk, 1s, [&] { | ||
147 | return firstCallbackInvoked && secondCallbackInvoked; | ||
148 | })) << "Timeout."; | ||
149 | ASSERT_TRUE(firstCallbackInvoked); | ||
150 | ASSERT_TRUE(secondCallbackInvoked); | ||
151 | } | ||
152 | |||
153 | ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback)); | ||
154 | |||
155 | // assert that the second callback is still invoked even though the first is unregistered. | ||
156 | { | ||
157 | std::unique_lock<std::mutex> lk(mutex); | ||
158 | firstCallbackInvoked = false; | ||
159 | secondCallbackInvoked = false; | ||
160 | } | ||
161 | |||
162 | ASSERT_ALL_OK(mHealth->update()); | ||
163 | |||
164 | { | ||
165 | std::unique_lock<std::mutex> lk(mutex); | ||
166 | EXPECT_TRUE(cv.wait_for(lk, 1s, [&] { return secondCallbackInvoked; })) << "Timeout."; | ||
167 | ASSERT_FALSE(firstCallbackInvoked); | ||
168 | ASSERT_TRUE(secondCallbackInvoked); | ||
169 | } | ||
170 | |||
171 | ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback)); | ||
172 | |||
173 | // avoid reference to lambda function that goes out of scope. | ||
174 | firstCallback->clear(); | ||
175 | secondCallback->clear(); | ||
176 | } | ||
177 | |||
178 | TEST_F(HealthHidlTest, UnregisterNonExistentCallback) { | ||
179 | sp<Callback> callback = new Callback([](const auto&) {}); | ||
180 | auto ret = mHealth->unregisterCallback(callback); | ||
181 | ASSERT_OK(ret); | ||
182 | ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * Pass the test if: | ||
187 | * - Property is not supported (res == NOT_SUPPORTED) | ||
188 | * - Result is success, and predicate is true | ||
189 | * @param res the Result value. | ||
190 | * @param valueStr the string representation for actual value (for error message) | ||
191 | * @param pred a predicate that test whether the value is valid | ||
192 | */ | ||
193 | #define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \ | ||
194 | EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred)) | ||
195 | |||
196 | AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred, | ||
197 | const std::string& predStr) { | ||
198 | if (res == Result::SUCCESS) { | ||
199 | if (pred) { | ||
200 | return AssertionSuccess(); | ||
201 | } | ||
202 | return AssertionFailure() << "value doesn't match.\nActual: " << valueStr | ||
203 | << "\nExpected: " << predStr; | ||
204 | } | ||
205 | if (res == Result::NOT_SUPPORTED) { | ||
206 | return AssertionSuccess(); | ||
207 | } | ||
208 | return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res); | ||
209 | } | ||
210 | |||
211 | TEST_F(HealthHidlTest, Properties) { | ||
212 | EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) { | ||
213 | EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0); | ||
214 | })); | ||
215 | EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) { | ||
216 | EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN); | ||
217 | })); | ||
218 | EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) { | ||
219 | EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN); | ||
220 | })); | ||
221 | EXPECT_OK(mHealth->getCapacity([](auto result, auto value) { | ||
222 | EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100); | ||
223 | })); | ||
224 | EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) { | ||
225 | EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN); | ||
226 | })); | ||
227 | EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) { | ||
228 | EXPECT_VALID_OR_UNSUPPORTED_PROP( | ||
229 | result, toString(value), | ||
230 | value == BatteryStatus::CHARGING || value == BatteryStatus::DISCHARGING || | ||
231 | value == BatteryStatus::NOT_CHARGING || value == BatteryStatus::FULL); | ||
232 | })); | ||
233 | } | ||
234 | |||
235 | } // namespace V2_0 | ||
236 | } // namespace health | ||
237 | } // namespace hardware | ||
238 | } // namespace android | ||
239 | |||
240 | int main(int argc, char** argv) { | ||
241 | using ::android::hardware::health::V2_0::HealthHidlEnvironment; | ||
242 | ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance()); | ||
243 | ::testing::InitGoogleTest(&argc, argv); | ||
244 | HealthHidlEnvironment::Instance()->init(&argc, argv); | ||
245 | int status = RUN_ALL_TESTS(); | ||
246 | LOG(INFO) << "Test result = " << status; | ||
247 | return status; | ||
248 | } | ||
diff --git a/health/Android.bp b/health/Android.bp index 2c931e59..ca89713e 100644 --- a/health/Android.bp +++ b/health/Android.bp | |||
@@ -5,4 +5,5 @@ subdirs = [ | |||
5 | "1.0/default/libhealthd", | 5 | "1.0/default/libhealthd", |
6 | "1.0/vts/functional", | 6 | "1.0/vts/functional", |
7 | "2.0", | 7 | "2.0", |
8 | "2.0/vts/functional", | ||
8 | ] | 9 | ] |