| // 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/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 <unittest/unittest.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; |
| } |
| |
| static bool dispatch_test(void) { |
| BEGIN_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_t handles[2]; |
| fidl_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], &handles[1]); |
| 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], &canary0); |
| ASSERT_EQ(ZX_OK, status, ""); |
| |
| zx_handle_t canary1 = ZX_HANDLE_INVALID; |
| status = zx_eventpair_create(0, &handles[1], &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], &canary0); |
| ASSERT_EQ(ZX_OK, status, ""); |
| |
| canary1 = ZX_HANDLE_INVALID; |
| status = zx_eventpair_create(0, &handles[1], &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, ""); |
| zx_handle_close_many(handles, 2); |
| zx_handle_close(canary0); |
| zx_handle_close(canary1); |
| |
| END_TEST; |
| } |
| |
| 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_msg_t* msg) { |
| my_connection_t* my_txn = (my_connection_t*)txn; |
| EXPECT_EQ(sizeof(fidl_test_echo_EchoEchoResponse), msg->num_bytes, ""); |
| EXPECT_EQ(0u, msg->num_handles, ""); |
| |
| fidl_message_header_t* hdr = (fidl_message_header_t*)msg->bytes; |
| EXPECT_EQ(hdr->magic_number, kFidlWireFormatMagicNumberInitial, ""); |
| ++my_txn->count; |
| return ZX_OK; |
| } |
| |
| static bool reply_test(void) { |
| BEGIN_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, ""); |
| |
| END_TEST; |
| } |
| |
| 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; |
| } |
| |
| static bool error_test(void) { |
| BEGIN_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_t handles[2]; |
| fidl_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], &handles[1]); |
| ASSERT_EQ(ZX_OK, status, ""); |
| status = fidl_test_echo_Echo_try_dispatch(NULL, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_ERR_ASYNC, status, ""); |
| |
| END_TEST; |
| } |
| |
| static bool incompatible_magic_test(void) { |
| BEGIN_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_t handles[2]; |
| fidl_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], &handles[1]); |
| ASSERT_EQ(ZX_OK, status, ""); |
| status = fidl_test_echo_Echo_try_dispatch(NULL, &txn, &msg, &ops); |
| ASSERT_EQ(ZX_ERR_PROTOCOL_NOT_SUPPORTED, status, ""); |
| |
| END_TEST; |
| } |
| |
| BEGIN_TEST_CASE(server_tests) |
| RUN_NAMED_TEST("fidl.test.echo.Echo dispatch test", dispatch_test) |
| RUN_NAMED_TEST("fidl.test.echo.Echo reply test", reply_test) |
| RUN_NAMED_TEST("fidl.test.echo.Echo error test", error_test) |
| RUN_NAMED_TEST("fidl.test.echo.Echo incompatible magic test", incompatible_magic_test) |
| END_TEST_CASE(server_tests); |