Once you are familiar with the Driver Framework v2 testing framework, follow this quick start to write a test for drivers that need to make synchronous FIDL (see driver FIDL test code). If your driver doesn't need to make synchronous FIDL calls, see the driver base test.
To test drivers, unit tests need to have access to the various resources and environments needed by the drivers themselves. For example, these are the library dependencies for the Driver FIDL test:
#include <fidl/fuchsia.driver.component.test/cpp/driver/wire.h> #include <fidl/fuchsia.driver.component.test/cpp/wire.h> #include <lib/async_patterns/testing/cpp/dispatcher_bound.h> #include <lib/component/incoming/cpp/service.h> #include <lib/driver/component/cpp/tests/test_driver.h> #include <lib/driver/incoming/cpp/namespace.h> #include <lib/driver/testing/cpp/driver_lifecycle.h> #include <lib/driver/testing/cpp/driver_runtime.h> #include <lib/driver/testing/cpp/test_environment.h> #include <lib/driver/testing/cpp/test_node.h> #include <lib/fdio/directory.h> #include <gtest/gtest.h>
DispatcherBound is required to test how the driver uses FIDL clients when calling into its environment. It ensures a server-end object runs in a single dispatcher, enabling the test to construct, call methods on, and destroy the object used (see Threading tips in tests).
GTest Runner is a test runner that launches a gtest
binary as a component, parses its output, and translates it to fuchsia.test.Suite
protocol on behalf of the test.
It's good practice for servers to provide a GetInstanceHandler
to easily add server bindings and run them off a binding group. The bindings should be added on the current driver dispatcher. The expectation is that this class is run inside of a dispatcher bound to the environment. For example, Driver FIDL test, line 35-52, provides a handler to the driver service:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/lib/driver/component/cpp/tests/driver_fidl_test.cc" region_tag="provide_handler" adjust_indentation="auto" %}
Creating the driver runtime automatically attaches a foreground dispatcher, Driver FIDL test, line 115:
fdf_testing::DriverRuntime runtime_;
The driver dispatcher is set as a background dispatcher, Driver FIDL test, line 118:
fdf::UnownedSynchronizedDispatcher env_dispatcher_ = runtime_.StartBackgroundDispatcher();
The test node serves the fdf::Node protocol
to the driver, Driver FIDL test, lines 127-128:
async_patterns::TestDispatcherBound<fdf_testing::TestNode> node_server_{ env_dispatcher(), std::in_place, std::string("root")};
The environment can serve both the Zircon and Driver transport based protocols to the driver, Driver FIDL test, lines 131-132:
async_patterns::TestDispatcherBound<fdf_testing::TestEnvironment> test_environment_{ env_dispatcher(), std::in_place};
The custom FIDL server lives on the background environment dispatcher and has to be wrapped in a dispatcher bound, Driver FIDL test, lines 121-124:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/lib/driver/component/cpp/tests/driver_fidl_test.cc" region_tag="custom_server_classes" adjust_indentation="auto" %}
Get the instance handler for the driver protocol, Driver FIDL test, lines 71-74:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/lib/driver/component/cpp/tests/driver_fidl_test.cc" region_tag="get_server_handlers" adjust_indentation="auto" %}
Move the instance handler into our driver's incoming namespace, Driver FIDL test, lines 76-87:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/lib/driver/component/cpp/tests/driver_fidl_test.cc" region_tag="move_server_handlers" adjust_indentation="auto" %}
Create and serve the start_args table
, Driver FIDL test, lines 59-60:
zx::result start_args = node_server_.SyncCall(&fdf_testing::TestNode::CreateStartArgsAndServe); ASSERT_EQ(ZX_OK, start_args.status_value());
Initialize the test environment, Driver FIDL test, lines 65-68:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/lib/driver/component/cpp/tests/driver_fidl_test.cc" region_tag="initialize_test_environment" adjust_indentation="auto" %}
Add the driver under test which will use the foreground dispatcher, Driver FIDL test, lines 167:
fdf_testing::DriverUnderTest<TestDriver> driver_;
Start the driver, Driver FIDL test, lines 237-238:
zx::result result = runtime().RunToCompletion(driver_.SyncCall( &fdf_testing::DriverUnderTest<TestDriver>::Start, std::move(start_args())));
Use the arrow operator on the DriverUnderTest
to add tests for the driver. The arrow operator gives access to the driver type (specified in the DriverUnderTest
template), for example, Driver FIDL test, lines 384-287:
driver().SyncCall([](fdf_testing::DriverUnderTest<TestDriver>* driver) { zx::result result = (*driver)->ServeDriverService(); ASSERT_EQ(ZX_OK, result.status_value()); });
PrepareStop
has to be called manually by tests, Driver FIDL test, line 159:
zx::result result = runtime().RunToCompletion(driver_.PrepareStop());
Execute the following command to run the driver tests (for the iwlwifi driver):
tools/bazel test third_party/iwlwifi/test:iwlwifi_test_pkg