/* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file test_netclock.c * \brief Test all netclock functions. * \ingroup test */ #include #include #include #include #include #include "common/std.h" #include "host/netclock.h" #include "lib/test.h" #include extern char dump_buffer[]; //void netclock_new_test_case(test_t t) //{ // netclock_ctx_t *netclock; // station_ctx_t *station; // // test_case_begin(t, "new"); // station = station_new(); // // test_begin(t, "station = NULL") // { // test_fail_unless( // (netclock_new(NULL) == NULL) // && (errno == EINVAL) // ); // } test_end; // // test_begin(t, "check new") // { // test_fail_unless( // ((netclock = netclock_new(station)) != NULL) // && (netclock->station == station) // ); // } test_end; // // netclock_free(netclock); // station_free(station); // return; //} // //void netclock_free_test_case(test_t t) //{ // return //} void netclock_init_test_case(test_t t) { netclock_ctx_t netclock; station_ctx_t station; sci_ctx_t sci; test_case_begin(t, "init"); sci_init(&sci, &station); test_begin(t, "netclock = NULL") { test_fail_unless( (netclock_init(NULL, &sci) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "sci = NULL") { test_fail_unless( (netclock_init(&netclock, NULL) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "check init") { test_fail_unless( (netclock_init(&netclock, &sci) >= 0) && (netclock.sci == &sci) && (netclock.callback_nb == 0) && (netclock.current_id == 1) && (netclock.sci->msg_callback[SCI_MSG_TYPE_NETWORK_CLOCK].function == netclock_recv) && (netclock.sci->msg_callback[SCI_MSG_TYPE_NETWORK_CLOCK].data == &netclock) // && (set_empty(&netclock.callback_set)) ); } test_end; return; } #define FCALL_DATA_STR "fill_hdr test" void netclock_fill_hdr_test_case(test_t t) { netclock_ctx_t netclock; station_ctx_t station; sci_ctx_t sci; sci_msg_t msg; unsigned char buffer[256]; test_case_begin(t, "fill_hdr"); station_init(&station); sci_init(&sci, &station); netclock_init(&netclock, &sci); test_begin(t, "init msg") { test_fail_unless( (0 == sci_msg_init(&msg, buffer, 256)) && (EINVAL != errno) ); } test_end; test_begin(t, "netclock = NULL") { test_fail_unless( (netclock_fill_hdr(NULL, &msg, NETWORK_CLOCK_TYPE_SYSTEM, 0, 0x1234567890abcdefULL) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "msg = NULL") { test_fail_unless( (netclock_fill_hdr(&netclock, NULL, NETWORK_CLOCK_TYPE_SYSTEM, 0, 0x1234567890abcdefULL) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "type < 0") { test_fail_unless( (netclock_fill_hdr(&netclock, &msg, -1, 0, 0x1234567890abcdefULL) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "type > max type value") { test_fail_unless( (netclock_fill_hdr(&netclock, &msg, NETWORK_CLOCK_TYPE_NB, 0, 0x1234567890abcdefULL) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "check fill_hdr") { int previous_id = netclock.current_id; test_fail_unless( (netclock_fill_hdr(&netclock, &msg, NETWORK_CLOCK_TYPE_SYSTEM, 0xa55a, 0x1234567890abcdefULL) >= 0) && ((unsigned char *)msg.hdr.netclock == msg.data_begin) && (msg.hdr.netclock->type == NETWORK_CLOCK_TYPE_SYSTEM) && (ntohs(msg.hdr.netclock->id) == previous_id) && (ntohs(msg.hdr.netclock->flags) == 0xa55a) && (ntohl(msg.hdr.netclock->tick_high) == 0x12345678) && (ntohl(msg.hdr.netclock->tick_low) == 0x90abcdef) && (netclock.current_id == ((previous_id + 1) & NETWORK_CLOCK_ID_MASK)) ); } test_end; test_begin(t, "id rollover") { netclock.current_id = NETWORK_CLOCK_ID_MASK; test_fail_unless( (netclock_fill_hdr(&netclock, &msg, NETWORK_CLOCK_TYPE_SYSTEM, 0xa55a, 0x1234567890abcdefULL) >= 0) && ((unsigned char *)msg.hdr.netclock == msg.data_begin) && (ntohs(msg.hdr.netclock->id) == NETWORK_CLOCK_ID_MASK) && (netclock.current_id == 0) ); } test_end; station_down(&station); return; } static void _test_schedule(void *data) { return; } static void _fake_schedule(void *data) { return; } void netclock_schedule_test_case(test_t t) { netclock_ctx_t netclock; netclock_callback_t callback, cb_reference; station_ctx_t station; sci_ctx_t sci; char data[32]; netclock_id_t id; sci_msg_hdr_t *hdr; netclock_msg_hdr_t *nclock_hdr; int fd_in, len; unsigned char buffer[1024]; test_case_begin(t, "schedule"); station_init(&station); sci_init(&sci, &station); netclock_init(&netclock, &sci); test_begin(t, "netclock = NULL") { test_fail_unless( (netclock_schedule(NULL, &callback, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data, &id) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end test_begin(t, "callback = NULL") { test_fail_unless( (netclock_schedule(&netclock, NULL, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data, &id) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end test_begin(t, "type < 0") { test_fail_unless( (netclock_schedule(&netclock, &callback, -1, 0x1234567890abcdefULL, _test_schedule, data, &id) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "type >= max value") { test_fail_unless( (netclock_schedule(&netclock, &callback, NETWORK_CLOCK_TYPE_NB, 0x1234567890abcdefULL, _test_schedule, data, &id) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end test_begin(t, "tick < current_tick") { station.current_tick_tck = 0x2234567890abcdefULL; test_fail_unless( (netclock_schedule(&netclock, &callback, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data, &id) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end test_begin(t, "id = NULL") { test_fail_unless( (netclock_schedule(&netclock, &callback, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data, &id) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end #ifdef STATION_SOCK fd_in = station.sock_pair_fd; #else /* STATION_SOCK */ fd_in = open(station.pipe_out_name, O_RDONLY); #endif /* STATION_SOCK */ test_begin(t, "recv netclock msg") { station.current_tick_tck = 0x0ULL; id = 0; set_node_init(&cb_reference.node); cb_reference.id = callback.id + 1; test_fail_unless( (netclock_schedule(&netclock, &callback, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data, &id) >= 0) && (set_begin(&netclock.callback_set) == set_find(&netclock.callback_set, &cb_reference.node)) && (set_begin(&netclock.callback_set) == &callback.node) && (callback.function == _test_schedule) && (callback.data == data) && (callback.id == netclock.current_id - 1) && (callback.tick == 0x1234567890abcdefULL) && (id == netclock.current_id - 1) && (netclock.callback_nb == 1) ); test_fail_if((len = read(fd_in, buffer, sizeof(sci_msg_hdr_t))) != sizeof(sci_msg_hdr_t)); hdr = (sci_msg_hdr_t *)buffer; test_fail_unless( (hdr->type == SCI_MSG_TYPE_NETWORK_CLOCK) ); test_fail_if((len = read(fd_in, buffer + sizeof(sci_msg_hdr_t), htons(hdr->length))) != sizeof(netclock_msg_hdr_t)); nclock_hdr = (netclock_msg_hdr_t *)(buffer + sizeof(sci_msg_hdr_t)); test_fail_unless( (nclock_hdr->type == NETWORK_CLOCK_TYPE_PHY) && (ntohl(nclock_hdr->tick_high) == 0x12345678) && (ntohl(nclock_hdr->tick_low) == 0x90abcdef) ); } test_end; // test_begin(t, "full registring table") // { // int i; // netclock.callback_nb = NETCLOCK_CALLBACK_MAX_NB; // test_fail_unless( // (netclock_schedule(&netclock, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data) < 0) // && (errno == ENOSPC) // ); // netclock.callback_nb = 1; // // for(i = 0; i < NETCLOCK_CALLBACK_TABLE_SIZE; i++) // { // netclock.callback_table[i].function = _fake_schedule; // } // test_fail_unless( // (netclock_schedule(&netclock, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data) < 0) // && (errno == ENOSPC) // ); // } test_end; // // test_begin(t, "one free slot") // { // netclock.callback_table[NETCLOCK_CALLBACK_TABLE_SIZE / 2].function = NULL; // netclock.callback_nb = NETCLOCK_CALLBACK_TABLE_SIZE - 1; // test_fail_unless( // (netclock_schedule(&netclock, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_schedule, data) > 0) // && (netclock.callback_table[NETCLOCK_CALLBACK_TABLE_SIZE / 2].function == _test_schedule) // && (netclock.callback_nb == NETCLOCK_CALLBACK_TABLE_SIZE) // ); // } test_end; station_down(&station); #ifndef STATION_SOCK close(fd_in); #endif /* STATION_SOCK */ return; } void netclock_unschedule_test_case(test_t t) { netclock_ctx_t netclock; station_ctx_t station; sci_ctx_t sci; sci_msg_hdr_t *hdr; netclock_msg_hdr_t *nclock_hdr; int fd_in; int len; unsigned char buffer[1024]; test_case_begin(t, "unschedule"); station_init(&station); sci_init(&sci, &station); netclock_init(&netclock, &sci); test_begin(t, "netclock = NULL") { test_fail_unless( (netclock_unschedule(NULL, 0) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end test_begin(t, "check unschedule") { netclock_callback_t callback1, callback2, cb_ref; callback1.id = 0x1233; callback1.function = _fake_schedule; set_node_init(&callback1.node); set_insert(&netclock.callback_set, &callback1.node); callback2.id = 0x1234; callback2.function = _test_schedule; set_node_init(&callback2.node); set_insert(&netclock.callback_set, &callback2.node); netclock.callback_nb = 2; set_node_init(&cb_ref.node); cb_ref.id = callback2.id; test_fail_unless( (netclock_unschedule(&netclock, 0x1234) >= 0) && (set_find(&netclock.callback_set, &cb_ref.node) == NULL) && (netclock.callback_nb == 1) ); #ifdef STATION_SOCK fd_in = station.sock_pair_fd; #else /* STATION_SOCK */ fd_in = open(station.pipe_out_name, O_RDONLY); #endif /* STATION_SOCK */ test_fail_if((len = read(fd_in, buffer, sizeof(sci_msg_hdr_t))) != sizeof(sci_msg_hdr_t)); hdr = (sci_msg_hdr_t *)buffer; test_fail_unless( (hdr->type == SCI_MSG_TYPE_NETWORK_CLOCK) ); test_fail_if((len = read(fd_in, buffer + sizeof(sci_msg_hdr_t), htons(hdr->length))) != sizeof(netclock_msg_hdr_t)); nclock_hdr = (netclock_msg_hdr_t *)(buffer + sizeof(sci_msg_hdr_t)); test_fail_unless( (nclock_hdr->type == NETWORK_CLOCK_TYPE_REMOVE) && (ntohs(nclock_hdr->id) == 0x1234) ); } test_end; test_begin(t, "id not exist") { test_fail_unless( (netclock_unschedule(&netclock, 0x1234) < 0) && (errno == ENOENT) && (netclock.callback_nb == 1) ); // reset errno errno = 0; } test_end; station_down(&station); #ifndef STATION_SOCK close(fd_in); #endif /* STATION_SOCK */ return; } static void _test_callback(void *data) { char *buffer; if(data == NULL) return; buffer = (char *)data; strcpy(buffer, "test_callback"); return; } void netclock_recv_test_case(test_t t) { netclock_ctx_t netclock; netclock_callback_t callback; station_ctx_t station; sci_ctx_t sci; sci_msg_t msg; sci_msg_hdr_t hdr; netclock_id_t id; unsigned char buffer[256]; char data_buffer[32]; int fd_in; test_case_begin(t, "recv"); station_init(&station); sci_init(&sci, &station); netclock_init(&netclock, &sci); test_begin(t, "init msg") { test_fail_unless( (0 == sci_msg_init(&msg, buffer, 256)) && (EINVAL != errno) ); } test_end; test_begin(t, "msg = NULL") { test_fail_unless( (netclock_recv(NULL, &netclock) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; test_begin(t, "netclock = NULL") { test_fail_unless( (netclock_recv(&msg, NULL) < 0) && (errno == EINVAL) ); // reset errno errno = 0; } test_end; #ifdef STATION_SOCK fd_in = station.sock_pair_fd; #else /* STATION_SOCK */ fd_in = open(station.pipe_out_name, O_RDONLY); #endif /* STATION_SOCK */ memset(data_buffer, '\0', 32); test_begin(t, "recv") { test_fail_unless( (netclock_schedule(&netclock, &callback, NETWORK_CLOCK_TYPE_PHY, 0x1234567890abcdefULL, _test_callback, data_buffer, &id) >= 0) ); test_fail_unless( (read(fd_in, &hdr, sizeof(sci_msg_hdr_t)) == (int)sizeof(sci_msg_hdr_t)) ); test_fail_unless( (ntohs(hdr.length) == sci_msg_push(&msg, ntohs(hdr.length))) && (EINVAL != errno) && (ENOSPC != errno) ); test_fail_unless( (read(fd_in, msg.data_begin, ntohs(hdr.length)) == ntohs(hdr.length)) ); test_fail_unless( (netclock_recv(&msg, &netclock) >= 0) && !memcmp(data_buffer, "test_callback", strlen("test_callback") + 1) && (netclock.callback_nb == 0) ); } test_end; #ifndef STATION_SOCK close(fd_in); #endif /* STATION_SOCK */ station_down(&station); return; } void netclock_test_suite(test_t t) { test_suite_begin(t, "netclock"); //netclock_new_test_case(t); //netclock_free_test_case(t); netclock_init_test_case(t); netclock_fill_hdr_test_case(t); netclock_schedule_test_case(t); netclock_unschedule_test_case(t); netclock_recv_test_case(t); }