blob: bb680f601ad362c4ad09e632806dd4d6da91be80 [file] [log] [blame]
// Copyright 2016 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 <stdio.h>
#include <stdlib.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
#include <lib/zx/event.h>
#include <lib/zx/thread.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <lib/zx/socket.h>
#include <zxtest/zxtest.h>
namespace {
constexpr uint32_t kEventOption = 0u;
constexpr uint32_t kSocketOption = 0u;
TEST(HandleInfoTest, DupAndInfoRights) {
zx::event orig_event;
ASSERT_OK(zx::event::create(kEventOption, &orig_event));
zx::event duped_event;
ASSERT_OK(orig_event.duplicate(ZX_RIGHT_SAME_RIGHTS, &duped_event));
ASSERT_OK(
orig_event.get_info(ZX_INFO_HANDLE_VALID, nullptr, 0u /*buffer_size*/, nullptr, nullptr));
orig_event.reset();
ASSERT_EQ(
orig_event.get_info(ZX_INFO_HANDLE_VALID, nullptr, 0u /*buffer_size*/, nullptr, nullptr),
ZX_ERR_BAD_HANDLE);
zx_info_handle_basic_t info = {};
ASSERT_EQ(duped_event.get_info(ZX_INFO_HANDLE_BASIC, &info, 4u /*buffer_size*/, nullptr, nullptr),
ZX_ERR_BUFFER_TOO_SMALL);
ASSERT_OK(duped_event.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr));
constexpr zx_rights_t evr = ZX_RIGHTS_BASIC | ZX_RIGHT_SIGNAL;
EXPECT_GT(info.koid, 0ULL, "object id should be positive");
EXPECT_EQ(info.type, ZX_OBJ_TYPE_EVENT, "handle should be an event");
EXPECT_EQ(info.rights, evr, "wrong set of rights");
EXPECT_EQ(info.related_koid, 0ULL, "events don't have associated koid");
}
TEST(HandleInfoTest, RelatedKoid) {
zx_info_handle_basic_t info_job = {};
zx_info_handle_basic_t info_process = {};
ASSERT_OK(zx::job::default_job()->get_info(ZX_INFO_HANDLE_BASIC, &info_job, sizeof(info_job),
nullptr, nullptr));
ASSERT_OK(zx::process::self()->get_info(ZX_INFO_HANDLE_BASIC, &info_process, sizeof(info_process),
nullptr, nullptr));
EXPECT_EQ(info_job.type, ZX_OBJ_TYPE_JOB);
EXPECT_EQ(info_process.type, ZX_OBJ_TYPE_PROCESS);
zx::thread thread;
ASSERT_OK(zx::thread::create(*zx::process::self(), "hitr", 4, 0u, &thread));
zx_info_handle_basic_t info_thread = {};
ASSERT_OK(
thread.get_info(ZX_INFO_HANDLE_BASIC, &info_thread, sizeof(info_thread), nullptr, nullptr));
EXPECT_EQ(info_thread.type, ZX_OBJ_TYPE_THREAD);
// The related koid of a process is its job and this test assumes that the
// default job is in fact the parent job of this test. Equivalently, a thread's
// associated koid is the process koid.
EXPECT_EQ(info_process.related_koid, info_job.koid);
EXPECT_EQ(info_thread.related_koid, info_process.koid);
thread.reset();
zx::socket socket_local, socket_remote;
ASSERT_OK(zx::socket::create(kSocketOption, &socket_local, &socket_remote));
zx_info_handle_basic_t info_socket_local = {};
ASSERT_OK(socket_local.get_info(ZX_INFO_HANDLE_BASIC, &info_socket_local,
sizeof(info_socket_local), nullptr, nullptr));
zx_info_handle_basic_t info_socket_remote = {};
ASSERT_OK(socket_remote.get_info(ZX_INFO_HANDLE_BASIC, &info_socket_remote,
sizeof(info_socket_remote), nullptr, nullptr));
EXPECT_EQ(info_socket_local.type, ZX_OBJ_TYPE_SOCKET);
EXPECT_EQ(info_socket_remote.type, ZX_OBJ_TYPE_SOCKET);
// The related koid of a socket pair are each other koids.
EXPECT_EQ(info_socket_local.related_koid, info_socket_remote.koid);
EXPECT_EQ(info_socket_remote.related_koid, info_socket_local.koid);
}
TEST(HandleInfoTest, DuplicateRights) {
zx::event orig_event;
ASSERT_OK(zx::event::create(kEventOption, &orig_event));
zx::event duped_ro1_event, duped_ro2_event;
ASSERT_OK(orig_event.duplicate(ZX_RIGHT_WAIT, &duped_ro1_event));
ASSERT_OK(orig_event.duplicate(ZX_RIGHT_WAIT, &duped_ro2_event));
zx_info_handle_basic_t info = {};
ASSERT_OK(duped_ro1_event.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr));
EXPECT_EQ(info.rights, ZX_RIGHT_WAIT, "wrong set of rights");
zx::event duped_ro3_event;
// Duplicate right removed, so this fails.
ASSERT_EQ(duped_ro1_event.duplicate(ZX_RIGHT_SAME_RIGHTS, &duped_ro3_event),
ZX_ERR_ACCESS_DENIED);
ASSERT_EQ(orig_event.duplicate(ZX_RIGHT_EXECUTE | ZX_RIGHT_WAIT, &duped_ro3_event),
ZX_ERR_INVALID_ARGS, "invalid right");
EXPECT_TRUE(orig_event.is_valid(), "original handle should be valid");
EXPECT_TRUE(duped_ro1_event.is_valid(), "duped handle should be valid");
EXPECT_TRUE(duped_ro2_event.is_valid(), "duped handle should be valid");
EXPECT_FALSE(duped_ro3_event.is_valid(), "duped handle should be invalid");
}
TEST(HandleInfoTest, ReplaceRights) {
zx::event event1, event2;
ASSERT_OK(zx::event::create(kEventOption, &event1));
ASSERT_OK(event1.replace(ZX_RIGHT_WAIT, &event2));
zx_info_handle_basic_t info = {};
ASSERT_OK(event2.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr));
EXPECT_EQ(info.rights, ZX_RIGHT_WAIT, "wrong set of rights");
EXPECT_FALSE(event1.is_valid(), "replaced event should be invalid");
EXPECT_EQ(event2.replace(ZX_RIGHT_SIGNAL | ZX_RIGHT_WAIT, &event1), ZX_ERR_INVALID_ARGS,
"cannot upgrade rights");
// event2 should also now be invalid.
EXPECT_FALSE(event2.is_valid(), "replaced event should be invalid on failure");
}
} // namespace