| // 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 <unittest/unittest.h> |
| |
| static bool handle_replace_test(void) { |
| BEGIN_TEST; |
| |
| zx_handle_t event = ZX_HANDLE_INVALID; |
| ASSERT_EQ(ZX_OK, zx_event_create(0u, &event), ""); |
| |
| zx_handle_t replaced = ZX_HANDLE_INVALID; |
| ASSERT_EQ(ZX_OK, zx_handle_replace(event, ZX_RIGHTS_BASIC, &replaced), ""); |
| ASSERT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(event), ""); |
| |
| zx_handle_t failed = ZX_HANDLE_INVALID; |
| ASSERT_EQ(ZX_ERR_INVALID_ARGS, zx_handle_replace(replaced, ZX_RIGHT_SIGNAL, &failed), ""); |
| ASSERT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(replaced), ""); |
| ASSERT_EQ(ZX_HANDLE_INVALID, failed, ""); |
| |
| END_TEST; |
| } |
| |
| static bool handle_info_test(void) { |
| BEGIN_TEST; |
| |
| zx_handle_t event; |
| ASSERT_EQ(zx_event_create(0u, &event), 0, ""); |
| zx_handle_t duped; |
| zx_status_t status = zx_handle_duplicate(event, ZX_RIGHT_SAME_RIGHTS, &duped); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| ASSERT_EQ(zx_object_get_info(event, ZX_INFO_HANDLE_VALID, NULL, 0u, NULL, NULL), ZX_OK, |
| "handle should be valid"); |
| ASSERT_EQ(zx_handle_close(event), ZX_OK, "failed to close the handle"); |
| ASSERT_EQ(zx_object_get_info(event, ZX_INFO_HANDLE_VALID, NULL, 0u, NULL, NULL), ZX_ERR_BAD_HANDLE, |
| "handle should be valid"); |
| |
| zx_info_handle_basic_t info = {}; |
| ASSERT_EQ(zx_object_get_info(duped, ZX_INFO_HANDLE_BASIC, &info, 4u, NULL, NULL), |
| ZX_ERR_BUFFER_TOO_SMALL, "bad struct size validation"); |
| |
| status = zx_object_get_info(duped, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, "handle should be valid"); |
| |
| const zx_rights_t evr = ZX_RIGHTS_BASIC | ZX_RIGHT_SIGNAL; |
| |
| EXPECT_GT(info.koid, 0ULL, "object id should be positive"); |
| EXPECT_EQ(info.type, (uint32_t)ZX_OBJ_TYPE_EVENT, "handle should be an event"); |
| EXPECT_EQ(info.rights, evr, "wrong set of rights"); |
| EXPECT_EQ(info.props, (uint32_t)ZX_OBJ_PROP_WAITABLE, ""); |
| EXPECT_EQ(info.related_koid, 0ULL, "events don't have associated koid"); |
| |
| zx_handle_close(event); |
| zx_handle_close(duped); |
| |
| END_TEST; |
| } |
| |
| static bool handle_related_koid_test(void) { |
| BEGIN_TEST; |
| |
| zx_info_handle_basic_t info0 = {}; |
| zx_info_handle_basic_t info1 = {}; |
| |
| zx_status_t status = zx_object_get_info( |
| zx_job_default(), ZX_INFO_HANDLE_BASIC, &info0, sizeof(info0), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| status = zx_object_get_info( |
| zx_process_self(), ZX_INFO_HANDLE_BASIC, &info1, sizeof(info1), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| EXPECT_EQ(info0.type, (uint32_t)ZX_OBJ_TYPE_JOB, ""); |
| EXPECT_EQ(info1.type, (uint32_t)ZX_OBJ_TYPE_PROCESS, ""); |
| |
| zx_handle_t thread; |
| status = zx_thread_create(zx_process_self(), "hitr", 4, 0u, &thread); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| zx_info_handle_basic_t info2 = {}; |
| |
| status = zx_object_get_info( |
| thread, ZX_INFO_HANDLE_BASIC, &info2, sizeof(info2), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| EXPECT_EQ(info2.type, (uint32_t)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(info1.related_koid, info0.koid, ""); |
| EXPECT_EQ(info2.related_koid, info1.koid, ""); |
| |
| zx_handle_close(thread); |
| |
| zx_handle_t sock0, sock1; |
| status = zx_socket_create(0u, &sock0, &sock1); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| status = zx_object_get_info( |
| sock0, ZX_INFO_HANDLE_BASIC, &info0, sizeof(info0), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| status = zx_object_get_info( |
| sock1, ZX_INFO_HANDLE_BASIC, &info1, sizeof(info1), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| EXPECT_EQ(info0.type, (uint32_t)ZX_OBJ_TYPE_SOCKET, ""); |
| EXPECT_EQ(info1.type, (uint32_t)ZX_OBJ_TYPE_SOCKET, ""); |
| |
| // The related koid of a socket pair are each other koids. |
| EXPECT_EQ(info0.related_koid, info1.koid, ""); |
| EXPECT_EQ(info1.related_koid, info0.koid, ""); |
| |
| zx_handle_close(sock0); |
| zx_handle_close(sock1); |
| END_TEST; |
| } |
| |
| static bool handle_rights_test(void) { |
| BEGIN_TEST; |
| |
| zx_handle_t event; |
| ASSERT_EQ(zx_event_create(0u, &event), 0, ""); |
| zx_handle_t duped_ro, duped_ro2; |
| ASSERT_EQ(zx_handle_duplicate(event, ZX_RIGHT_WAIT, &duped_ro), ZX_OK, ""); |
| ASSERT_EQ(zx_handle_duplicate(event, ZX_RIGHT_WAIT, &duped_ro2), ZX_OK, ""); |
| |
| zx_info_handle_basic_t info = {}; |
| zx_status_t status = zx_object_get_info(duped_ro, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL); |
| ASSERT_EQ(status, ZX_OK, "handle should be valid"); |
| |
| ASSERT_EQ(info.rights, ZX_RIGHT_WAIT, "wrong set of rights"); |
| |
| zx_handle_t h; |
| status = zx_handle_duplicate(duped_ro, ZX_RIGHT_SAME_RIGHTS, &h); |
| ASSERT_EQ(status, ZX_ERR_ACCESS_DENIED, "should fail rights check"); |
| |
| status = zx_handle_duplicate(event, ZX_RIGHT_EXECUTE | ZX_RIGHT_WAIT, &h); |
| ASSERT_EQ(status, ZX_ERR_INVALID_ARGS, "cannot upgrade rights"); |
| |
| ASSERT_EQ(zx_handle_replace(duped_ro, ZX_RIGHT_SIGNAL | ZX_RIGHT_WAIT, &h), ZX_ERR_INVALID_ARGS, |
| "cannot upgrade rights"); |
| // duped_ro1 should now be invalid. |
| ASSERT_EQ(zx_handle_close(duped_ro), ZX_ERR_BAD_HANDLE, "replaced handle should be invalid on failure"); |
| |
| status = zx_handle_replace(duped_ro2, ZX_RIGHT_SAME_RIGHTS, &h); |
| ASSERT_EQ(status, ZX_OK, "should be able to replace handle"); |
| // duped_ro2 should now be invalid. |
| |
| ASSERT_EQ(zx_handle_close(event), ZX_OK, "failed to close original handle"); |
| ASSERT_EQ(zx_handle_close(duped_ro2), ZX_ERR_BAD_HANDLE, "replaced handle should be invalid on success"); |
| ASSERT_EQ(zx_handle_close(h), ZX_OK, "failed to close replacement handle"); |
| |
| END_TEST; |
| } |
| |
| BEGIN_TEST_CASE(handle_info_tests) |
| RUN_TEST(handle_replace_test) |
| RUN_TEST(handle_info_test) |
| RUN_TEST(handle_related_koid_test) |
| RUN_TEST(handle_rights_test) |
| END_TEST_CASE(handle_info_tests) |
| |
| #ifndef BUILD_COMBINED_TESTS |
| int main(int argc, char** argv) { |
| return unittest_run_all_tests(argc, argv) ? 0 : -1; |
| } |
| #endif |