blob: e705230b2cd328084e3dc499bf7e63b07e5b76d2 [file] [log] [blame]
// 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/devices/bin/driver_manager/tests/driver_runner_test_fixture.h"
namespace driver_runner {
// BEGIN DEATH TESTS
// _________-----_____
// _____------ __ ----_
// ___---- ___------ \
// ----________ ---- \
// -----__ | _____)
// __- / \
// _______----- ___-- \ /)\
// ------_______ ---____ \__/ /
// -----__ \ -- _ /\
// --__--__ \_____/ \_/\
// ----| / |
// | |___________|
// | | ((_(_)| )_)
// | \_((_(_)|/(_)
// \ (
// \_____________)
//
// These tests test the allowlist for the fuchsia.device/Controller
// interface. They first test the interface with an class name that
// is on the allowlist, then with a classname that is not on the allowlist
// to make sure it fails.
const char* kAllowedClassName = "driver_runner_test";
const char* kDisallowedClassName = "Not_on_allowlist";
const char* kAllowedChildName = "node-1";
const char* kBannedChildName = "node-0";
// This type of test creates two children, one with an allowed class name
// and the other without.
class DriverRunnerDeathTest : public DriverRunnerTest {
public:
void SetUp() override {
SetupDriverRunner();
root_driver_ = StartRootDriver();
ASSERT_EQ(ZX_OK, root_driver_.status_value());
allowed_child_ =
root_driver_->driver->AddChild(kAllowedChildName, true, false, kAllowedClassName);
banned_child_ =
root_driver_->driver->AddChild(kBannedChildName, true, false, kDisallowedClassName);
EXPECT_TRUE(RunLoopUntilIdle());
allowed_controller_ = ConnectToDeviceController(kAllowedChildName);
banned_controller_ = ConnectToDeviceController(kBannedChildName);
}
protected:
zx::result<StartDriverResult> root_driver_;
std::shared_ptr<CreatedChild> allowed_child_, banned_child_;
fidl::WireClient<fuchsia_device::Controller> allowed_controller_, banned_controller_;
};
void TryConnectToController(fidl::WireClient<fuchsia_device::Controller>& controller,
async::TestLoop& loop) {
auto controller_endpoints = fidl::Endpoints<fuchsia_device::Controller>::Create();
fidl::OneWayStatus result =
controller->ConnectToController(std::move(controller_endpoints.server));
ASSERT_TRUE(loop.RunUntilIdle());
ASSERT_EQ(result.status(), ZX_OK);
}
// Start the root driver, add a child node, and verify that the child node's device controller is
// reachable.
TEST_F(DriverRunnerDeathTest, AllowlistCausesConnectToControllerToFail) {
TryConnectToController(allowed_controller_, test_loop());
ASSERT_DEATH(TryConnectToController(banned_controller_, test_loop()),
"Undeclared DEVFS_USAGE detected");
}
void TryConnectToDeviceFidl(fidl::WireClient<fuchsia_device::Controller>& controller,
async::TestLoop& loop) {
auto controller_endpoints = fidl::Endpoints<fuchsia_device::Controller>::Create();
fidl::OneWayStatus result =
controller->ConnectToDeviceFidl(controller_endpoints.server.TakeChannel());
ASSERT_TRUE(loop.RunUntilIdle());
ASSERT_EQ(result.status(), ZX_OK);
}
// This just verifies that the call was able to be made and now blocked by the allowlist. It does
// not check that the device actually connected an interface.
TEST_F(DriverRunnerDeathTest, AllowlistCausesConnectToDeviceFidlToFail) {
TryConnectToDeviceFidl(allowed_controller_, test_loop());
ASSERT_DEATH(TryConnectToDeviceFidl(banned_controller_, test_loop()),
"Undeclared DEVFS_USAGE detected");
}
void TryBind(fidl::WireClient<fuchsia_device::Controller>& controller, async::TestLoop& loop) {
auto controller_endpoints = fidl::Endpoints<fuchsia_device::Controller>::Create();
controller->Bind(fidl::StringView::FromExternal(second_driver_url))
.Then([](fidl::WireUnownedResult<fuchsia_device::Controller::Bind>& reply) {
ASSERT_EQ(reply.status(), ZX_OK);
});
ASSERT_TRUE(loop.RunUntilIdle());
}
TEST_F(DriverRunnerDeathTest, AllowlistCausesBindToFail) {
PrepareRealmForDriverComponentStart("dev.node-1", second_driver_url);
driver_index().set_match_callback([](auto args) -> zx::result<FakeDriverIndex::MatchResult> {
EXPECT_EQ(args.driver_url_suffix().get(), second_driver_url);
return zx::ok(FakeDriverIndex::MatchResult{
.url = second_driver_url,
});
});
TryBind(allowed_controller_, test_loop());
ASSERT_DEATH(TryBind(banned_controller_, test_loop()), "Undeclared DEVFS_USAGE detected");
}
void TryScheduleUnbind(fidl::WireClient<fuchsia_device::Controller>& controller,
async::TestLoop& loop) {
auto controller_endpoints = fidl::Endpoints<fuchsia_device::Controller>::Create();
controller->ScheduleUnbind().Then(
[](fidl::WireUnownedResult<fuchsia_device::Controller::ScheduleUnbind>& reply) {
ASSERT_EQ(reply.status(), ZX_OK);
});
ASSERT_TRUE(loop.RunUntilIdle());
}
TEST_F(DriverRunnerDeathTest, AllowlistCausesScheduleUnbindToFail) {
TryScheduleUnbind(allowed_controller_, test_loop());
ASSERT_DEATH(TryScheduleUnbind(banned_controller_, test_loop()),
"Undeclared DEVFS_USAGE detected");
}
void TryUnbindChildren(fidl::WireClient<fuchsia_device::Controller>& controller,
async::TestLoop& loop) {
auto controller_endpoints = fidl::Endpoints<fuchsia_device::Controller>::Create();
controller->UnbindChildren().Then(
[](fidl::WireUnownedResult<fuchsia_device::Controller::UnbindChildren>& reply) {
ASSERT_EQ(reply.status(), ZX_OK);
});
ASSERT_TRUE(loop.RunUntilIdle());
}
TEST_F(DriverRunnerDeathTest, AllowlistCausesUnbindChildrenToFail) {
TryUnbindChildren(allowed_controller_, test_loop());
ASSERT_DEATH(TryUnbindChildren(banned_controller_, test_loop()),
"Undeclared DEVFS_USAGE detected");
}
} // namespace driver_runner