blob: 3b3ecba3d741c8964cc452c19bcd65d1c538f4b1 [file] [log] [blame]
// 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);