1 /*
2 * Copyright (C) 2019 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/file.h>
18 #include <cutils/fs.h>
19 #include <gtest/gtest.h>
20
21 #include <cstdlib>
22 #include <fstream>
23
24 #include "Hardware.h"
25
26 namespace aidl {
27 namespace android {
28 namespace hardware {
29 namespace vibrator {
30
31 using ::testing::Test;
32 using ::testing::TestParamInfo;
33 using ::testing::ValuesIn;
34 using ::testing::WithParamInterface;
35
36 class HwApiTest : public Test {
37 private:
38 static constexpr const char *FILE_NAMES[]{
39 "device/f0_stored",
40 "device/redc_stored",
41 "device/q_stored",
42 "activate",
43 "duration",
44 "state",
45 "device/cp_trigger_duration",
46 "device/cp_trigger_index",
47 "device/cp_trigger_queue",
48 "device/cp_dig_scale",
49 "device/dig_scale",
50 "device/asp_enable",
51 "device/gpio1_fall_index",
52 "device/gpio1_fall_dig_scale",
53 "device/gpio1_rise_index",
54 "device/gpio1_rise_dig_scale",
55 "device/num_waves",
56 "device/available_pwle_segments",
57 "device/pwle",
58 };
59
60 public:
SetUp()61 void SetUp() override {
62 std::string prefix;
63 for (auto n : FILE_NAMES) {
64 auto name = std::filesystem::path(n);
65 auto path = std::filesystem::path(mFilesDir.path) / name;
66 fs_mkdirs(path.c_str(), S_IRWXU);
67 std::ofstream touch{path};
68 mFileMap[name] = path;
69 }
70 prefix = std::filesystem::path(mFilesDir.path) / "";
71 setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true);
72 mHwApi = std::make_unique<HwApi>();
73
74 for (auto n : FILE_NAMES) {
75 auto name = std::filesystem::path(n);
76 auto path = std::filesystem::path(mEmptyDir.path) / name;
77 }
78 prefix = std::filesystem::path(mEmptyDir.path) / "";
79 setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true);
80 mNoApi = std::make_unique<HwApi>();
81 }
82
TearDown()83 void TearDown() override { verifyContents(); }
84
ParamNameFixup(std::string str)85 static auto ParamNameFixup(std::string str) {
86 std::replace(str.begin(), str.end(), '/', '_');
87 return str;
88 }
89
90 protected:
91 // Set expected file content for a test.
92 template <typename T>
expectContent(const std::string & name,const T & value)93 void expectContent(const std::string &name, const T &value) {
94 mExpectedContent[name] << value << std::endl;
95 }
96
97 // Set actual file content for an input test.
98 template <typename T>
updateContent(const std::string & name,const T & value)99 void updateContent(const std::string &name, const T &value) {
100 std::ofstream(mFileMap[name]) << value << std::endl;
101 }
102
103 template <typename T>
expectAndUpdateContent(const std::string & name,const T & value)104 void expectAndUpdateContent(const std::string &name, const T &value) {
105 expectContent(name, value);
106 updateContent(name, value);
107 }
108
109 // Compare all file contents against expected contents.
verifyContents()110 void verifyContents() {
111 for (auto &a : mFileMap) {
112 std::ifstream file{a.second};
113 std::string expect = mExpectedContent[a.first].str();
114 std::string actual = std::string(std::istreambuf_iterator<char>(file),
115 std::istreambuf_iterator<char>());
116 EXPECT_EQ(expect, actual) << a.first;
117 }
118 }
119
120 protected:
121 std::unique_ptr<Vibrator::HwApi> mHwApi;
122 std::unique_ptr<Vibrator::HwApi> mNoApi;
123 std::map<std::string, std::string> mFileMap;
124 TemporaryDir mFilesDir;
125 TemporaryDir mEmptyDir;
126 std::map<std::string, std::stringstream> mExpectedContent;
127 };
128
129 template <typename T>
130 class HwApiTypedTest : public HwApiTest,
131 public WithParamInterface<std::tuple<std::string, std::function<T>>> {
132 public:
PrintParam(const TestParamInfo<typename HwApiTypedTest::ParamType> & info)133 static auto PrintParam(const TestParamInfo<typename HwApiTypedTest::ParamType> &info) {
134 return ParamNameFixup(std::get<0>(info.param));
135 }
MakeParam(std::string name,std::function<T> func)136 static auto MakeParam(std::string name, std::function<T> func) {
137 return std::make_tuple(name, func);
138 }
139 };
140
141 using HasTest = HwApiTypedTest<bool(Vibrator::HwApi &)>;
142
TEST_P(HasTest,success_returnsTrue)143 TEST_P(HasTest, success_returnsTrue) {
144 auto param = GetParam();
145 auto func = std::get<1>(param);
146
147 EXPECT_TRUE(func(*mHwApi));
148 }
149
TEST_P(HasTest,success_returnsFalse)150 TEST_P(HasTest, success_returnsFalse) {
151 auto param = GetParam();
152 auto func = std::get<1>(param);
153
154 EXPECT_FALSE(func(*mNoApi));
155 }
156
157 INSTANTIATE_TEST_CASE_P(
158 HwApiTests, HasTest,
159 ValuesIn({
160 HasTest::MakeParam("device/cp_dig_scale", &Vibrator::HwApi::hasEffectScale),
161 HasTest::MakeParam("device/asp_enable", &Vibrator::HwApi::hasAspEnable),
162 HasTest::MakeParam("device/pwle", &Vibrator::HwApi::hasPwle),
163 }),
164 HasTest::PrintParam);
165
166 using GetBoolTest = HwApiTypedTest<bool(Vibrator::HwApi &, bool *)>;
167
TEST_P(GetBoolTest,success_returnsTrue)168 TEST_P(GetBoolTest, success_returnsTrue) {
169 auto param = GetParam();
170 auto name = std::get<0>(param);
171 auto func = std::get<1>(param);
172 bool expect = true;
173 bool actual = !expect;
174
175 expectAndUpdateContent(name, "1");
176
177 EXPECT_TRUE(func(*mHwApi, &actual));
178 EXPECT_EQ(expect, actual);
179 }
180
TEST_P(GetBoolTest,success_returnsFalse)181 TEST_P(GetBoolTest, success_returnsFalse) {
182 auto param = GetParam();
183 auto name = std::get<0>(param);
184 auto func = std::get<1>(param);
185 bool expect = false;
186 bool actual = !expect;
187
188 expectAndUpdateContent(name, "0");
189
190 EXPECT_TRUE(func(*mHwApi, &actual));
191 EXPECT_EQ(expect, actual);
192 }
193
TEST_P(GetBoolTest,failure)194 TEST_P(GetBoolTest, failure) {
195 auto param = GetParam();
196 auto func = std::get<1>(param);
197 bool value;
198
199 EXPECT_FALSE(func(*mNoApi, &value));
200 }
201
202 INSTANTIATE_TEST_CASE_P(HwApiTests, GetBoolTest,
203 ValuesIn({
204 GetBoolTest::MakeParam("device/asp_enable",
205 &Vibrator::HwApi::getAspEnable),
206 }),
207 GetBoolTest::PrintParam);
208
209 using GetUint32Test = HwApiTypedTest<bool(Vibrator::HwApi &, uint32_t *)>;
210
TEST_P(GetUint32Test,success)211 TEST_P(GetUint32Test, success) {
212 auto param = GetParam();
213 auto name = std::get<0>(param);
214 auto func = std::get<1>(param);
215 uint32_t expect = std::rand();
216 uint32_t actual = ~expect;
217
218 expectAndUpdateContent(name, expect);
219
220 EXPECT_TRUE(func(*mHwApi, &actual));
221 EXPECT_EQ(expect, actual);
222 }
223
TEST_P(GetUint32Test,failure)224 TEST_P(GetUint32Test, failure) {
225 auto param = GetParam();
226 auto func = std::get<1>(param);
227 uint32_t value;
228
229 EXPECT_FALSE(func(*mNoApi, &value));
230 }
231
232 INSTANTIATE_TEST_CASE_P(HwApiTests, GetUint32Test,
233 ValuesIn({
234 GetUint32Test::MakeParam("device/num_waves",
235 &Vibrator::HwApi::getEffectCount),
236 GetUint32Test::MakeParam("device/cp_trigger_duration",
237 &Vibrator::HwApi::getEffectDuration),
238 GetUint32Test::MakeParam("device/available_pwle_segments",
239 &Vibrator::HwApi::getAvailablePwleSegments),
240 }),
241 GetUint32Test::PrintParam);
242
243 using SetBoolTest = HwApiTypedTest<bool(Vibrator::HwApi &, bool)>;
244
TEST_P(SetBoolTest,success_returnsTrue)245 TEST_P(SetBoolTest, success_returnsTrue) {
246 auto param = GetParam();
247 auto name = std::get<0>(param);
248 auto func = std::get<1>(param);
249
250 expectContent(name, "1");
251
252 EXPECT_TRUE(func(*mHwApi, true));
253 }
254
TEST_P(SetBoolTest,success_returnsFalse)255 TEST_P(SetBoolTest, success_returnsFalse) {
256 auto param = GetParam();
257 auto name = std::get<0>(param);
258 auto func = std::get<1>(param);
259
260 expectContent(name, "0");
261
262 EXPECT_TRUE(func(*mHwApi, false));
263 }
264
TEST_P(SetBoolTest,failure)265 TEST_P(SetBoolTest, failure) {
266 auto param = GetParam();
267 auto func = std::get<1>(param);
268
269 EXPECT_FALSE(func(*mNoApi, true));
270 EXPECT_FALSE(func(*mNoApi, false));
271 }
272
273 INSTANTIATE_TEST_CASE_P(HwApiTests, SetBoolTest,
274 ValuesIn({
275 SetBoolTest::MakeParam("activate", &Vibrator::HwApi::setActivate),
276 SetBoolTest::MakeParam("state", &Vibrator::HwApi::setState),
277 SetBoolTest::MakeParam("device/asp_enable",
278 &Vibrator::HwApi::setAspEnable),
279 }),
280 SetBoolTest::PrintParam);
281
282 using SetUint32Test = HwApiTypedTest<bool(Vibrator::HwApi &, uint32_t)>;
283
TEST_P(SetUint32Test,success)284 TEST_P(SetUint32Test, success) {
285 auto param = GetParam();
286 auto name = std::get<0>(param);
287 auto func = std::get<1>(param);
288 uint32_t value = std::rand();
289
290 expectContent(name, value);
291
292 EXPECT_TRUE(func(*mHwApi, value));
293 }
294
TEST_P(SetUint32Test,failure)295 TEST_P(SetUint32Test, failure) {
296 auto param = GetParam();
297 auto func = std::get<1>(param);
298 uint32_t value = std::rand();
299
300 EXPECT_FALSE(func(*mNoApi, value));
301 }
302
303 INSTANTIATE_TEST_CASE_P(
304 HwApiTests, SetUint32Test,
305 ValuesIn({
306 SetUint32Test::MakeParam("device/f0_stored", &Vibrator::HwApi::setF0),
307 SetUint32Test::MakeParam("device/redc_stored", &Vibrator::HwApi::setRedc),
308 SetUint32Test::MakeParam("device/q_stored", &Vibrator::HwApi::setQ),
309 SetUint32Test::MakeParam("duration", &Vibrator::HwApi::setDuration),
310 SetUint32Test::MakeParam("device/cp_trigger_index",
311 &Vibrator::HwApi::setEffectIndex),
312 SetUint32Test::MakeParam("device/cp_dig_scale", &Vibrator::HwApi::setEffectScale),
313 SetUint32Test::MakeParam("device/dig_scale", &Vibrator::HwApi::setGlobalScale),
314 SetUint32Test::MakeParam("device/gpio1_fall_index",
315 &Vibrator::HwApi::setGpioFallIndex),
316 SetUint32Test::MakeParam("device/gpio1_fall_dig_scale",
317 &Vibrator::HwApi::setGpioFallScale),
318 SetUint32Test::MakeParam("device/gpio1_rise_index",
319 &Vibrator::HwApi::setGpioRiseIndex),
320 SetUint32Test::MakeParam("device/gpio1_rise_dig_scale",
321 &Vibrator::HwApi::setGpioRiseScale),
322 }),
323 SetUint32Test::PrintParam);
324
325 using SetStringTest = HwApiTypedTest<bool(Vibrator::HwApi &, std::string)>;
326
TEST_P(SetStringTest,success)327 TEST_P(SetStringTest, success) {
328 auto param = GetParam();
329 auto name = std::get<0>(param);
330 auto func = std::get<1>(param);
331 std::string value = TemporaryFile().path;
332
333 expectContent(name, value);
334
335 EXPECT_TRUE(func(*mHwApi, value));
336 }
337
TEST_P(SetStringTest,failure)338 TEST_P(SetStringTest, failure) {
339 auto param = GetParam();
340 auto func = std::get<1>(param);
341 std::string value = TemporaryFile().path;
342
343 EXPECT_FALSE(func(*mNoApi, value));
344 }
345
346 INSTANTIATE_TEST_CASE_P(HwApiTests, SetStringTest,
347 ValuesIn({
348 SetStringTest::MakeParam("device/cp_trigger_queue",
349 &Vibrator::HwApi::setEffectQueue),
350 SetStringTest::MakeParam("device/pwle",
351 &Vibrator::HwApi::setPwle),
352 }),
353 SetStringTest::PrintParam);
354
355 } // namespace vibrator
356 } // namespace hardware
357 } // namespace android
358 } // namespace aidl
359