1 /*
2 * Copyright (C) 2022 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 "calibration/f0_stored",
40 "default/f0_offset",
41 "calibration/redc_stored",
42 "calibration/q_stored",
43 "default/f0_comp_enable",
44 "default/redc_comp_enable",
45 "default/owt_free_space",
46 "default/num_waves",
47 "default/delay_before_stop_playback_us",
48 };
49
50 public:
SetUp()51 void SetUp() override {
52 std::string prefix;
53 for (auto n : FILE_NAMES) {
54 auto name = std::filesystem::path(n);
55 auto path = std::filesystem::path(mFilesDir.path) / name;
56 fs_mkdirs(path.c_str(), S_IRWXU);
57 std::ofstream touch{path};
58 mFileMap[name] = path;
59 }
60 prefix = std::filesystem::path(mFilesDir.path) / "";
61 setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true);
62 mHwApi = std::make_unique<HwApi>();
63
64 for (auto n : FILE_NAMES) {
65 auto name = std::filesystem::path(n);
66 auto path = std::filesystem::path(mEmptyDir.path) / name;
67 }
68 prefix = std::filesystem::path(mEmptyDir.path) / "";
69 setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true);
70 mNoApi = std::make_unique<HwApi>();
71 }
72
TearDown()73 void TearDown() override { verifyContents(); }
74
ParamNameFixup(std::string str)75 static auto ParamNameFixup(std::string str) {
76 std::replace(str.begin(), str.end(), '/', '_');
77 return str;
78 }
79
80 protected:
81 // Set expected file content for a test.
82 template <typename T>
expectContent(const std::string & name,const T & value)83 void expectContent(const std::string &name, const T &value) {
84 mExpectedContent[name] << value << std::endl;
85 }
86
87 // Set actual file content for an input test.
88 template <typename T>
updateContent(const std::string & name,const T & value)89 void updateContent(const std::string &name, const T &value) {
90 std::ofstream(mFileMap[name]) << value << std::endl;
91 }
92
93 template <typename T>
expectAndUpdateContent(const std::string & name,const T & value)94 void expectAndUpdateContent(const std::string &name, const T &value) {
95 expectContent(name, value);
96 updateContent(name, value);
97 }
98
99 // Compare all file contents against expected contents.
verifyContents()100 void verifyContents() {
101 for (auto &a : mFileMap) {
102 std::ifstream file{a.second};
103 std::string expect = mExpectedContent[a.first].str();
104 std::string actual = std::string(std::istreambuf_iterator<char>(file),
105 std::istreambuf_iterator<char>());
106 EXPECT_EQ(expect, actual) << a.first;
107 }
108 }
109
110 protected:
111 std::unique_ptr<Vibrator::HwApi> mHwApi;
112 std::unique_ptr<Vibrator::HwApi> mNoApi;
113 std::map<std::string, std::string> mFileMap;
114 TemporaryDir mFilesDir;
115 TemporaryDir mEmptyDir;
116 std::map<std::string, std::stringstream> mExpectedContent;
117 };
118
119 template <typename T>
120 class HwApiTypedTest : public HwApiTest,
121 public WithParamInterface<std::tuple<std::string, std::function<T>>> {
122 public:
PrintParam(const TestParamInfo<typename HwApiTypedTest::ParamType> & info)123 static auto PrintParam(const TestParamInfo<typename HwApiTypedTest::ParamType> &info) {
124 return ParamNameFixup(std::get<0>(info.param));
125 }
MakeParam(std::string name,std::function<T> func)126 static auto MakeParam(std::string name, std::function<T> func) {
127 return std::make_tuple(name, func);
128 }
129 };
130
131 using HasTest = HwApiTypedTest<bool(Vibrator::HwApi &)>;
132
TEST_P(HasTest,success_returnsTrue)133 TEST_P(HasTest, success_returnsTrue) {
134 auto param = GetParam();
135 auto func = std::get<1>(param);
136
137 EXPECT_TRUE(func(*mHwApi));
138 }
139
TEST_P(HasTest,success_returnsFalse)140 TEST_P(HasTest, success_returnsFalse) {
141 auto param = GetParam();
142 auto func = std::get<1>(param);
143
144 EXPECT_FALSE(func(*mNoApi));
145 }
146
147 INSTANTIATE_TEST_CASE_P(HwApiTests, HasTest,
148 ValuesIn({
149 HasTest::MakeParam("default/owt_free_space",
150 &Vibrator::HwApi::hasOwtFreeSpace),
151 }),
152 HasTest::PrintParam);
153
154 using GetUint32Test = HwApiTypedTest<bool(Vibrator::HwApi &, uint32_t *)>;
155
TEST_P(GetUint32Test,success)156 TEST_P(GetUint32Test, success) {
157 auto param = GetParam();
158 auto name = std::get<0>(param);
159 auto func = std::get<1>(param);
160 uint32_t expect = std::rand();
161 uint32_t actual = ~expect;
162
163 expectAndUpdateContent(name, expect);
164
165 EXPECT_TRUE(func(*mHwApi, &actual));
166 EXPECT_EQ(expect, actual);
167 }
168
TEST_P(GetUint32Test,failure)169 TEST_P(GetUint32Test, failure) {
170 auto param = GetParam();
171 auto func = std::get<1>(param);
172 uint32_t value;
173
174 EXPECT_FALSE(func(*mNoApi, &value));
175 }
176
177 INSTANTIATE_TEST_CASE_P(HwApiTests, GetUint32Test,
178 ValuesIn({
179 GetUint32Test::MakeParam("default/num_waves",
180 &Vibrator::HwApi::getEffectCount),
181 GetUint32Test::MakeParam("default/owt_free_space",
182 &Vibrator::HwApi::getOwtFreeSpace),
183 }),
184 GetUint32Test::PrintParam);
185
186 using SetBoolTest = HwApiTypedTest<bool(Vibrator::HwApi &, bool)>;
187
TEST_P(SetBoolTest,success_returnsTrue)188 TEST_P(SetBoolTest, success_returnsTrue) {
189 auto param = GetParam();
190 auto name = std::get<0>(param);
191 auto func = std::get<1>(param);
192
193 expectContent(name, "1");
194
195 EXPECT_TRUE(func(*mHwApi, true));
196 }
197
TEST_P(SetBoolTest,success_returnsFalse)198 TEST_P(SetBoolTest, success_returnsFalse) {
199 auto param = GetParam();
200 auto name = std::get<0>(param);
201 auto func = std::get<1>(param);
202
203 expectContent(name, "0");
204
205 EXPECT_TRUE(func(*mHwApi, false));
206 }
207
TEST_P(SetBoolTest,failure)208 TEST_P(SetBoolTest, failure) {
209 auto param = GetParam();
210 auto func = std::get<1>(param);
211
212 EXPECT_FALSE(func(*mNoApi, true));
213 EXPECT_FALSE(func(*mNoApi, false));
214 }
215
216 INSTANTIATE_TEST_CASE_P(HwApiTests, SetBoolTest,
217 ValuesIn({
218 SetBoolTest::MakeParam("default/f0_comp_enable",
219 &Vibrator::HwApi::setF0CompEnable),
220 SetBoolTest::MakeParam("default/redc_comp_enable",
221 &Vibrator::HwApi::setRedcCompEnable),
222 }),
223 SetBoolTest::PrintParam);
224
225 using SetUint32Test = HwApiTypedTest<bool(Vibrator::HwApi &, uint32_t)>;
226
TEST_P(SetUint32Test,success)227 TEST_P(SetUint32Test, success) {
228 auto param = GetParam();
229 auto name = std::get<0>(param);
230 auto func = std::get<1>(param);
231 uint32_t value = std::rand();
232
233 expectContent(name, value);
234
235 EXPECT_TRUE(func(*mHwApi, value));
236 }
237
TEST_P(SetUint32Test,failure)238 TEST_P(SetUint32Test, failure) {
239 auto param = GetParam();
240 auto func = std::get<1>(param);
241 uint32_t value = std::rand();
242
243 EXPECT_FALSE(func(*mNoApi, value));
244 }
245
246 INSTANTIATE_TEST_CASE_P(HwApiTests, SetUint32Test,
247 ValuesIn({
248 SetUint32Test::MakeParam("default/f0_offset",
249 &Vibrator::HwApi::setF0Offset),
250 SetUint32Test::MakeParam("default/delay_before_stop_playback_us",
251 &Vibrator::HwApi::setMinOnOffInterval),
252 }),
253 SetUint32Test::PrintParam);
254
255 using SetStringTest = HwApiTypedTest<bool(Vibrator::HwApi &, std::string)>;
256
TEST_P(SetStringTest,success)257 TEST_P(SetStringTest, success) {
258 auto param = GetParam();
259 auto name = std::get<0>(param);
260 auto func = std::get<1>(param);
261 std::string value = TemporaryFile().path;
262
263 expectContent(name, value);
264
265 EXPECT_TRUE(func(*mHwApi, value));
266 }
267
TEST_P(SetStringTest,failure)268 TEST_P(SetStringTest, failure) {
269 auto param = GetParam();
270 auto func = std::get<1>(param);
271 std::string value = TemporaryFile().path;
272
273 EXPECT_FALSE(func(*mNoApi, value));
274 }
275
276 INSTANTIATE_TEST_CASE_P(
277 HwApiTests, SetStringTest,
278 ValuesIn({
279 SetStringTest::MakeParam("calibration/f0_stored", &Vibrator::HwApi::setF0),
280 SetStringTest::MakeParam("calibration/redc_stored", &Vibrator::HwApi::setRedc),
281 SetStringTest::MakeParam("calibration/q_stored", &Vibrator::HwApi::setQ),
282 }),
283 SetStringTest::PrintParam);
284
285 } // namespace vibrator
286 } // namespace hardware
287 } // namespace android
288 } // namespace aidl
289