| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "aml-light.h" |
| |
| #include <fuchsia/hardware/gpio/cpp/banjo-mock.h> |
| #include <fuchsia/hardware/pwm/cpp/banjo-mock.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/fidl-async/cpp/bind.h> |
| |
| #include <cmath> |
| |
| #include <fbl/alloc_checker.h> |
| |
| bool operator==(const pwm_config_t& lhs, const pwm_config_t& rhs) { |
| return (lhs.polarity == rhs.polarity) && (lhs.period_ns == rhs.period_ns) && |
| (lhs.duty_cycle == rhs.duty_cycle) && (lhs.mode_config_size == rhs.mode_config_size) && |
| (reinterpret_cast<aml_pwm::mode_config*>(lhs.mode_config_buffer)->mode == |
| reinterpret_cast<aml_pwm::mode_config*>(rhs.mode_config_buffer)->mode); |
| } |
| |
| namespace aml_light { |
| |
| class FakeAmlLight : public AmlLight { |
| public: |
| static std::unique_ptr<FakeAmlLight> Create(const gpio_protocol_t* gpio, |
| std::optional<const pwm_protocol_t*> pwm, |
| zx_duration_t pwm_period = 170'625) { |
| fbl::AllocChecker ac; |
| auto device = fbl::make_unique_checked<FakeAmlLight>(&ac); |
| if (!ac.check()) { |
| zxlogf(ERROR, "%s: device object alloc failed", __func__); |
| return nullptr; |
| } |
| device->lights_.emplace_back( |
| "test", ddk::GpioProtocolClient(gpio), |
| pwm.has_value() ? std::optional<ddk::PwmProtocolClient>(*pwm) : std::nullopt, |
| zx::duration(pwm_period)); |
| EXPECT_OK(device->lights_.back().Init(true)); |
| return device; |
| } |
| |
| explicit FakeAmlLight() : AmlLight(nullptr) {} |
| |
| zx_status_t Connect(async_dispatcher_t* dispatcher, zx::channel request) { |
| return fidl::BindSingleInFlightOnly(dispatcher, std::move(request), this); |
| } |
| }; |
| |
| class AmlLightTest : public zxtest::Test { |
| public: |
| void Init() { |
| loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigAttachToCurrentThread); |
| |
| zx::channel server; |
| ASSERT_OK(zx::channel::create(0, &client_, &server)); |
| ASSERT_OK(loop_->StartThread("aml-light-test-loop")); |
| ASSERT_OK(light_->Connect(loop_->dispatcher(), std::move(server))); |
| } |
| |
| void TearDown() override { |
| gpio_.VerifyAndClear(); |
| pwm_.VerifyAndClear(); |
| |
| loop_->Quit(); |
| loop_->JoinThreads(); |
| } |
| |
| protected: |
| friend class FakeAmlLight; |
| |
| std::unique_ptr<FakeAmlLight> light_; |
| |
| ddk::MockGpio gpio_; |
| ddk::MockPwm pwm_; |
| |
| zx::channel client_; |
| |
| private: |
| std::unique_ptr<async::Loop> loop_; |
| }; |
| |
| TEST_F(AmlLightTest, GetInfoTest1) { |
| pwm_.ExpectEnable(ZX_OK); |
| aml_pwm::mode_config regular = {aml_pwm::ON, {}}; |
| pwm_config_t init_config = {false, 170625, 100.0, reinterpret_cast<uint8_t*>(®ular), |
| sizeof(regular)}; |
| pwm_.ExpectSetConfig(ZX_OK, init_config); |
| |
| auto gpio = gpio_.GetProto(); |
| auto pwm = pwm_.GetProto(); |
| light_ = FakeAmlLight::Create(gpio, pwm); |
| ASSERT_NOT_NULL(light_); |
| Init(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_light::Light> client(std::move(client_)); |
| auto result = client->GetInfo(0); |
| EXPECT_OK(result.status()); |
| EXPECT_FALSE(result->is_error()); |
| EXPECT_EQ(strcmp(result->value()->info.name.begin(), "test"), 0); |
| EXPECT_EQ(result->value()->info.capability, Capability::kBrightness); |
| } |
| |
| TEST_F(AmlLightTest, GetInfoTest2) { |
| gpio_.ExpectWrite(ZX_OK, true); |
| |
| auto gpio = gpio_.GetProto(); |
| light_ = FakeAmlLight::Create(gpio, std::nullopt); |
| ASSERT_NOT_NULL(light_); |
| Init(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_light::Light> client(std::move(client_)); |
| auto result = client->GetInfo(0); |
| EXPECT_OK(result.status()); |
| EXPECT_FALSE(result->is_error()); |
| EXPECT_EQ(strcmp(result->value()->info.name.begin(), "test"), 0); |
| EXPECT_EQ(result->value()->info.capability, Capability::kSimple); |
| } |
| |
| TEST_F(AmlLightTest, SetValueTest1) { |
| gpio_.ExpectWrite(ZX_OK, true); |
| |
| auto gpio = gpio_.GetProto(); |
| light_ = FakeAmlLight::Create(gpio, std::nullopt); |
| ASSERT_NOT_NULL(light_); |
| Init(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_light::Light> client(std::move(client_)); |
| { |
| auto get_result = client->GetCurrentSimpleValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, true); |
| } |
| { |
| auto get_result = client->GetCurrentSimpleValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, true); |
| } |
| { |
| gpio_.ExpectWrite(ZX_OK, false); |
| auto set_result = client->SetSimpleValue(0, false); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| auto get_result = client->GetCurrentSimpleValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, false); |
| } |
| { |
| gpio_.ExpectWrite(ZX_OK, true); |
| auto set_result = client->SetSimpleValue(0, true); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| gpio_.ExpectWrite(ZX_OK, true); |
| auto set_result = client->SetSimpleValue(0, true); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| auto get_result = client->GetCurrentSimpleValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, true); |
| } |
| } |
| |
| TEST_F(AmlLightTest, SetValueTest2) { |
| pwm_.ExpectEnable(ZX_OK); |
| aml_pwm::mode_config regular = {aml_pwm::ON, {}}; |
| pwm_config_t config = {false, 170625, 100.0, reinterpret_cast<uint8_t*>(®ular), |
| sizeof(regular)}; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| |
| auto gpio = gpio_.GetProto(); |
| auto pwm = pwm_.GetProto(); |
| light_ = FakeAmlLight::Create(gpio, pwm); |
| ASSERT_NOT_NULL(light_); |
| Init(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_light::Light> client(std::move(client_)); |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 1.0); |
| } |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 1.0); |
| } |
| { |
| config.duty_cycle = 0; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| auto set_result = client->SetBrightnessValue(0, 0.0); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 0.0); |
| } |
| { |
| config.duty_cycle = 20.0; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| auto set_result = client->SetBrightnessValue(0, 0.2); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| auto set_result = client->SetBrightnessValue(0, 0.2); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 0.2); |
| } |
| } |
| |
| TEST_F(AmlLightTest, SetInvalidValueTest) { |
| pwm_.ExpectEnable(ZX_OK); |
| aml_pwm::mode_config regular = {aml_pwm::ON, {}}; |
| pwm_config_t config = {false, 170625, 100.0, reinterpret_cast<uint8_t*>(®ular), |
| sizeof(regular)}; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| |
| auto gpio = gpio_.GetProto(); |
| auto pwm = pwm_.GetProto(); |
| light_ = FakeAmlLight::Create(gpio, pwm); |
| ASSERT_NOT_NULL(light_); |
| Init(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_light::Light> client(std::move(client_)); |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 1.0); |
| } |
| { |
| auto set_result = client->SetBrightnessValue(0, 3.2); |
| EXPECT_OK(set_result.status()); |
| EXPECT_TRUE(set_result->is_error()); |
| } |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 1.0); |
| } |
| { |
| auto set_result = client->SetBrightnessValue(0, -0.225); |
| EXPECT_OK(set_result.status()); |
| EXPECT_TRUE(set_result->is_error()); |
| } |
| { |
| auto set_result = client->SetBrightnessValue(0, NAN); |
| EXPECT_OK(set_result.status()); |
| EXPECT_TRUE(set_result->is_error()); |
| } |
| { |
| auto get_result = client->GetCurrentBrightnessValue(0); |
| EXPECT_OK(get_result.status()); |
| EXPECT_FALSE(get_result->is_error()); |
| EXPECT_EQ(get_result->value()->value, 1.0); |
| } |
| } |
| |
| TEST_F(AmlLightTest, SetValueTestNelson) { |
| pwm_.ExpectEnable(ZX_OK); |
| aml_pwm::mode_config regular = {aml_pwm::ON, {}}; |
| pwm_config_t config = {false, 500'000, 100.0, reinterpret_cast<uint8_t*>(®ular), |
| sizeof(regular)}; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| |
| auto gpio = gpio_.GetProto(); |
| auto pwm = pwm_.GetProto(); |
| light_ = FakeAmlLight::Create(gpio, pwm, 500'000); |
| ASSERT_NOT_NULL(light_); |
| Init(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_light::Light> client(std::move(client_)); |
| |
| { |
| config.duty_cycle = 0; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| auto set_result = client->SetBrightnessValue(0, 0.0); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| config.duty_cycle = 20.0; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| auto set_result = client->SetBrightnessValue(0, 0.2); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| { |
| config.duty_cycle = 100.0; |
| pwm_.ExpectSetConfig(ZX_OK, config); |
| auto set_result = client->SetBrightnessValue(0, 1.0); |
| EXPECT_OK(set_result.status()); |
| EXPECT_FALSE(set_result->is_error()); |
| } |
| } |
| |
| } // namespace aml_light |