blob: bc1c8df27d7b19d16ac3c662023aa112bb708698 [file] [log] [blame]
// Copyright 2022 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.
#ifndef LIB_DRIVER_RUNTIME_TESTING_LOOP_FIXTURE_TEST_LOOP_FIXTURE_H_
#define LIB_DRIVER_RUNTIME_TESTING_LOOP_FIXTURE_TEST_LOOP_FIXTURE_H_
#include <lib/async/cpp/task.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <lib/fdf/testing.h>
#include <lib/sync/cpp/completion.h>
#include <gtest/gtest.h>
namespace gtest {
// An extension of Test class which sets up a driver runtime message loop for
// the test.
//
// Example:
//
// class FooTest : public ::gtest::DriverTestLoopFixture { /* ... */ };
//
// TEST_F(FooTest, TestCase) {
//
// // Initialize an object with the underlying driver runtime dispatcher.
// Foo foo(driver_dispatcher());
//
// /* Run a method on foo in the driver dispatcher */
// RunOnDispatcher([&]() {foo.DoSomething();});
//
// /* Wait until any posted tasks on the dispatcher are complete. */
// WaitUntilIdle();
//
// /* Make assertions about the state of the test case, say about |foo|. */
// }
class DriverTestLoopFixture : public ::testing::Test {
public:
static void WaitUntilIdle() { fdf_testing_wait_until_all_dispatchers_idle(); }
void SetUp() override {
::testing::Test::SetUp();
// When creating a new dispatcher, we need to associate it with some owner so that the driver
// runtime library doesn't complain.
fdf_testing_push_driver(this);
auto dispatcher = fdf::Dispatcher::Create(
FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS, "driver-test-loop",
[this](fdf_dispatcher_t* dispatcher) { dispatcher_shutdown_.Signal(); });
EXPECT_EQ(ZX_OK, dispatcher.status_value());
dispatcher_ = std::move(dispatcher.value());
// Now that we have created the dispatcher we can pop this.
fdf_testing_pop_driver();
}
void TearDown() override {
::testing::Test::TearDown();
ShutdownDriverDispatcher();
}
// Shuts down the driver dispatcher.
void ShutdownDriverDispatcher() {
dispatcher_.ShutdownAsync();
EXPECT_EQ(ZX_OK, dispatcher_shutdown_.Wait());
}
// Posts a task on the driver dispatcher and waits synchronously until it is completed.
void RunOnDispatcher(fit::closure task) {
libsync::Completion task_completion;
async::PostTask(dispatcher_.async_dispatcher(), [task = std::move(task), &task_completion]() {
task();
task_completion.Signal();
});
task_completion.Wait();
}
const fdf::Dispatcher& driver_dispatcher() { return dispatcher_; }
private:
fdf::Dispatcher dispatcher_;
libsync::Completion dispatcher_shutdown_;
};
} // namespace gtest
#endif // LIB_DRIVER_RUNTIME_TESTING_LOOP_FIXTURE_TEST_LOOP_FIXTURE_H_