blob: 8ed86d1dd8038551847b16df2bb05f36cfc5e096 [file] [log] [blame]
// Copyright 2025 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 <fidl/fuchsia.hardware.test/cpp/fidl.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/driver/fake-platform-device/cpp/fake-pdev.h>
#include <lib/driver/metadata/cpp/metadata.h>
#include <lib/driver/metadata/cpp/metadata_server.h>
#include <lib/driver/testing/cpp/driver_runtime.h>
#include <lib/driver/testing/cpp/driver_test.h>
#include "src/lib/testing/predicates/status.h"
#if FUCHSIA_API_LEVEL_AT_LEAST(HEAD)
namespace fdf_metadata::test {
class FakeDriver : public fdf::DriverBase {
public:
static DriverRegistration GetDriverRegistration() {
return FUCHSIA_DRIVER_REGISTRATION_V1(fdf_internal::DriverServer<FakeDriver>::initialize,
fdf_internal::DriverServer<FakeDriver>::destroy);
}
FakeDriver(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: fdf::DriverBase("fake", std::move(start_args), std::move(driver_dispatcher)) {}
zx::result<> Start() override { return zx::ok(); }
void Serve(const fuchsia_hardware_test::Metadata& metadata) {
ASSERT_OK(metadata_server_.Serve(*outgoing(), dispatcher(), metadata));
}
void ForwardAndServe(bool expected_is_serving) {
zx::result is_serving = metadata_server_.ForwardAndServe(*outgoing(), dispatcher(), incoming());
ASSERT_OK(is_serving);
ASSERT_EQ(is_serving.value(), expected_is_serving);
}
void ForwardAndServeFromPDev(bool expected_is_serving) {
zx::result pdev = incoming()->Connect<fuchsia_hardware_platform_device::Service::Device>();
ASSERT_OK(pdev);
zx::result is_serving =
metadata_server_.ForwardAndServe(*outgoing(), dispatcher(), pdev.value());
ASSERT_OK(is_serving);
ASSERT_EQ(is_serving.value(), expected_is_serving);
}
std::optional<fuchsia_driver_framework::Offer> CreateOffer() {
return metadata_server_.CreateOffer();
}
private:
fdf_metadata::MetadataServer<fuchsia_hardware_test::Metadata> metadata_server_;
};
class TestEnvironment : public fdf_testing::Environment {
public:
void InitPdev(const fuchsia_hardware_test::Metadata& metadata) {
ASSERT_FALSE(pdev_.has_value());
fdf_fake::FakePDev& pdev = pdev_.emplace();
pdev.AddFidlMetadata(fuchsia_hardware_test::Metadata::kSerializableName, metadata);
}
void InitMetadataServer(fuchsia_hardware_test::Metadata metadata) {
ASSERT_FALSE(metadata_.has_value());
metadata_.emplace(std::move(metadata));
}
zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) override {
async_dispatcher_t* dispatcher = fdf::Dispatcher::GetCurrent()->async_dispatcher();
if (pdev_.has_value()) {
zx::result result = to_driver_vfs.AddService<fuchsia_hardware_platform_device::Service>(
pdev_.value().GetInstanceHandler(dispatcher));
if (result.is_error()) {
return result.take_error();
}
}
if (metadata_.has_value()) {
zx::result result = metadata_server_.Serve(to_driver_vfs, dispatcher, metadata_.value());
if (result.is_error()) {
return result.take_error();
}
}
return zx::ok();
}
private:
std::optional<fdf_fake::FakePDev> pdev_;
fdf_metadata::MetadataServer<fuchsia_hardware_test::Metadata> metadata_server_;
std::optional<fuchsia_hardware_test::Metadata> metadata_;
};
class FixtureConfig final {
public:
using DriverType = FakeDriver;
using EnvironmentType = TestEnvironment;
};
class MetadataServerTest : public ::testing::Test {
public:
void TearDown() override { ASSERT_OK(driver_test_.StopDriver()); }
protected:
void InitPdev(const fuchsia_hardware_test::Metadata& metadata) {
driver_test_.RunInEnvironmentTypeContext([&](TestEnvironment& env) { env.InitPdev(metadata); });
}
void InitParentMetadataServer(fuchsia_hardware_test::Metadata metadata) {
driver_test_.RunInEnvironmentTypeContext(
[metadata = std::move(metadata)](TestEnvironment& env) {
env.InitMetadataServer(std::move(metadata));
});
}
void StartDriver() { ASSERT_OK(driver_test_.StartDriver()); }
fdf_testing::BackgroundDriverTest<FixtureConfig>& driver_test() { return driver_test_; }
private:
fdf_testing::BackgroundDriverTest<FixtureConfig> driver_test_;
};
// Verify `MetadataServer::Serve()` serves metadata.
TEST_F(MetadataServerTest, ServeMetadata) {
static const fuchsia_hardware_test::Metadata kMetadata({.test_property = "test value"});
StartDriver();
driver_test().RunInDriverContext([](FakeDriver& driver) {
driver.Serve(kMetadata);
// Verify `MetadataServer::CreateOffer()` creates an offer.
ASSERT_TRUE(driver.CreateOffer().has_value());
});
zx::result metadata = fdf_metadata::GetMetadataIfExists<fuchsia_hardware_test::Metadata>(
driver_test().ConnectToDriverSvcDir());
ASSERT_OK(metadata);
ASSERT_EQ(metadata.value(), kMetadata);
}
// Verify `MetadataServer::ForwardAndServe()` can retrieve metadata from a metadata server found in
// its incoming namespace and serve it.
TEST_F(MetadataServerTest, ForwardMetadata) {
static const fuchsia_hardware_test::Metadata kMetadata({.test_property = "test value"});
InitParentMetadataServer(kMetadata);
StartDriver();
driver_test().RunInDriverContext([](FakeDriver& driver) {
driver.ForwardAndServe(true);
// Verify `MetadataServer::CreateOffer()` creates an offer.
ASSERT_TRUE(driver.CreateOffer().has_value());
});
zx::result metadata = fdf_metadata::GetMetadataIfExists<fuchsia_hardware_test::Metadata>(
driver_test().ConnectToDriverSvcDir());
ASSERT_OK(metadata);
ASSERT_EQ(metadata.value(), kMetadata);
}
// Verify `MetadataServer::ForwardAndServe()` does not serve any metadata if it fails to retrieve
// metadata from a given platform device.
TEST_F(MetadataServerTest, ForwardNonExistentMetadata) {
StartDriver();
driver_test().RunInDriverContext([](FakeDriver& driver) {
driver.ForwardAndServe(false);
// Verify `MetadataServer::CreateOffer()` does not create an offer.
ASSERT_FALSE(driver.CreateOffer().has_value());
});
zx::result metadata = fdf_metadata::GetMetadataIfExists<fuchsia_hardware_test::Metadata>(
driver_test().ConnectToDriverSvcDir());
ASSERT_OK(metadata);
ASSERT_FALSE(metadata.value().has_value());
}
// Verify `MetadataServer::ForwardAndServe()` can retrieve metadata from a given platform device and
// serve it.
TEST_F(MetadataServerTest, ForwardPDevMetadata) {
static const fuchsia_hardware_test::Metadata kMetadata({.test_property = "test value"});
InitPdev(kMetadata);
StartDriver();
driver_test().RunInDriverContext([](FakeDriver& driver) {
driver.ForwardAndServeFromPDev(true);
// Verify `MetadataServer::CreateOffer()` creates an offer.
ASSERT_TRUE(driver.CreateOffer().has_value());
});
zx::result metadata = fdf_metadata::GetMetadata<fuchsia_hardware_test::Metadata>(
driver_test().ConnectToDriverSvcDir());
ASSERT_OK(metadata);
ASSERT_EQ(metadata.value(), kMetadata);
}
// Verify `MetadataServer::ForwardAndServe()` does not serve any metadata if it fails to retrieve
// metadata from a given platform device.
TEST_F(MetadataServerTest, ForwardNonExistentPDevMetadata) {
StartDriver();
driver_test().RunInDriverContext([](FakeDriver& driver) {
driver.ForwardAndServeFromPDev(false);
// Verify `MetadataServer::CreateOffer()` does not create an offer.
ASSERT_FALSE(driver.CreateOffer().has_value());
});
zx::result metadata = fdf_metadata::GetMetadataIfExists<fuchsia_hardware_test::Metadata>(
driver_test().ConnectToDriverSvcDir());
ASSERT_OK(metadata);
ASSERT_FALSE(metadata.value().has_value());
}
} // namespace fdf_metadata::test
#endif