[devmgr][coord] Add test for binding devices
This test goes through the full bind of a device with a devhost, and the
disconnection of the devhost.
ZX-3286
Test: Ran Fuchsia and /system/test/ddk tests.
Change-Id: Ibfc9bc5a2f041772130d9417cd9e032c75b7b587
diff --git a/system/core/devmgr/devmgr/coordinator-test.cpp b/system/core/devmgr/devmgr/coordinator-test.cpp
index fff1204..9660899 100644
--- a/system/core/devmgr/devmgr/coordinator-test.cpp
+++ b/system/core/devmgr/devmgr/coordinator-test.cpp
@@ -4,10 +4,15 @@
#include <set>
+#include <fbl/algorithm.h>
+#include <fuchsia/device/manager/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
+#include <lib/fidl/coding.h>
#include <unittest/unittest.h>
+#include <zircon/fidl.h>
#include "coordinator.h"
+#include "devmgr.h"
namespace devmgr {
zx::channel fs_clone(const char* path) {
@@ -116,6 +121,7 @@
zx_status_t status = coordinator.InitializeCoreDevices();
ASSERT_EQ(ZX_OK, status);
+ coordinator.set_running(true);
std::set<const devmgr::Driver*> drivers;
auto callback = [&coordinator, &drivers](devmgr::Driver* drv, const char* version) {
@@ -132,10 +138,88 @@
END_TEST;
}
+bool bind_devices() {
+ BEGIN_TEST;
+
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ devmgr::Coordinator coordinator(default_config(loop.dispatcher()));
+
+ zx_status_t status = coordinator.InitializeCoreDevices();
+ ASSERT_EQ(ZX_OK, status);
+
+ // Initialize devfs.
+ devmgr::devfs_init(&coordinator.root_device(), loop.dispatcher());
+ status = devmgr::devfs_publish(&coordinator.root_device(), &coordinator.test_device());
+ ASSERT_EQ(ZX_OK, status);
+ coordinator.set_running(true);
+
+ // Add the device.
+ zx::channel local, remote;
+ status = zx::channel::create(0, &local, &remote);
+ ASSERT_EQ(ZX_OK, status);
+ status = coordinator.AddDevice(&coordinator.test_device(), std::move(local),
+ nullptr /* props_data */, 0 /* props_count */,
+ "mock-device", ZX_PROTOCOL_TEST, nullptr /* driver_path */,
+ nullptr /* args */, false /* invisible */,
+ zx::channel() /* client_remote */);
+ ASSERT_EQ(ZX_OK, status);
+ ASSERT_EQ(1, coordinator.devices().size_slow());
+
+ // Add the driver.
+ devmgr::find_loadable_drivers("/boot/driver/test",
+ fit::bind_member(&coordinator,
+ &devmgr::Coordinator::DriverAdded));
+ loop.RunUntilIdle();
+ ASSERT_FALSE(coordinator.drivers().is_empty());
+
+ // Bind the device to a fake devhost.
+ devmgr::Device* dev = &coordinator.devices().front();
+ devmgr::Devhost host;
+ dev->host = &host;
+ status = coordinator.BindDevice(dev, "/boot/driver/test/mock-device.so");
+ ASSERT_EQ(ZX_OK, status);
+
+ // Wait for the BindDriver request.
+ zx_signals_t pending;
+ status = remote.wait_one(ZX_CHANNEL_READABLE, zx::time::infinite(), &pending);
+ ASSERT_EQ(ZX_OK, status);
+ ASSERT_TRUE(pending & ZX_CHANNEL_READABLE);
+
+ // Read the BindDriver request.
+ uint8_t bytes[ZX_CHANNEL_MAX_MSG_BYTES];
+ zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
+ uint32_t actual_bytes;
+ uint32_t actual_handles;
+ status = remote.read(0, bytes, sizeof(bytes), &actual_bytes, handles, fbl::count_of(handles),
+ &actual_handles);
+ ASSERT_EQ(ZX_OK, status);
+ ASSERT_LT(0, actual_bytes);
+ ASSERT_EQ(1, actual_handles);
+ status = zx_handle_close(handles[0]);
+ ASSERT_EQ(ZX_OK, status);
+
+ // Validate the BindDriver request.
+ auto hdr = reinterpret_cast<fidl_message_header_t*>(bytes);
+ ASSERT_EQ(fuchsia_device_manager_ControllerBindDriverOrdinal, hdr->ordinal);
+ status = fidl_decode(&fuchsia_device_manager_ControllerBindDriverRequestTable, bytes,
+ actual_bytes, handles, actual_handles, nullptr);
+ ASSERT_EQ(ZX_OK, status);
+ auto req = reinterpret_cast<fuchsia_device_manager_ControllerBindDriverRequest*>(bytes);
+ ASSERT_STR_EQ("/boot/driver/test/mock-device.so", req->driver_path.data);
+
+ // Reset the fake devhost connection.
+ dev->host = nullptr;
+ remote.reset();
+ loop.RunUntilIdle();
+
+ END_TEST;
+}
+
BEGIN_TEST_CASE(coordinator_tests)
RUN_TEST(initialize_core_devices)
RUN_TEST(open_virtcon)
RUN_TEST(dump_state)
RUN_TEST(find_loadable_drivers)
RUN_TEST(bind_drivers)
+RUN_TEST(bind_devices)
END_TEST_CASE(coordinator_tests)
diff --git a/system/core/devmgr/devmgr/coordinator.h b/system/core/devmgr/devmgr/coordinator.h
index e7100d5..9148910 100644
--- a/system/core/devmgr/devmgr/coordinator.h
+++ b/system/core/devmgr/devmgr/coordinator.h
@@ -371,7 +371,9 @@
}
void set_dmctl_socket(zx::socket dmctl_socket) { dmctl_socket_ = std::move(dmctl_socket); }
+ fbl::DoublyLinkedList<Driver*, Driver::Node>& drivers() { return drivers_; }
const fbl::DoublyLinkedList<Driver*, Driver::Node>& drivers() const { return drivers_; }
+ fbl::DoublyLinkedList<Device*, Device::AllDevicesNode>& devices() { return devices_; }
const fbl::DoublyLinkedList<Device*, Device::AllDevicesNode>& devices() const {
return devices_;
}