blob: 0893e0dd1a204a5f51318a1c419f620fee8b57ee [file] [log] [blame]
// Copyright 2018 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/async-testing/dispatcher_stub.h>
#include <lib/async/cpp/trap.h>
#include <zxtest/zxtest.h>
namespace {
const zx_handle_t dummy_guest = static_cast<zx_handle_t>(1);
const zx_vaddr_t dummy_addr = 0x1000;
const size_t dummy_length = 0x1000;
const zx_packet_guest_bell_t dummy_bell{
.addr = dummy_addr,
.reserved0 = 0u,
.reserved1 = 0u,
.reserved2 = 0u,
};
class MockDispatcher : public async::DispatcherStub {
public:
zx_status_t SetGuestBellTrap(async_guest_bell_trap_t* trap, const zx::guest& guest,
zx_vaddr_t addr, size_t length) override {
last_trap = trap;
last_guest = guest.get();
last_addr = addr;
last_length = length;
return ZX_OK;
}
async_guest_bell_trap_t* last_trap = nullptr;
zx_handle_t last_guest = ZX_HANDLE_INVALID;
zx_vaddr_t last_addr = 0u;
size_t last_length = 0u;
};
class Harness {
public:
void Handler(async_dispatcher_t* dispatcher, async::GuestBellTrapBase* trap, zx_status_t status,
const zx_packet_guest_bell_t* bell) {
handler_ran = true;
last_trap = trap;
last_status = status;
last_bell = bell;
}
virtual async::GuestBellTrapBase& trap() = 0;
bool handler_ran = false;
async::GuestBellTrapBase* last_trap = nullptr;
zx_status_t last_status = ZX_ERR_INTERNAL;
const zx_packet_guest_bell_t* last_bell = nullptr;
};
class LambdaHarness : public Harness {
public:
async::GuestBellTrapBase& trap() override { return trap_; }
private:
async::GuestBellTrap trap_{
[this](async_dispatcher_t* dispatcher, async::GuestBellTrap* trap, zx_status_t status,
const zx_packet_guest_bell_t* bell) { Handler(dispatcher, trap, status, bell); }};
};
class MethodHarness : public Harness {
public:
async::GuestBellTrapBase& trap() override { return trap_; }
private:
async::GuestBellTrapMethod<Harness, &Harness::Handler> trap_{this};
};
TEST(TrapTests, guest_bell_trap_set_handler_test) {
{
async::GuestBellTrap trap;
EXPECT_FALSE(trap.has_handler());
trap.set_handler([](async_dispatcher_t* dispatcher, async::GuestBellTrap* trap,
zx_status_t status, const zx_packet_guest_bell_t* bell) {});
EXPECT_TRUE(trap.has_handler());
}
{
async::GuestBellTrap trap([](async_dispatcher_t* dispatcher, async::GuestBellTrap* trap,
zx_status_t status, const zx_packet_guest_bell_t* bell) {});
EXPECT_TRUE(trap.has_handler());
}
}
template <typename Harness>
void guest_bell_trap_test() {
MockDispatcher dispatcher;
Harness harness;
EXPECT_EQ(ZX_OK, harness.trap().SetTrap(&dispatcher, *zx::unowned_guest(dummy_guest), dummy_addr,
dummy_length));
EXPECT_EQ(dummy_guest, dispatcher.last_guest);
EXPECT_EQ(dummy_addr, dispatcher.last_addr);
EXPECT_EQ(dummy_length, dispatcher.last_length);
dispatcher.last_trap->handler(&dispatcher, dispatcher.last_trap, ZX_OK, &dummy_bell);
EXPECT_TRUE(harness.handler_ran);
EXPECT_EQ(&harness.trap(), harness.last_trap);
EXPECT_EQ(ZX_OK, harness.last_status);
EXPECT_EQ(&dummy_bell, harness.last_bell);
}
} // namespace
TEST(TrapTests, guest_bell_trap_test_LambdaHarness) { guest_bell_trap_test<LambdaHarness>(); }
TEST(TrapTests, guest_bell_trap_test_MethodHarness) { guest_bell_trap_test<MethodHarness>(); }