blob: 7f18853b1ed680643363e43ffee92781a37fbb2a [file] [log] [blame]
// Copyright 2021 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 "include/lib/driver-integration-test/fixture.h"
#include <fidl/fuchsia.board.test/cpp/wire.h>
#include <fidl/fuchsia.device.manager/cpp/wire.h>
#include <fidl/fuchsia.driver.framework/cpp/wire.h>
#include <fuchsia/driver/test/cpp/fidl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/device-watcher/cpp/device-watcher.h>
#include <lib/driver_test_realm/realm_builder/cpp/lib.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/global.h>
#include "lib/sys/component/cpp/testing/realm_builder.h"
namespace driver_integration_test {
using namespace component_testing;
zx_status_t IsolatedDevmgr::Create(Args* args, IsolatedDevmgr* out) {
IsolatedDevmgr devmgr;
devmgr.loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);
// Create and build the realm.
auto realm_builder = component_testing::RealmBuilder::Create();
driver_test_realm::Setup(realm_builder);
// Setup Fshost.
if (args->disable_block_watcher) {
realm_builder.AddChild("fshost", "#meta/test-fshost-no-watcher.cm");
} else {
realm_builder.AddChild("fshost", "#meta/test-fshost.cm");
}
realm_builder.AddRoute(Route{
.capabilities = {Protocol{"fuchsia.process.Launcher"}},
.source = {ParentRef()},
.targets = {ChildRef{"fshost"}},
});
realm_builder.AddRoute(Route{
.capabilities = {Protocol{"fuchsia.device.manager.Administrator"}},
.source = {ChildRef{"driver_test_realm"}},
.targets = {ChildRef{"fshost"}},
});
realm_builder.AddRoute(Route{
.capabilities = {Protocol{"fuchsia.hardware.power.statecontrol.Admin"}},
.source = {ChildRef{"driver_test_realm"}},
.targets = {ChildRef{"fshost"}},
});
realm_builder.AddRoute(Route{
.capabilities = {Protocol{"fuchsia.logger.LogSink"}},
.source = {ParentRef()},
.targets = {ChildRef{"fshost"}},
});
realm_builder.AddRoute(Route{
.capabilities = {Protocol{"fuchsia.fshost.BlockWatcher"}, Protocol{"fuchsia.fshost.Admin"}},
.source = {ChildRef{"fshost"}},
.targets = {ParentRef()},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "factory", .rights = fuchsia::io::R_STAR_DIR}},
.source = {ChildRef{"fshost"}},
.targets = {ParentRef()},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "durable", .rights = fuchsia::io::RW_STAR_DIR}},
.source = {ChildRef{"fshost"}},
.targets = {ParentRef()},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "install", .rights = fuchsia::io::RW_STAR_DIR}},
.source = {ChildRef{"fshost"}},
.targets = {ParentRef()},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "tmp", .rights = fuchsia::io::RW_STAR_DIR}},
.source = {ChildRef{"fshost"}},
.targets = {ParentRef()},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "volume", .rights = fuchsia::io::RW_STAR_DIR}},
.source = {ChildRef{"fshost"}},
.targets = {ParentRef()},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "dev-topological", .rights = fuchsia::io::R_STAR_DIR}},
.source = {ChildRef{"driver_test_realm"}},
.targets = {ChildRef{"fshost"}},
});
realm_builder.AddRoute(Route{
.capabilities = {Directory{.name = "dev-class", .rights = fuchsia::io::R_STAR_DIR}},
.source = {ChildRef{"driver_test_realm"}},
.targets = {ChildRef{"fshost"}},
});
// Build the realm.
devmgr.realm_ = std::make_unique<component_testing::RealmRoot>(
realm_builder.Build(devmgr.loop_->dispatcher()));
// Start DriverTestRealm.
fidl::SynchronousInterfacePtr<fuchsia::driver::test::Realm> driver_test_realm;
if (zx_status_t status = devmgr.realm_->component().Connect(driver_test_realm.NewRequest());
status != ZX_OK) {
return status;
}
fuchsia::driver::test::Realm_Start_Result realm_result;
auto realm_args = fuchsia::driver::test::RealmArgs();
realm_args.set_root_driver("fuchsia-boot:///platform-bus#meta/platform-bus.cm");
realm_args.set_driver_log_level(args->log_level);
realm_args.set_board_name(std::string(args->board_name.data()));
realm_args.set_driver_disable(args->driver_disable);
realm_args.set_driver_bind_eager(args->driver_bind_eager);
if (zx_status_t status = driver_test_realm->Start(std::move(realm_args), &realm_result);
status != ZX_OK) {
return status;
}
if (realm_result.is_err()) {
return realm_result.err();
}
// Connect to dev.
fidl::InterfaceHandle<fuchsia::io::Node> dev;
if (zx_status_t status =
devmgr.realm_->component().Connect("dev-topological", dev.NewRequest().TakeChannel());
status != ZX_OK) {
return status;
}
if (zx_status_t status =
fdio_fd_create(dev.TakeChannel().release(), devmgr.devfs_root_.reset_and_get_address());
status != ZX_OK) {
return status;
}
zx::result channel =
device_watcher::RecursiveWaitForFile(devmgr.devfs_root_.get(), "sys/platform/pt/test-board");
if (channel.is_error()) {
return channel.status_value();
}
fidl::ClientEnd<fuchsia_board_test::Board> client_end(std::move(channel.value()));
fidl::WireSyncClient client(std::move(client_end));
for (auto& device : args->device_list) {
std::vector<uint8_t> metadata(device.metadata, device.metadata + device.metadata_size);
const fidl::WireResult result = client->CreateDevice({
.name = fidl::StringView::FromExternal(device.name),
.metadata = fidl::VectorView<uint8_t>::FromExternal(metadata),
.vid = device.vid,
.pid = device.pid,
.did = device.did,
});
if (!result.ok()) {
return result.status();
}
}
*out = std::move(devmgr);
return ZX_OK;
}
zx_status_t IsolatedDevmgr::SuspendDriverManager() {
auto endpoints = fidl::CreateEndpoints<fuchsia_device_manager::Administrator>();
if (endpoints.is_error()) {
return endpoints.error_value();
}
zx_status_t status = realm_->component().Connect(
fidl::DiscoverableProtocolName<fuchsia_device_manager::Administrator>,
endpoints->server.TakeChannel());
if (status != ZX_OK) {
return status;
}
auto result = fidl::WireCall(endpoints->client)->SuspendWithoutExit();
if (!result.ok()) {
return result.status();
}
return ZX_OK;
}
} // namespace driver_integration_test