blob: 72899540a4b835d92fdfa6843d51ee0f96ed9801 [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.
#include "lib/ld/testing/mock-loader-service.h"
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/dispatcher.h>
#include <gmock/gmock.h>
namespace ld::testing {
namespace {
using ::testing::Return;
} // namespace
// A mock server implementation serving the fuchsia.ldsvc.Loader protocol. When
// it receives a request, it will invoke the associated MOCK_METHOD. If the
// test caller did not call Expect* for the request before it is made, then
// the MockServer will fail the test.
class MockLoaderService::MockServer : public fidl::WireServer<fuchsia_ldsvc::Loader> {
public:
MockServer() = default;
~MockServer() {
if (backing_loop_) {
backing_loop_->Shutdown();
}
}
void Init(fidl::ServerEnd<fuchsia_ldsvc::Loader> server) {
backing_loop_.emplace(&kAsyncLoopConfigNoAttachToCurrentThread);
zx_status_t status = backing_loop_->StartThread("MockLoaderService");
ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
fidl::BindServer(backing_loop_->dispatcher(), std::move(server), this);
}
// Note the mocked methods take std::string, though the Expect* wrappers take
// std::string_view. The std::string_view passed to the wrappers is not
// guaranteed to point to memory that's valid after the call, so they copy
// into a fresh std::string for EXPECT_CALL; those stay live in the mock.
MOCK_METHOD(zx::result<zx::vmo>, MockLoadObject, (std::string));
MOCK_METHOD(zx::result<>, MockConfig, (std::string));
private:
// The fidl::WireServer<fuchsia_ldsvc::Loader> implementation, each FIDL
// method will call into its associated gMock method when invoked.
// Done is not used in ld tests.
void Done(DoneCompleter::Sync& completer) override { ADD_FAILURE() << "unexpected Done call"; }
void LoadObject(LoadObjectRequestView request, LoadObjectCompleter::Sync& completer) override {
auto result = MockLoadObject(std::string(request->object_name.get()));
completer.Reply(result.status_value(), std::move(result).value_or(zx::vmo()));
}
void Config(ConfigRequestView request, ConfigCompleter::Sync& completer) override {
auto result = MockConfig(std::string(request->config.get()));
completer.Reply(result.status_value());
}
// Clone is not used in ld tests.
void Clone(CloneRequestView request, CloneCompleter::Sync& completer) override {
ADD_FAILURE() << "unexpected Clone call";
}
std::optional<async::Loop> backing_loop_;
};
MockLoaderService::MockLoaderService() = default;
MockLoaderService::~MockLoaderService() = default;
void MockLoaderService::Init() {
mock_server_ = std::make_unique<::testing::StrictMock<MockServer>>();
auto endpoints = fidl::CreateEndpoints<fuchsia_ldsvc::Loader>();
ASSERT_EQ(endpoints.status_value(), ZX_OK);
ASSERT_NO_FATAL_FAILURE(mock_server_->Init(std::move(endpoints->server)));
mock_client_ = std::move(endpoints->client);
}
void MockLoaderService::ExpectLoadObject(std::string_view name,
zx::result<zx::vmo> expected_result) {
EXPECT_CALL(*mock_server_, MockLoadObject(std::string{name}))
.WillOnce(Return(std::move(expected_result)));
}
void MockLoaderService::ExpectConfig(std::string_view name, zx::result<> expected_result) {
EXPECT_CALL(*mock_server_, MockConfig(std::string{name})).WillOnce(Return(expected_result));
}
} // namespace ld::testing