blob: 191fea169be618c25d022e10a2b1002691849493 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/unittest/unittest.h>
#include <fbl/alloc_checker.h>
#include <fbl/ref_ptr.h>
#include <ktl/utility.h>
#include <object/dispatcher.h>
#include <object/event_pair_dispatcher.h>
#include "fake_dispatcher.h"
#include "object/handle.h"
#include <ktl/enforce.h>
namespace {
bool KernelHandleCreate() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
{
KernelHandle handle(dispatcher);
EXPECT_EQ(dispatcher.get(), handle.dispatcher().get());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleCreateUpcast() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
{
KernelHandle<FakeDispatcherBase> handle(dispatcher);
EXPECT_EQ(dispatcher.get(), handle.dispatcher().get());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleReset() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
fbl::RefPtr<FakeDispatcher> dispatcher2 = FakeDispatcher::Create();
{
KernelHandle handle(dispatcher);
handle.reset(dispatcher2);
EXPECT_EQ(dispatcher2.get(), handle.dispatcher().get());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleResetUpcast() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
fbl::RefPtr<FakeDispatcher> dispatcher2 = FakeDispatcher::Create();
{
KernelHandle<FakeDispatcherBase> handle(dispatcher);
handle.reset(dispatcher2);
EXPECT_EQ(dispatcher2.get(), handle.dispatcher().get());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleResetToNull() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
KernelHandle handle(dispatcher);
handle.reset();
EXPECT_NULL(handle.dispatcher());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleRelease() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
KernelHandle handle(dispatcher);
fbl::RefPtr<FakeDispatcher> dispatcher_copy = handle.release();
EXPECT_NULL(handle.dispatcher());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 0);
EXPECT_EQ(dispatcher.get(), dispatcher_copy.get());
END_TEST;
}
bool KernelHandleMoveConstructor() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
KernelHandle handle(dispatcher);
{
KernelHandle new_handle(ktl::move(handle));
EXPECT_NULL(handle.dispatcher());
EXPECT_NONNULL(new_handle.dispatcher());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleMoveConstructorUpcast() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
KernelHandle handle(dispatcher);
{
KernelHandle<FakeDispatcherBase> new_handle(ktl::move(handle));
EXPECT_NULL(handle.dispatcher());
EXPECT_NONNULL(new_handle.dispatcher());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleMoveAssignment() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
fbl::RefPtr<FakeDispatcher> dispatcher2 = FakeDispatcher::Create();
{
KernelHandle handle(dispatcher);
KernelHandle handle2(dispatcher2);
handle = ktl::move(handle2);
EXPECT_NONNULL(handle.dispatcher());
EXPECT_NULL(handle2.dispatcher());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleMoveAssignmentUpcast() {
BEGIN_TEST;
fbl::RefPtr<FakeDispatcher> dispatcher = FakeDispatcher::Create();
fbl::RefPtr<FakeDispatcher> dispatcher2 = FakeDispatcher::Create();
{
KernelHandle<FakeDispatcherBase> handle(dispatcher);
KernelHandle handle2(dispatcher2);
handle = ktl::move(handle2);
EXPECT_NONNULL(handle.dispatcher());
EXPECT_NULL(handle2.dispatcher());
EXPECT_EQ(dispatcher->on_zero_handles_calls(), 1);
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 0);
}
EXPECT_EQ(dispatcher2->on_zero_handles_calls(), 1);
END_TEST;
}
bool KernelHandleUpgrade() {
BEGIN_TEST;
// HandleOwner requires a real Dispatcher so we can't use FakeDispatcher
// here. Use eventpair instead since we can signal the peer to check
// whether its on_zero_handles() has been called.
KernelHandle<EventPairDispatcher> eventpair[2];
zx_rights_t rights;
ASSERT_EQ(EventPairDispatcher::Create(&eventpair[0], &eventpair[1], &rights), ZX_OK);
{
HandleOwner handle_owner;
{
handle_owner = Handle::Make(ktl::move(eventpair[0]), rights);
EXPECT_NULL(eventpair[0].dispatcher());
EXPECT_TRUE(handle_owner);
EXPECT_EQ(handle_owner->rights(), rights);
}
EXPECT_EQ(eventpair[1].dispatcher()->user_signal_peer(0, ZX_USER_SIGNAL_0), ZX_OK);
}
EXPECT_EQ(eventpair[1].dispatcher()->user_signal_peer(0, ZX_USER_SIGNAL_0), ZX_ERR_PEER_CLOSED);
END_TEST;
}
} // namespace
UNITTEST_START_TESTCASE(handle_tests)
UNITTEST("KernelHandleCreate", KernelHandleCreate)
UNITTEST("KernelHandleCreateUpcast", KernelHandleCreateUpcast)
UNITTEST("KernelHandleReset", KernelHandleReset)
UNITTEST("KernelHandleResetUpcast", KernelHandleResetUpcast)
UNITTEST("KernelHandleResetToNull", KernelHandleResetToNull)
UNITTEST("KernelHandleRelease", KernelHandleRelease)
UNITTEST("KernelHandleMoveConstructor", KernelHandleMoveConstructor)
UNITTEST("KernelHandleMoveConstructorUpcast", KernelHandleMoveConstructorUpcast)
UNITTEST("KernelHandleMoveAssignment", KernelHandleMoveAssignment)
UNITTEST("KernelHandleMoveAssignmentUpcast", KernelHandleMoveAssignmentUpcast)
UNITTEST("KernelHandleUpgrade", KernelHandleUpgrade)
UNITTEST_END_TESTCASE(handle_tests, "handle", "Handle test")