| // Copyright 2024 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 "src/graphics/display/drivers/aml-canvas/aml-canvas-driver.h" |
| |
| #include <fidl/fuchsia.hardware.amlogiccanvas/cpp/wire.h> |
| #include <lib/async_patterns/testing/cpp/dispatcher_bound.h> |
| #include <lib/component/incoming/cpp/service.h> |
| #include <lib/driver/compat/cpp/logging.h> |
| #include <lib/driver/testing/cpp/driver_lifecycle.h> |
| #include <lib/driver/testing/cpp/driver_runtime.h> |
| #include <lib/driver/testing/cpp/test_environment.h> |
| #include <lib/driver/testing/cpp/test_node.h> |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/devices/bus/testing/fake-pdev/fake-pdev.h" |
| #include "src/lib/testing/predicates/status.h" |
| |
| namespace aml_canvas { |
| |
| namespace { |
| |
| class AmlCanvasDriverTest : public ::testing::Test { |
| public: |
| void SetUp() override { |
| zx::result create_start_args_zx_result = |
| node_server_.SyncCall(&fdf_testing::TestNode::CreateStartArgsAndServe); |
| ASSERT_TRUE(create_start_args_zx_result.is_ok()); |
| |
| auto [start_args, incoming_directory_server, outgoing_directory_client] = |
| std::move(create_start_args_zx_result).value(); |
| start_args_ = std::move(start_args); |
| driver_outgoing_ = std::move(outgoing_directory_client); |
| |
| zx::result init_result = test_environment_.SyncCall(&fdf_testing::TestEnvironment::Initialize, |
| std::move(incoming_directory_server)); |
| ASSERT_EQ(ZX_OK, init_result.status_value()); |
| |
| zx::vmo mmio_vmo; |
| static constexpr uint64_t kMmioVmoSize = 0x2000; |
| ASSERT_OK(zx::vmo::create(kMmioVmoSize, 0, &mmio_vmo)); |
| |
| fake_pdev::FakePDevFidl::Config config; |
| config.use_fake_bti = true; |
| config.mmios[0] = fake_pdev::MmioInfo{ |
| .vmo = std::move(mmio_vmo), |
| .offset = 0, |
| .size = kMmioVmoSize, |
| }; |
| fake_pdev_.SyncCall(&fake_pdev::FakePDevFidl::SetConfig, std::move(config)); |
| |
| auto instance_handler = fake_pdev_.SyncCall(&fake_pdev::FakePDevFidl::GetInstanceHandler, |
| async_patterns::PassDispatcher); |
| test_environment_.SyncCall([&](fdf_testing::TestEnvironment* env) { |
| const zx::result result = |
| env->incoming_directory().AddService<fuchsia_hardware_platform_device::Service>( |
| std::move(instance_handler)); |
| ASSERT_TRUE(result.is_ok()); |
| }); |
| } |
| |
| void TearDown() override { |
| driver_.reset(); |
| test_environment_.reset(); |
| fake_pdev_.reset(); |
| node_server_.reset(); |
| } |
| |
| fidl::ClientEnd<fuchsia_io::Directory> CreateDriverSvcClient() { |
| // Open the svc directory in the driver's outgoing, and store a client to it. |
| auto svc_endpoints = fidl::Endpoints<fuchsia_io::Directory>::Create(); |
| |
| zx_status_t status = fdio_open_at(driver_outgoing_.handle()->get(), "/svc", |
| static_cast<uint32_t>(fuchsia_io::OpenFlags::kDirectory), |
| svc_endpoints.server.TakeChannel().release()); |
| EXPECT_EQ(ZX_OK, status); |
| return std::move(svc_endpoints.client); |
| } |
| |
| void StartDriver() { |
| zx::result start_result = runtime_.RunToCompletion(driver_.SyncCall( |
| &fdf_testing::DriverUnderTest<AmlCanvasDriver>::Start, (std::move(start_args_)))); |
| ASSERT_OK(start_result.status_value()); |
| } |
| |
| void StopDriver() { |
| zx::result stop_result = runtime_.RunToCompletion( |
| driver_.SyncCall(&fdf_testing::DriverUnderTest<AmlCanvasDriver>::PrepareStop)); |
| ASSERT_OK(stop_result.status_value()); |
| } |
| |
| fdf_testing::DriverRuntime& runtime() { return runtime_; } |
| async_patterns::TestDispatcherBound<fdf_testing::DriverUnderTest<AmlCanvasDriver>>& driver() { |
| return driver_; |
| } |
| |
| async_dispatcher_t* driver_async_dispatcher() { return driver_dispatcher_->async_dispatcher(); } |
| async_dispatcher_t* env_async_dispatcher() { return env_dispatcher_->async_dispatcher(); } |
| |
| private: |
| // Attaches a foreground dispatcher for us automatically. |
| fdf_testing::DriverRuntime runtime_; |
| |
| // Env and driver dispatchers run in the background because we need to make |
| // sync calls into them. |
| fdf::UnownedSynchronizedDispatcher driver_dispatcher_ = runtime_.StartBackgroundDispatcher(); |
| fdf::UnownedSynchronizedDispatcher env_dispatcher_ = runtime_.StartBackgroundDispatcher(); |
| |
| async_patterns::TestDispatcherBound<fdf_testing::TestNode> node_server_{ |
| env_async_dispatcher(), std::in_place, std::string("root")}; |
| async_patterns::TestDispatcherBound<fake_pdev::FakePDevFidl> fake_pdev_{env_async_dispatcher(), |
| std::in_place}; |
| async_patterns::TestDispatcherBound<fdf_testing::TestEnvironment> test_environment_{ |
| env_async_dispatcher(), std::in_place}; |
| |
| async_patterns::TestDispatcherBound<fdf_testing::DriverUnderTest<AmlCanvasDriver>> driver_{ |
| driver_async_dispatcher(), std::in_place}; |
| |
| fuchsia_driver_framework::DriverStartArgs start_args_; |
| fidl::ClientEnd<fuchsia_io::Directory> driver_outgoing_; |
| }; |
| |
| TEST_F(AmlCanvasDriverTest, Lifecycle) { |
| StartDriver(); |
| StopDriver(); |
| } |
| |
| TEST_F(AmlCanvasDriverTest, ServesAmlogicCanvasDeviceProtocol) { |
| StartDriver(); |
| |
| zx::result canvas_client_end = |
| component::ConnectAtMember<fuchsia_hardware_amlogiccanvas::Service::Device>( |
| CreateDriverSvcClient()); |
| ASSERT_OK(canvas_client_end.status_value()); |
| |
| StopDriver(); |
| } |
| |
| } // namespace |
| |
| } // namespace aml_canvas |