blob: 2107b59c869e49f7033f1150935090eb325271b4 [file] [log] [blame]
// Copyright 2023 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_TESTING_CPP_INTERNAL_TEST_ENVIRONMENT_H_
#define LIB_DRIVER_TESTING_CPP_INTERNAL_TEST_ENVIRONMENT_H_
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.logger/cpp/fidl.h>
#include <lib/driver/outgoing/cpp/outgoing_directory.h>
#include <lib/fdf/dispatcher.h>
namespace fdf_testing::internal {
// The |TestEnvironment| manages the mocked test environment that the driver being tested uses.
// It provides the server backing the driver's incoming namespace. This incoming namespace can
// be customized by the user through the |incoming_directory| method. The |TestEnvironment|
// uses a fdf::OutgoingDirectory which can support driver transport. Therefore it must be used
// with an fdf_dispatcher.
//
// # Thread safety
//
// This class is thread-unsafe. Instances must be managed and used from a synchronized dispatcher.
// See
// https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/thread-safe-async#synchronized-dispatcher
//
// If the dispatcher used for it is the foreground dispatcher, the TestEnvironment does not need to
// be wrapped in a DispatcherBound.
//
// If the dispatcher is a background dispatcher, the suggestion is to wrap this inside of an
// |async_patterns::TestDispatcherBound|.
class TestEnvironment final {
public:
explicit TestEnvironment(fdf_dispatcher_t* dispatcher = nullptr);
// Get the fdf::OutgoingDirectory that backs the driver's incoming namespace.
fdf::OutgoingDirectory& incoming_directory() {
std::lock_guard guard(checker_);
return incoming_directory_server_;
}
const fdf::OutgoingDirectory& incoming_directory() const {
std::lock_guard guard(checker_);
return incoming_directory_server_;
}
// Adds LogSink to the incoming directory. If required, this *must* be called before calling
// `Initialize`.
template <typename Callback>
zx::result<> AddLogSink(Callback callback) {
if (logsink_added_) {
return zx::error(ZX_ERR_BAD_STATE);
}
logsink_added_ = true;
return incoming_directory_server_.component().AddUnmanagedProtocol<fuchsia_logger::LogSink>(
[callback = std::move(callback)](fidl::ServerEnd<fuchsia_logger::LogSink> server_end) {
callback(std::move(server_end));
});
}
zx::result<> Initialize(fidl::ServerEnd<fuchsia_io::Directory> incoming_directory_server_end);
private:
static const char kTestEnvironmentThreadSafetyDescription[];
fdf_dispatcher_t* dispatcher_;
fdf::OutgoingDirectory incoming_directory_server_;
bool logsink_added_ = false;
async::synchronization_checker checker_;
};
} // namespace fdf_testing::internal
#endif // LIB_DRIVER_TESTING_CPP_INTERNAL_TEST_ENVIRONMENT_H_