blob: 17317d7709574c92651a8338d1a272127df3d966 [file] [log] [blame]
// Copyright 2023 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 "lib/driver/devicetree/testing/board-test-helper.h"
#include <fcntl.h>
#include <fidl/fuchsia.driver.test/cpp/wire.h>
#include <lib/device-watcher/cpp/device-watcher.h>
#include <lib/driver_test_realm/realm_builder/cpp/lib.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/io.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/defer.h>
#include <lib/sync/cpp/completion.h>
#include <lib/sys/component/cpp/testing/realm_builder_types.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/vfs/cpp/service.h>
#include <lib/zbi-format/zbi.h>
#include <sys/stat.h>
#include <zircon/errors.h>
namespace fdf_devicetree::testing {
namespace {
using namespace component_testing;
namespace fdt = fuchsia_driver_test;
zx::result<zx::vmo> LoadDevicetreeBlob(const char* path) {
int file = open(path, O_RDONLY);
if (file == -1) {
return zx::error(ZX_ERR_IO);
}
zx::vmo out;
zx_status_t status = fdio_get_vmo_copy(file, out.reset_and_get_address());
if (status != ZX_OK) {
return zx::error(status);
}
return zx::ok(std::move(out));
}
} // namespace
BoardTestHelper::~BoardTestHelper() {
libsync::Completion teardown_complete;
realm_->Teardown(
[&](fit::result<fuchsia::component::Error> result) { teardown_complete.Signal(); });
teardown_complete.Wait();
}
void BoardTestHelper::SetupRealm() {
auto realm_builder = component_testing::RealmBuilder::Create();
realm_builder_ = std::make_unique<component_testing::RealmBuilder>(std::move(realm_builder));
driver_test_realm::Setup(*realm_builder_);
}
zx::result<> BoardTestHelper::StartRealm() {
realm_ = std::make_unique<component_testing::RealmRoot>(realm_builder_->Build(dispatcher_));
auto client = realm_->component().Connect<fdt::Realm>();
if (client.is_error()) {
FX_LOGS(ERROR) << "Failed to connect to driver test realm : " << client.status_string();
return client.take_error();
}
zx::result dtb = LoadDevicetreeBlob(dtb_path_.c_str());
if (dtb.is_error()) {
FX_LOGS(ERROR) << "Failed to open dtb : " << dtb.status_string();
return dtb.take_error();
}
fidl::WireSyncClient driver_test_realm{std::move(*client)};
fidl::Arena arena;
auto args = fdt::wire::RealmArgs::Builder(arena)
.root_driver("fuchsia-boot:///platform-bus#meta/platform-bus.cm")
.devicetree(std::move(*dtb))
.platform_vid(platform_id_.vid)
.platform_pid(platform_id_.pid)
.board_name(platform_id_.board_name)
.Build();
auto start_result = driver_test_realm->Start(args);
if (start_result.status() != ZX_OK) {
FX_LOGS(ERROR) << "Failed to start driver test realm : " << start_result.status_string();
return zx::error(start_result.status());
}
if (start_result->is_error()) {
FX_LOGS(ERROR) << "Failed to start driver test realm : " << start_result.error();
return start_result->take_error();
}
return zx::ok();
}
zx::result<> BoardTestHelper::WaitOnDevices(const std::vector<std::string>& device_paths) {
auto [client_end, server_end] = fidl::Endpoints<fuchsia_io::Directory>::Create();
auto result = realm_->component().exposed()->Open("dev-topological", fuchsia::io::PERM_READABLE,
{}, server_end.TakeChannel());
if (result != ZX_OK) {
FX_LOGS(ERROR) << "Failed to open dev-topological : " << zx_status_get_string(result);
return zx::error(result);
}
int dev_fd;
result = fdio_fd_create(client_end.TakeChannel().release(), &dev_fd);
if (result != ZX_OK) {
FX_LOGS(ERROR) << "Failed to create fd : " << zx_status_get_string(result);
return zx::error(result);
}
auto close_fd = fit::defer([&dev_fd]() { close(dev_fd); });
for (const auto& path : device_paths) {
FX_LOGS(INFO) << "Waiting for " << path;
auto wait_result = device_watcher::RecursiveWaitForFile(dev_fd, path.c_str());
if (wait_result.is_error()) {
FX_LOGS(ERROR) << "Failed to wait for " << path << " : " << wait_result.status_string();
return wait_result.take_error();
}
FX_LOGS(INFO) << "Found " << path;
}
return zx::ok();
}
} // namespace fdf_devicetree::testing