/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include "Hardware.h" namespace android { namespace hardware { namespace vibrator { namespace V1_3 { namespace implementation { using ::testing::Test; using ::testing::TestParamInfo; using ::testing::ValuesIn; using ::testing::WithParamInterface; class HwApiTest : public Test { protected: static constexpr const char *FILE_NAMES[]{ "device/autocal", "device/ol_lra_period", "activate", "duration", "state", "device/rtp_input", "device/mode", "device/set_sequencer", "device/scale", "device/ctrl_loop", "device/lp_trigger_effect", "device/lra_wave_shape", "device/od_clamp", }; static constexpr const char *REQUIRED[]{ "activate", "duration", "state", }; public: void SetUp() override { std::string prefix; for (auto n : FILE_NAMES) { auto name = std::filesystem::path(n); auto path = std::filesystem::path(mFilesDir.path) / name; fs_mkdirs(path.c_str(), S_IRWXU); std::ofstream touch{path}; mFileMap[name] = path; } prefix = std::filesystem::path(mFilesDir.path) / ""; setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true); mHwApi = HwApi::Create(); for (auto n : REQUIRED) { auto name = std::filesystem::path(n); auto path = std::filesystem::path(mEmptyDir.path) / name; fs_mkdirs(path.c_str(), S_IRWXU); std::ofstream touch{path}; } prefix = std::filesystem::path(mEmptyDir.path) / ""; setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true); mNoApi = HwApi::Create(); } void TearDown() override { verifyContents(); } protected: // Set expected file content for a test. template void expectContent(const std::string &name, const T &value) { mExpectedContent[name] << value << std::endl; } // Set actual file content for an input test. template void updateContent(const std::string &name, const T &value) { std::ofstream(mFileMap[name]) << value << std::endl; } template void expectAndUpdateContent(const std::string &name, const T &value) { expectContent(name, value); updateContent(name, value); } // Compare all file contents against expected contents. void verifyContents() { for (auto &a : mFileMap) { std::ifstream file{a.second}; std::string expect = mExpectedContent[a.first].str(); std::string actual = std::string(std::istreambuf_iterator(file), std::istreambuf_iterator()); EXPECT_EQ(expect, actual) << a.first; } } // TODO(eliptus): Determine how to induce errors in required files static bool isRequired(const std::string &name) { for (auto n : REQUIRED) { if (std::string(n) == name) { return true; } } return false; } static auto ParamNameFixup(std::string str) { std::replace(str.begin(), str.end(), '/', '_'); return str; } protected: std::unique_ptr mHwApi; std::unique_ptr mNoApi; std::map mFileMap; TemporaryDir mFilesDir; TemporaryDir mEmptyDir; std::map mExpectedContent; }; class CreateTest : public HwApiTest, public WithParamInterface { public: void SetUp() override{}; void TearDown() override{}; static auto PrintParam(const TestParamInfo &info) { return ParamNameFixup(info.param); } static auto &AllParams() { return FILE_NAMES; } }; TEST_P(CreateTest, file_missing) { auto skip = std::string(GetParam()); TemporaryDir dir; std::unique_ptr hwapi; std::string prefix; for (auto n : FILE_NAMES) { auto name = std::string(n); auto path = std::string(dir.path) + "/" + name; if (name == skip) { continue; } fs_mkdirs(path.c_str(), S_IRWXU); std::ofstream touch{path}; } prefix = std::filesystem::path(dir.path) / ""; setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true); hwapi = HwApi::Create(); if (isRequired(skip)) { EXPECT_EQ(nullptr, hwapi); } else { EXPECT_NE(nullptr, hwapi); } } INSTANTIATE_TEST_CASE_P(HwApiTests, CreateTest, ValuesIn(CreateTest::AllParams()), CreateTest::PrintParam); template class HwApiTypedTest : public HwApiTest, public WithParamInterface>> { public: static auto PrintParam(const TestParamInfo &info) { return ParamNameFixup(std::get<0>(info.param)); } static auto MakeParam(std::string name, std::function func) { return std::make_tuple(name, func); } }; using HasTest = HwApiTypedTest; TEST_P(HasTest, success_returnsTrue) { auto param = GetParam(); auto func = std::get<1>(param); EXPECT_TRUE(func(*mHwApi)); } TEST_P(HasTest, success_returnsFalse) { auto param = GetParam(); auto func = std::get<1>(param); EXPECT_FALSE(func(*mNoApi)); } INSTANTIATE_TEST_CASE_P(HwApiTests, HasTest, ValuesIn({ HasTest::MakeParam("device/rtp_input", &Vibrator::HwApi::hasRtpInput), }), HasTest::PrintParam); using SetBoolTest = HwApiTypedTest; TEST_P(SetBoolTest, success_returnsTrue) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); expectContent(name, "1"); EXPECT_TRUE(func(*mHwApi, true)); } TEST_P(SetBoolTest, success_returnsFalse) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); expectContent(name, "0"); EXPECT_TRUE(func(*mHwApi, false)); } TEST_P(SetBoolTest, failure) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); if (isRequired(name)) { GTEST_SKIP(); } EXPECT_FALSE(func(*mNoApi, true)); EXPECT_FALSE(func(*mNoApi, false)); } INSTANTIATE_TEST_CASE_P(HwApiTests, SetBoolTest, ValuesIn({ SetBoolTest::MakeParam("activate", &Vibrator::HwApi::setActivate), SetBoolTest::MakeParam("state", &Vibrator::HwApi::setState), SetBoolTest::MakeParam("device/ctrl_loop", &Vibrator::HwApi::setCtrlLoop), }), SetBoolTest::PrintParam); using SetInt8Test = HwApiTypedTest; TEST_P(SetInt8Test, success) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); int8_t value = std::rand(); expectContent(name, +value); EXPECT_TRUE(func(*mHwApi, value)); } TEST_P(SetInt8Test, failure) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); int8_t value = std::rand(); if (isRequired(name)) { GTEST_SKIP(); } EXPECT_FALSE(func(*mNoApi, value)); } INSTANTIATE_TEST_CASE_P(HwApiTests, SetInt8Test, ValuesIn({ SetInt8Test::MakeParam("device/rtp_input", &Vibrator::HwApi::setRtpInput), }), SetInt8Test::PrintParam); using SetUint8Test = HwApiTypedTest; TEST_P(SetUint8Test, success) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); uint8_t value = std::rand(); expectContent(name, +value); EXPECT_TRUE(func(*mHwApi, value)); } TEST_P(SetUint8Test, failure) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); uint8_t value = std::rand(); if (isRequired(name)) { GTEST_SKIP(); } EXPECT_FALSE(func(*mNoApi, value)); } INSTANTIATE_TEST_CASE_P(HwApiTests, SetUint8Test, ValuesIn({ SetUint8Test::MakeParam("device/scale", &Vibrator::HwApi::setScale), }), SetUint8Test::PrintParam); using SetUint32Test = HwApiTypedTest; TEST_P(SetUint32Test, success) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); uint32_t value = std::rand(); expectContent(name, value); EXPECT_TRUE(func(*mHwApi, value)); } TEST_P(SetUint32Test, failure) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); uint32_t value = std::rand(); if (isRequired(name)) { GTEST_SKIP(); } EXPECT_FALSE(func(*mNoApi, value)); } INSTANTIATE_TEST_CASE_P( HwApiTests, SetUint32Test, ValuesIn({ SetUint32Test::MakeParam("device/ol_lra_period", &Vibrator::HwApi::setOlLraPeriod), SetUint32Test::MakeParam("duration", &Vibrator::HwApi::setDuration), SetUint32Test::MakeParam("device/lp_trigger_effect", &Vibrator::HwApi::setLpTriggerEffect), SetUint32Test::MakeParam("device/lra_wave_shape", &Vibrator::HwApi::setLraWaveShape), SetUint32Test::MakeParam("device/od_clamp", &Vibrator::HwApi::setOdClamp), }), SetUint32Test::PrintParam); using SetStringTest = HwApiTypedTest; TEST_P(SetStringTest, success) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); std::string value = TemporaryFile().path; expectContent(name, value); EXPECT_TRUE(func(*mHwApi, value)); } TEST_P(SetStringTest, failure) { auto param = GetParam(); auto name = std::get<0>(param); auto func = std::get<1>(param); std::string value = TemporaryFile().path; if (isRequired(name)) { GTEST_SKIP(); } EXPECT_FALSE(func(*mNoApi, value)); } INSTANTIATE_TEST_CASE_P( HwApiTests, SetStringTest, ValuesIn({ SetStringTest::MakeParam("device/autocal", &Vibrator::HwApi::setAutocal), SetStringTest::MakeParam("device/mode", &Vibrator::HwApi::setMode), SetStringTest::MakeParam("device/set_sequencer", &Vibrator::HwApi::setSequencer), }), SetStringTest::PrintParam); } // namespace implementation } // namespace V1_3 } // namespace vibrator } // namespace hardware } // namespace android