| // 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/fidl/internal.h> |
| #include <lib/fidl/txn_header.h> |
| #include <string.h> |
| #include <zircon/errors.h> |
| #include <zircon/fidl.h> |
| #include <zircon/syscalls.h> |
| #include <zircon/types.h> |
| |
| #include <fidl/test/echo/c/fidl.h> |
| #include <zxtest/zxtest.h> |
| |
| static int kContext = 42; |
| static size_t g_echo_call_count = 0u; |
| |
| static zx_status_t echo(void* ctx, zx_handle_t process, zx_handle_t thread, fidl_txn_t* txn) { |
| ++g_echo_call_count; |
| EXPECT_EQ(&kContext, ctx, ""); |
| EXPECT_NE(ZX_HANDLE_INVALID, process, ""); |
| EXPECT_NE(ZX_HANDLE_INVALID, thread, ""); |
| EXPECT_NE(NULL, txn, ""); |
| zx_handle_close(process); |
| zx_handle_close(thread); |
| return ZX_OK; |
| } |
| |
| TEST(ServerTests, dispatch_test) { |
| fidl_test_echo_Echo_ops_t ops = { |
| .Echo = echo, |
| }; |
| |
| fidl_test_echo_EchoEchoRequest request; |
| memset(&request, 0, sizeof(request)); |
| zx_txid_t txid = 42; |
| fidl_init_txn_header(&request.hdr, txid, fidl_test_echo_EchoEchoOrdinal); |
| request.process = FIDL_HANDLE_PRESENT; |
| request.thread = FIDL_HANDLE_PRESENT; |
| |
| zx_handle_info_t handles[2] = { |
| { |
| .handle = ZX_HANDLE_INVALID, |
| .type = ZX_OBJ_TYPE_EVENTPAIR, |
| .rights = ZX_RIGHT_SAME_RIGHTS, |
| }, |
| { |
| .handle = ZX_HANDLE_INVALID, |
| .type = ZX_OBJ_TYPE_EVENTPAIR, |
| .rights = ZX_RIGHT_SAME_RIGHTS, |
| }, |
| }; |
| fidl_incoming_msg_t msg = { |
| .bytes = &request, |
| .handles = handles, |
| .num_bytes = sizeof(request), |
| .num_handles = 2, |
| }; |
| |
| fidl_txn_t txn; |
| memset(&txn, 0, sizeof(txn)); |
| |
| // Success |
| |
| zx_status_t status = zx_eventpair_create(0, &handles[0].handle, &handles[1].handle); |
| ASSERT_EQ(ZX_OK, status, ""); |
| EXPECT_EQ(0u, g_echo_call_count, ""); |
| status = fidl_test_echo_Echo_dispatch(&kContext, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_OK, status, ""); |
| EXPECT_EQ(1u, g_echo_call_count, ""); |
| g_echo_call_count = 0u; |
| |
| // Bad ordinal (dispatch) |
| |
| request.hdr.ordinal = 8949; |
| zx_handle_t canary0 = ZX_HANDLE_INVALID; |
| status = zx_eventpair_create(0, &handles[0].handle, &canary0); |
| ASSERT_EQ(ZX_OK, status, ""); |
| |
| zx_handle_t canary1 = ZX_HANDLE_INVALID; |
| status = zx_eventpair_create(0, &handles[1].handle, &canary1); |
| ASSERT_EQ(ZX_OK, status, ""); |
| |
| EXPECT_EQ(0u, g_echo_call_count, ""); |
| status = fidl_test_echo_Echo_dispatch(&kContext, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, status, ""); |
| EXPECT_EQ(0u, g_echo_call_count, ""); |
| g_echo_call_count = 0u; |
| status = zx_object_signal_peer(canary0, 0, ZX_USER_SIGNAL_0); |
| ASSERT_EQ(ZX_ERR_PEER_CLOSED, status, ""); |
| status = zx_object_signal_peer(canary1, 0, ZX_USER_SIGNAL_0); |
| ASSERT_EQ(ZX_ERR_PEER_CLOSED, status, ""); |
| zx_handle_close(canary0); |
| zx_handle_close(canary1); |
| |
| // Bad ordinal (try_dispatch) |
| |
| request.hdr.ordinal = 8949; |
| canary0 = ZX_HANDLE_INVALID; |
| status = zx_eventpair_create(0, &handles[0].handle, &canary0); |
| ASSERT_EQ(ZX_OK, status, ""); |
| |
| canary1 = ZX_HANDLE_INVALID; |
| status = zx_eventpair_create(0, &handles[1].handle, &canary1); |
| ASSERT_EQ(ZX_OK, status, ""); |
| |
| EXPECT_EQ(0u, g_echo_call_count, ""); |
| status = fidl_test_echo_Echo_try_dispatch(&kContext, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, status, ""); |
| EXPECT_EQ(0u, g_echo_call_count, ""); |
| g_echo_call_count = 0u; |
| status = zx_object_signal_peer(canary0, 0, ZX_USER_SIGNAL_0); |
| ASSERT_EQ(ZX_OK, status, ""); |
| status = zx_object_signal_peer(canary1, 0, ZX_USER_SIGNAL_0); |
| ASSERT_EQ(ZX_OK, status, ""); |
| FidlHandleInfoCloseMany(handles, 2); |
| zx_handle_close(canary0); |
| zx_handle_close(canary1); |
| } |
| |
| typedef struct my_connection { |
| fidl_txn_t txn; |
| size_t count; |
| } my_connection_t; |
| |
| static zx_status_t reply_handler(fidl_txn_t* txn, const fidl_outgoing_msg_t* msg) { |
| ZX_ASSERT(msg->type == FIDL_OUTGOING_MSG_TYPE_BYTE); |
| my_connection_t* my_txn = (my_connection_t*)txn; |
| EXPECT_EQ(sizeof(fidl_test_echo_EchoEchoResponse), msg->byte.num_bytes, ""); |
| EXPECT_EQ(0u, msg->byte.num_handles, ""); |
| |
| fidl_message_header_t* hdr = (fidl_message_header_t*)msg->byte.bytes; |
| EXPECT_EQ(hdr->magic_number, kFidlWireFormatMagicNumberInitial, ""); |
| ++my_txn->count; |
| return ZX_OK; |
| } |
| |
| TEST(ServerTests, reply_test) { |
| my_connection_t conn; |
| conn.txn.reply = reply_handler; |
| conn.count = 0u; |
| |
| zx_status_t status = fidl_test_echo_EchoEcho_reply(&conn.txn, ZX_OK); |
| ASSERT_EQ(ZX_OK, status, ""); |
| EXPECT_EQ(1u, conn.count, ""); |
| } |
| |
| static zx_status_t return_async(void* ctx, zx_handle_t process, zx_handle_t thread, |
| fidl_txn_t* txn) { |
| zx_handle_close(process); |
| zx_handle_close(thread); |
| return ZX_ERR_ASYNC; |
| } |
| |
| TEST(ServerTests, error_test) { |
| fidl_test_echo_Echo_ops_t ops = { |
| .Echo = return_async, |
| }; |
| |
| fidl_test_echo_EchoEchoRequest request; |
| memset(&request, 0, sizeof(request)); |
| zx_txid_t txid = 42; |
| fidl_init_txn_header(&request.hdr, txid, fidl_test_echo_EchoEchoOrdinal); |
| request.process = FIDL_HANDLE_PRESENT; |
| request.thread = FIDL_HANDLE_PRESENT; |
| |
| zx_handle_info_t handles[2] = { |
| { |
| .handle = ZX_HANDLE_INVALID, |
| .type = ZX_OBJ_TYPE_EVENTPAIR, |
| .rights = ZX_RIGHT_SAME_RIGHTS, |
| }, |
| { |
| .handle = ZX_HANDLE_INVALID, |
| .type = ZX_OBJ_TYPE_EVENTPAIR, |
| .rights = ZX_RIGHT_SAME_RIGHTS, |
| }, |
| }; |
| fidl_incoming_msg_t msg = { |
| .bytes = &request, |
| .handles = handles, |
| .num_bytes = sizeof(request), |
| .num_handles = 2, |
| }; |
| |
| fidl_txn_t txn; |
| memset(&txn, 0, sizeof(txn)); |
| |
| zx_status_t status = zx_eventpair_create(0, &handles[0].handle, &handles[1].handle); |
| ASSERT_EQ(ZX_OK, status, ""); |
| status = fidl_test_echo_Echo_try_dispatch(NULL, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_ERR_ASYNC, status, ""); |
| } |
| |
| TEST(ServerTests, incompatible_magic_test) { |
| fidl_test_echo_Echo_ops_t ops = { |
| .Echo = return_async, |
| }; |
| |
| fidl_test_echo_EchoEchoRequest request; |
| memset(&request, 0, sizeof(request)); |
| zx_txid_t txid = 42; |
| fidl_init_txn_header(&request.hdr, txid, fidl_test_echo_EchoEchoOrdinal); |
| request.hdr.magic_number = 0; |
| request.process = FIDL_HANDLE_PRESENT; |
| request.thread = FIDL_HANDLE_PRESENT; |
| |
| zx_handle_info_t handles[2] = { |
| { |
| .handle = ZX_HANDLE_INVALID, |
| .type = ZX_OBJ_TYPE_EVENTPAIR, |
| .rights = ZX_RIGHT_SAME_RIGHTS, |
| }, |
| { |
| .handle = ZX_HANDLE_INVALID, |
| .type = ZX_OBJ_TYPE_EVENTPAIR, |
| .rights = ZX_RIGHT_SAME_RIGHTS, |
| }, |
| }; |
| fidl_incoming_msg_t msg = { |
| .bytes = &request, |
| .handles = handles, |
| .num_bytes = sizeof(request), |
| .num_handles = 2, |
| }; |
| |
| fidl_txn_t txn; |
| memset(&txn, 0, sizeof(txn)); |
| |
| zx_status_t status = zx_eventpair_create(0, &handles[0].handle, &handles[1].handle); |
| ASSERT_EQ(ZX_OK, status, ""); |
| status = fidl_test_echo_Echo_try_dispatch(NULL, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_ERR_PROTOCOL_NOT_SUPPORTED, status, ""); |
| } |