summaryrefslogtreecommitdiff
path: root/cesar/host/test/src/test_sci.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/host/test/src/test_sci.c')
-rw-r--r--cesar/host/test/src/test_sci.c527
1 files changed, 527 insertions, 0 deletions
diff --git a/cesar/host/test/src/test_sci.c b/cesar/host/test/src/test_sci.c
new file mode 100644
index 0000000000..baf6186800
--- /dev/null
+++ b/cesar/host/test/src/test_sci.c
@@ -0,0 +1,527 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file test_sci.c
+ * \brief Test all sci functions.
+ * \ingroup test
+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <errno.h>
+#include "common/std.h"
+#include "host/sci.h"
+#include "lib/test.h"
+
+extern char dump_buffer[];
+
+//void sci_new_test_case(test_t t)
+//{
+// sci_ctx_t *sci;
+// station_ctx_t *station;
+//
+// test_case_begin(t, "new");
+// station = station_new();
+//
+// test_begin(t, "NULL station")
+// {
+// test_fail_unless(
+// (sci_new(NULL) == NULL)
+// && (errno == EINVAL));
+// } test_end;
+//
+// test_begin(t, "check new")
+// {
+// sci = sci_new(station);
+// test_fail_unless(
+// (sci != NULL)
+// && (sci->station == station));
+// }
+//
+// sci_free(sci);
+// station_free(station);
+//}
+
+void sci_init_test_case(test_t t)
+{
+ sci_ctx_t sci;
+ station_ctx_t station;
+
+ test_case_begin(t, "init");
+
+ test_begin(t, "NULL sci")
+ {
+ test_fail_unless(
+ (sci_init(NULL, &station) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "NULL station")
+ {
+ test_fail_unless(
+ (sci_init(&sci, NULL) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "check init call")
+ {
+ test_fail_unless(
+ (sci_init(&sci, &station) >= 0)
+ && (sci.station == &station)
+ );
+ } test_end;
+ return;
+}
+
+//void sci_free_test_case(test_t t)
+//{
+// station_ctx_t *station
+// sci_ctx_t *sci;
+//
+// test_case_begin(t, "free");
+//
+// test_begin(t, "NULL sci")
+// {
+// sci_free(NULL); /* must not crash */
+// test_fail_if(0);
+// } test_end;
+//
+// station = station_new();
+// sci = sci_new(station);
+//
+// test_begin(t, "check station integrity")
+// {
+// sci_free(sci);
+// test_fail_unless(
+// (station->id != 0)); /* station has not been freed */
+// } test_end;
+//
+// station_free(station);
+//}
+
+static int _sci_callback(sci_msg_t *msg, void *data)
+{
+ return 0;
+}
+
+void sci_register_callback_test_case(test_t t)
+{
+ station_ctx_t station;
+ sci_ctx_t sci;
+
+ test_case_begin(t, "register_callback");
+ sci_init(&sci, &station);
+
+ test_begin(t, "sci = NULL")
+ {
+ test_fail_unless(
+ (sci_register_callback(NULL, 0, NULL, NULL) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "bad type -1")
+ {
+ test_fail_unless(
+ (sci_register_callback(&sci, -1, NULL, NULL) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "bad type > max")
+ {
+ test_fail_unless(
+ (sci_register_callback(&sci, SCI_MSG_TYPE_NB, NULL, NULL) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "registering NULL function")
+ {
+ test_fail_unless(
+ (sci_register_callback(&sci, SCI_MSG_TYPE_SYSTEM, NULL, &station) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "registering test function")
+ {
+ test_fail_unless(
+ (sci_register_callback(&sci, SCI_MSG_TYPE_PHY, _sci_callback, &station) >= 0)
+ && (sci.msg_callback[SCI_MSG_TYPE_PHY].function == _sci_callback)
+ && (sci.msg_callback[SCI_MSG_TYPE_PHY].data = &station));
+ } test_end;
+
+}
+
+void sci_fill_hdr_test_case(test_t t)
+{
+ station_ctx_t station;
+ sci_ctx_t sci;
+ sci_msg_t msg;
+ unsigned char buffer[128];
+ unsigned short previous_msg_id;
+
+
+ test_case_begin(t, "fill_hdr");
+
+ test_begin(t, "init msg")
+ {
+ test_fail_unless(
+ (0 == sci_msg_init(&msg, buffer, 128))
+ && (EINVAL != errno)
+ );
+ } test_end;
+
+ station_init(&station);
+ sci_init(&sci, &station);
+
+ test_begin(t, "sci = NULL")
+ {
+ test_fail_unless(
+ (sci_fill_hdr(NULL, &msg, SCI_MSG_TYPE_PHY, 0) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "msg = NULL")
+ {
+ test_fail_unless(
+ (sci_fill_hdr(&sci, NULL, SCI_MSG_TYPE_PHY, 0) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "type < 0")
+ {
+ test_fail_unless(
+ (sci_fill_hdr(&sci, &msg, -1, 0) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "type >= max")
+ {
+ test_fail_unless(
+ (sci_fill_hdr(&sci, &msg, SCI_MSG_TYPE_NB, 0) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "check content")
+ {
+ test_fail_unless(
+ (64 == sci_msg_push(&msg, 64))
+ && (EINVAL != errno)
+ && (ENOSPC != errno)
+ );
+ previous_msg_id = sci.current_msg_id;
+ test_fail_unless(
+ (sci_fill_hdr(&sci, &msg, SCI_MSG_TYPE_SYSTEM, 0xaa55) >= 0)
+ && ((unsigned char *)msg.sci_hdr == msg.data_begin)
+ && !memcmp((unsigned char *)&msg.sci_hdr->magic_id, SCI_MSG_MAGIC, 4)
+ && (msg.sci_hdr->version == SCI_MSG_VERSION)
+ && (msg.sci_hdr->type == SCI_MSG_TYPE_SYSTEM)
+ && (ntohs(msg.sci_hdr->length) == 64)
+ && (ntohs(msg.sci_hdr->flags) == 0xaa55)
+ && (ntohs(msg.sci_hdr->station_id) == sci.station->id)
+ && ((ntohs(msg.sci_hdr->msg_id) & ~SCI_MSG_ID_STATION) == sci.current_msg_id - 1)
+ && (ntohs(msg.sci_hdr->msg_id) & SCI_MSG_ID_STATION));
+ } test_end;
+
+ test_begin(t, "check msg_id rollover")
+ {
+ test_fail_unless(
+ (0 == sci_msg_init(&msg, buffer, 128))
+ && (EINVAL != errno)
+ );
+ sci.current_msg_id = SCI_MSG_ID_MASK;
+ test_fail_unless(
+ (sci_fill_hdr(&sci, &msg, SCI_MSG_TYPE_SYSTEM, 0) >= 0)
+ && (ntohs(msg.sci_hdr->msg_id) == (SCI_MSG_ID_MASK | SCI_MSG_ID_STATION))
+ && (sci.current_msg_id == 0)
+ );
+ } test_end;
+
+ station_down(&station);
+}
+
+#define TEST_DATA_STR "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+void sci_send_test_case(test_t t)
+{
+ station_ctx_t station;
+ sci_ctx_t sci;
+ unsigned char msg_buffer[256], buffer[256];
+ sci_msg_t msg;
+ int fd_out;
+
+ test_case_begin(t, "send");
+ station_init(&station);
+
+ test_begin(t, "init msg")
+ {
+ test_fail_unless(
+ (0 == sci_msg_init(&msg, msg_buffer, 256))
+ && (EINVAL != errno)
+ );
+ } test_end;
+
+ sci_init(&sci, &station);
+
+ test_begin(t, "sci = NULL")
+ {
+ test_fail_unless(
+ (sci_send(NULL, &msg) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "msg = NULL")
+ {
+ test_fail_unless(
+ (sci_send(&sci, NULL) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "check send")
+ {
+#ifdef STATION_SOCK
+ fd_out = station.sock_pair_fd;
+#else
+ fd_out = open(station.pipe_out_name, O_RDONLY);
+#endif
+ test_fail_unless(
+ ((int)strlen(TEST_DATA_STR) == sci_msg_push(&msg, strlen(TEST_DATA_STR)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno)
+ );
+ memcpy(msg.data_begin, TEST_DATA_STR, msg.length);
+ test_fail_unless(
+ (sci_fill_hdr(&sci, &msg, SCI_MSG_TYPE_FUNCTION_CALL, 0) >= 0)
+ && (sci_send(&sci, &msg) == msg.length)
+ && (read(fd_out, buffer, msg.length) == msg.length)
+ && !memcmp(msg.data_begin, buffer, msg.length)
+ );
+ } test_end;
+ close(fd_out);
+ station_down(&station);
+}
+
+#define TEST_RECV_STR "test_recv"
+static int _sci_send_callback(sci_msg_t *msg, void *data)
+{
+ unsigned char *buffer;
+ buffer = (unsigned char *)data;
+
+ if((msg == NULL)
+ || (msg->length != sizeof(station_msg_hdr_t) + strlen(TEST_DATA_STR))
+ || (msg->length != msg->data_end - msg->data_begin)
+ || ((unsigned char *)msg->hdr.station != msg->data_begin)
+ || (buffer == NULL))
+ return -1;
+ if(msg->hdr.station->type != SYSTEM_TYPE_IDLE)
+ return -1;
+ if(sci_msg_pop(msg, sizeof(station_msg_hdr_t)) < (int)sizeof(station_msg_hdr_t))
+ return -1;
+ if(memcmp(msg->data_begin, TEST_DATA_STR, strlen(TEST_DATA_STR)))
+ return -1;
+
+ memcpy(buffer, TEST_RECV_STR, strlen(TEST_RECV_STR));
+ return 0;
+}
+
+void sci_recv_test_case(test_t t)
+{
+ station_ctx_t station;
+ sci_ctx_t sci;
+ unsigned char msg_buffer[256], data_buffer[16];
+ sci_msg_t msg;
+ int fd_in;
+ char *magic_id = SCI_MSG_MAGIC;
+
+ test_case_begin(t, "recv");
+ memset(msg_buffer, '\0', 256);
+ memset(data_buffer, '\0', 16);
+ station_init(&station);
+ //station.pipe_log_fd = 1;
+ station.current_tick_tck = 0x1234567890abcdefULL;
+
+ test_begin(t, "init msg")
+ {
+ test_fail_unless(
+ (0 == sci_msg_init(&msg, msg_buffer, 256))
+ && (EINVAL != errno)
+ );
+ } test_end;
+
+ sci_init(&sci, &station);
+
+ test_begin(t, "sci = NULL")
+ {
+ test_fail_unless(
+ (sci_recv(NULL) < 0)
+ && (errno == EINVAL)
+ );
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ sci_register_callback(&sci, SCI_MSG_TYPE_SYSTEM, _sci_send_callback, data_buffer);
+
+ test_begin(t, "push msg")
+ {
+ test_fail_unless(
+ ((int)strlen(TEST_DATA_STR) == sci_msg_push(&msg, strlen(TEST_DATA_STR)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno)
+ );
+ memcpy(msg.data_begin, TEST_DATA_STR, strlen(TEST_DATA_STR));
+ test_fail_unless(
+ ((int)sizeof(station_msg_hdr_t) == sci_msg_push(&msg, sizeof(station_msg_hdr_t)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno)
+ );
+ msg.hdr.station = (station_msg_hdr_t *)msg.data_begin;
+ msg.hdr.station->type = SYSTEM_TYPE_IDLE;
+ } test_end;
+
+ test_begin(t, "fill hdr")
+ {
+ test_fail_unless(
+ sci_fill_hdr(&sci, &msg, SCI_MSG_TYPE_SYSTEM, 0) >= 0
+ );
+ } test_end;
+#ifdef STATION_SOCK
+ fd_in = station.sock_pair_fd;
+#else
+ fd_in = open(station.pipe_in_name, O_WRONLY);
+#endif
+ test_begin(t, "bad magic")
+ {
+ ((char *)&msg.sci_hdr->magic_id)[2] = magic_id[2] + 1;
+ test_fail_unless(
+ (write(fd_in, msg.data_begin, msg.length) == msg.length)
+ && (sci_recv(&sci) < 0)
+ && (errno == EPROTOTYPE)
+ );
+ // reset errno
+ errno = 0;
+ ((char *)&msg.sci_hdr->magic_id)[2] = magic_id[2];
+ } test_end;
+
+ test_begin(t, "length > SCI_MSG_MAX_SIZE")
+ {
+ msg.sci_hdr->length = htons(SCI_MSG_MAX_SIZE + 1 - sizeof(sci_msg_hdr_t));
+ test_fail_unless(
+ (write(fd_in, msg.data_begin, msg.length) == msg.length)
+ && (sci_recv(&sci) < 0)
+ && (errno == ENOSPC)
+ );
+ // reset errno
+ errno = 0;
+ msg.sci_hdr->length = htons(msg.length - sizeof(sci_msg_hdr_t));
+ } test_end;
+
+
+ test_begin(t, "type > SCI_MSG_TYPE_NB")
+ {
+ msg.sci_hdr->type = SCI_MSG_TYPE_NB;
+ test_fail_unless(
+ (write(fd_in, msg.data_begin, msg.length) == msg.length)
+ && (sci_recv(&sci) < 0)
+ && (errno == EPROTOTYPE)
+ );
+ // reset errno
+ errno = 0;
+ msg.sci_hdr->type = SCI_MSG_TYPE_SYSTEM;
+ } test_end;
+
+ test_begin(t, "bad station id")
+ {
+ msg.sci_hdr->station_id = htons(station.id + 1);
+ test_fail_unless(
+ (write(fd_in, msg.data_begin, msg.length) == msg.length)
+ && (sci_recv(&sci) < 0)
+ && (errno == ENODEV)
+ );
+ // reset errno
+ errno = 0;
+ msg.sci_hdr->station_id = htons(station.id);
+ } test_end;
+
+ test_begin(t, "msg_tick is older than current_tick")
+ {
+ msg.sci_hdr->netclock_low = 0;
+ test_fail_unless(
+ (write(fd_in, msg.data_begin, msg.length) == msg.length)
+ && (sci_recv(&sci) >= 0)
+ && (station.current_tick_tck == 0x1234567890abcdefULL)
+ );
+ msg.sci_hdr->netclock_low = 0x90abcdef;
+ } test_end;
+
+ memset(data_buffer, '\0', 16);
+ test_begin(t, "callback process")
+ {
+ msg.sci_hdr->netclock_low = 0xffffffff;
+ test_fail_unless(
+ (write(fd_in, msg.data_begin, msg.length) == msg.length)
+ && (sci_recv(&sci) >= 0)
+ && !memcmp(data_buffer, TEST_RECV_STR, strlen(TEST_RECV_STR))
+ && (station.current_tick_tck == 0x12345678ffffffffULL)
+ );
+ close(fd_in);
+ } test_end;
+
+ close(fd_in);
+ station_down(&station);
+ return;
+}
+
+void sci_test_suite(test_t t)
+{
+ test_suite_begin(t, "sci");
+ //sci_new_test_case(t);
+ sci_init_test_case(t);
+ //sci_free_test_case(t);
+ sci_register_callback_test_case(t);
+ sci_fill_hdr_test_case(t);
+ sci_send_test_case(t);
+ sci_recv_test_case(t);
+}