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