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