diff options
author | Jakub Grajciar <grajciar.jakub@gmail.com> | 2017-08-30 10:13:25 +0200 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2017-09-13 20:12:54 +0000 |
commit | 7c5c40db2a8d71a857ae63b6238cfac6e257da6d (patch) | |
tree | f0c01c2087ffd67e770d6f7932849ba13f44f12f /extras/libmemif/test | |
parent | a4393be1a03f6a8f8da5d53c22b8dca52fed6f51 (diff) |
Shared memory packet interface (memif) library
Change-Id: I5097462ae85acd705f19e92517c01094dba7565f
Signed-off-by: Jakub Grajciar <grajciar.jakub@gmail.com>
Diffstat (limited to 'extras/libmemif/test')
-rw-r--r-- | extras/libmemif/test/main_test.c | 1079 | ||||
-rw-r--r-- | extras/libmemif/test/main_test.h | 25 | ||||
-rw-r--r-- | extras/libmemif/test/socket_test.c | 625 | ||||
-rw-r--r-- | extras/libmemif/test/socket_test.h | 25 | ||||
-rw-r--r-- | extras/libmemif/test/unit_test.c | 63 | ||||
-rw-r--r-- | extras/libmemif/test/unit_test.h | 38 |
6 files changed, 1855 insertions, 0 deletions
diff --git a/extras/libmemif/test/main_test.c b/extras/libmemif/test/main_test.c new file mode 100644 index 00000000000..deb8acb69ff --- /dev/null +++ b/extras/libmemif/test/main_test.c @@ -0,0 +1,1079 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <main_test.h> + +#include <memif_private.h> + +#define SOCKET_FILENAME "/run/vpp/memif.sock" + +uint8_t ready_called; +#define read_call (1 << 0) +#define write_call (1 << 1) +#define error_call (1 << 2) + +int +read_fn (memif_connection_t * c) +{ + ready_called |= read_call; + return 0; +} + +int +write_fn (memif_connection_t * c) +{ + ready_called |= write_call; + return 0; +} + +int +error_fn (memif_connection_t * c) +{ + ready_called |= error_call; + return 0; +} + +static void +register_fd_ready_fn (memif_connection_t * c, + memif_fn * read_fn, memif_fn * write_fn, + memif_fn * error_fn) +{ + c->read_fn = read_fn; + c->write_fn = write_fn; + c->error_fn = error_fn; +} + +START_TEST (test_init) +{ + int err; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + libmemif_main_t *lm = &libmemif_main; + + ck_assert_ptr_ne (lm, NULL); + ck_assert_ptr_ne (lm->control_fd_update, NULL); + ck_assert_int_gt (lm->timerfd, 2); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; +} + +END_TEST +START_TEST (test_init_epoll) +{ + int err; + + if ((err = memif_init (NULL, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + libmemif_main_t *lm = &libmemif_main; + + ck_assert_ptr_ne (lm, NULL); + ck_assert_ptr_ne (lm->control_fd_update, NULL); + ck_assert_int_gt (lm->timerfd, 2); + ck_assert_int_gt (memif_epfd, -1); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; +} + +END_TEST +START_TEST (test_create) +{ + int err; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + ck_assert_ptr_ne (c, NULL); + + ck_assert_uint_eq (c->args.interface_id, args.interface_id); + ck_assert_uint_eq (c->args.is_master, args.is_master); + ck_assert_uint_eq (c->args.mode, args.mode); + + ck_assert_uint_eq (c->args.num_s2m_rings, MEMIF_DEFAULT_TX_QUEUES); + ck_assert_uint_eq (c->args.num_m2s_rings, MEMIF_DEFAULT_RX_QUEUES); + ck_assert_uint_eq (c->args.buffer_size, MEMIF_DEFAULT_BUFFER_SIZE); + ck_assert_uint_eq (c->args.log2_ring_size, MEMIF_DEFAULT_LOG2_RING_SIZE); + + ck_assert_ptr_eq (c->msg_queue, NULL); + ck_assert_ptr_eq (c->regions, NULL); + ck_assert_ptr_eq (c->tx_queues, NULL); + ck_assert_ptr_eq (c->rx_queues, NULL); + + ck_assert_int_eq (c->fd, -1); + + ck_assert_ptr_ne (c->on_connect, NULL); + ck_assert_ptr_ne (c->on_disconnect, NULL); + ck_assert_ptr_ne (c->on_interrupt, NULL); + + ck_assert_str_eq (c->args.interface_name, args.interface_name); + ck_assert_str_eq (c->args.instance_name, args.instance_name); + ck_assert_str_eq (c->args.socket_filename, SOCKET_FILENAME); + + struct itimerspec timer; + timerfd_gettime (lm->timerfd, &timer); + + ck_assert_msg (timer.it_interval.tv_sec == lm->arm.it_interval.tv_sec, + "timerfd not armed!"); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_create_master) +{ + int err, rv; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.is_master = 1; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + ck_assert_ptr_ne (c, NULL); + + ck_assert_uint_eq (c->args.interface_id, args.interface_id); + ck_assert_uint_eq (c->args.is_master, args.is_master); + ck_assert_uint_eq (c->args.mode, args.mode); + + ck_assert_uint_eq (c->args.num_s2m_rings, MEMIF_DEFAULT_TX_QUEUES); + ck_assert_uint_eq (c->args.num_m2s_rings, MEMIF_DEFAULT_RX_QUEUES); + ck_assert_uint_eq (c->args.buffer_size, MEMIF_DEFAULT_BUFFER_SIZE); + ck_assert_uint_eq (c->args.log2_ring_size, MEMIF_DEFAULT_LOG2_RING_SIZE); + + ck_assert_ptr_eq (c->msg_queue, NULL); + ck_assert_ptr_eq (c->regions, NULL); + ck_assert_ptr_eq (c->tx_queues, NULL); + ck_assert_ptr_eq (c->rx_queues, NULL); + + ck_assert_int_eq (c->fd, -1); + + ck_assert_ptr_ne (c->on_connect, NULL); + ck_assert_ptr_ne (c->on_disconnect, NULL); + ck_assert_ptr_ne (c->on_interrupt, NULL); + + ck_assert_str_eq (c->args.interface_name, args.interface_name); + ck_assert_str_eq (c->args.instance_name, args.instance_name); + ck_assert_str_eq (c->args.socket_filename, SOCKET_FILENAME); + + struct stat file_stat; + + rv = stat (SOCKET_FILENAME, &file_stat); + ck_assert_int_eq (rv, 0); + + ck_assert (S_ISSOCK (file_stat.st_mode)); + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_create_mult) +{ + int err; + memif_conn_handle_t conn = NULL; + memif_conn_handle_t conn1 = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + args.interface_id = 1; + + if ((err = memif_create (&conn1, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + memif_connection_t *c1 = (memif_connection_t *) conn1; + + ck_assert_ptr_ne (c, NULL); + ck_assert_ptr_ne (c1, NULL); + + ck_assert_uint_eq (c->args.interface_id, 0); + ck_assert_uint_eq (c->args.is_master, args.is_master); + ck_assert_uint_eq (c->args.mode, args.mode); + ck_assert_uint_eq (c1->args.interface_id, 1); + ck_assert_uint_eq (c1->args.is_master, args.is_master); + ck_assert_uint_eq (c1->args.mode, args.mode); + + ck_assert_uint_eq (c->args.num_s2m_rings, MEMIF_DEFAULT_TX_QUEUES); + ck_assert_uint_eq (c->args.num_m2s_rings, MEMIF_DEFAULT_RX_QUEUES); + ck_assert_uint_eq (c->args.buffer_size, MEMIF_DEFAULT_BUFFER_SIZE); + ck_assert_uint_eq (c->args.log2_ring_size, MEMIF_DEFAULT_LOG2_RING_SIZE); + ck_assert_uint_eq (c1->args.num_s2m_rings, MEMIF_DEFAULT_TX_QUEUES); + ck_assert_uint_eq (c1->args.num_m2s_rings, MEMIF_DEFAULT_RX_QUEUES); + ck_assert_uint_eq (c1->args.buffer_size, MEMIF_DEFAULT_BUFFER_SIZE); + ck_assert_uint_eq (c1->args.log2_ring_size, MEMIF_DEFAULT_LOG2_RING_SIZE); + + ck_assert_ptr_eq (c->msg_queue, NULL); + ck_assert_ptr_eq (c->regions, NULL); + ck_assert_ptr_eq (c->tx_queues, NULL); + ck_assert_ptr_eq (c->rx_queues, NULL); + ck_assert_ptr_eq (c1->msg_queue, NULL); + ck_assert_ptr_eq (c1->regions, NULL); + ck_assert_ptr_eq (c1->tx_queues, NULL); + ck_assert_ptr_eq (c1->rx_queues, NULL); + + ck_assert_int_eq (c->fd, -1); + ck_assert_int_eq (c1->fd, -1); + + ck_assert_ptr_ne (c->on_connect, NULL); + ck_assert_ptr_ne (c->on_disconnect, NULL); + ck_assert_ptr_ne (c->on_interrupt, NULL); + ck_assert_ptr_ne (c1->on_connect, NULL); + ck_assert_ptr_ne (c1->on_disconnect, NULL); + ck_assert_ptr_ne (c1->on_interrupt, NULL); + + ck_assert_str_eq (c->args.interface_name, args.interface_name); + ck_assert_str_eq (c->args.instance_name, args.instance_name); + ck_assert_str_eq (c->args.socket_filename, SOCKET_FILENAME); + ck_assert_str_eq (c1->args.interface_name, args.interface_name); + ck_assert_str_eq (c1->args.instance_name, args.instance_name); + ck_assert_str_eq (c1->args.socket_filename, SOCKET_FILENAME); + + struct itimerspec timer; + timerfd_gettime (lm->timerfd, &timer); + + ck_assert_msg (timer.it_interval.tv_sec == lm->arm.it_interval.tv_sec, + "timerfd not armed!"); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_control_fd_handler) +{ + int err; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + if ((err = + memif_control_fd_handler (lm->timerfd, + MEMIF_FD_EVENT_READ)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_NO_FILE, "err code: %u, err msg: %s", err, + memif_strerror (err)); + + register_fd_ready_fn (c, read_fn, write_fn, error_fn); + c->fd = 69; + lm->control_list[0].key = c->fd; + lm->control_list[0].data_struct = c; + + if ((err = + memif_control_fd_handler (c->fd, + MEMIF_FD_EVENT_READ)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert (ready_called & read_call); + + if ((err = + memif_control_fd_handler (c->fd, + MEMIF_FD_EVENT_WRITE)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert (ready_called & write_call); + + if ((err = + memif_control_fd_handler (c->fd, + MEMIF_FD_EVENT_ERROR)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert (ready_called & error_call); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_buffer_alloc) +{ + int err, i; + uint8_t qid; + uint16_t buf; + memif_buffer_t *bufs; + uint16_t max_buf = 10; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + c->fd = 69; + + /* test buffer allocation qid 0 (positive) */ + + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + qid = 0; + if ((err = + memif_buffer_alloc (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (buf, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_uint_eq (bufs[i].buffer_len, MEMIF_DEFAULT_BUFFER_SIZE); + + /* test buffer allocation qid 1 (positive) */ + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + qid = 1; + if ((err = + memif_buffer_alloc (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (buf, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_uint_eq (bufs[i].buffer_len, MEMIF_DEFAULT_BUFFER_SIZE); + + /* test buffer allocation qid 2 (negative) */ + + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + qid = 2; + if ((err = + memif_buffer_alloc (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_QID, "err code: %u, err msg: %s", err, + memif_strerror (err)); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + free (bufs); + bufs = NULL; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_tx_burst) +{ + int err, i; + uint16_t max_buf = 10, buf, tx; + uint8_t qid; + memif_buffer_t *bufs; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + c->fd = 69; + + /* test transmit qid 0 (positive) */ + + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + qid = 0; + if ((err = + memif_buffer_alloc (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (buf, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_uint_eq (bufs[i].buffer_len, MEMIF_DEFAULT_BUFFER_SIZE); + + if ((err = + memif_tx_burst (conn, qid, bufs, max_buf, &tx)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (tx, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_eq (bufs[i].data, NULL); + + /* test transmit qid 1 (positive) */ + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + qid = 1; + if ((err = + memif_buffer_alloc (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (buf, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_uint_eq (bufs[i].buffer_len, MEMIF_DEFAULT_BUFFER_SIZE); + + if ((err = + memif_tx_burst (conn, qid, bufs, max_buf, &tx)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (tx, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_eq (bufs[i].data, NULL); + + /* test transmit qid 2 (negative) */ + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + qid = 2; + if ((err = + memif_tx_burst (conn, qid, bufs, max_buf, &tx)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_QID, "err code: %u, err msg: %s", err, + memif_strerror (err)); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + free (bufs); + bufs = NULL; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_rx_burst) +{ + int err, i; + uint16_t max_buf = 10, buf, rx; + uint8_t qid; + memif_buffer_t *bufs; + memif_queue_t *mq; + memif_ring_t *ring; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + c->fd = 69; + + /* test receive qid 0 (positive) */ + qid = 0; + mq = &c->rx_queues[qid]; + ring = mq->ring; + ring->head += max_buf; + + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + if ((err = + memif_rx_burst (conn, qid, bufs, max_buf, &rx)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (rx, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_ne (bufs[i].data, NULL); + + /* test receive qid 1 (positive) */ + qid = 1; + mq = &c->rx_queues[qid]; + ring = mq->ring; + ring->head += max_buf; + + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + if ((err = + memif_rx_burst (conn, qid, bufs, max_buf, &rx)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (rx, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_ne (bufs[i].data, NULL); + + /* test receive qid 2 (negative) */ + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + if ((err = + memif_rx_burst (conn, qid, bufs, max_buf, &rx)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_QID, "err code: %u, err msg: %s", err, + memif_strerror (err)); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + free (bufs); + bufs = NULL; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_buffer_free) +{ + int err, i; + uint16_t max_buf = 10, buf, rx; + uint8_t qid; + memif_buffer_t *bufs; + memif_queue_t *mq; + memif_ring_t *ring; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + c->fd = 69; + + /* test buffer free qid 0 (positive) */ + qid = 0; + mq = &c->rx_queues[qid]; + ring = mq->ring; + ring->head += 10; + + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + if ((err = + memif_rx_burst (conn, qid, bufs, max_buf, &rx)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (rx, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_ne (bufs[i].data, NULL); + + if ((err = + memif_buffer_free (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (buf, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_eq (bufs[i].data, NULL); + ck_assert_uint_eq (ring->head, ring->tail); + + /* test buffer free qid 1 (positive) */ + qid = 1; + mq = &c->rx_queues[qid]; + ring = mq->ring; + ring->head += 10; + + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + if ((err = + memif_rx_burst (conn, qid, bufs, max_buf, &rx)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (rx, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_ne (bufs[i].data, NULL); + + if ((err = + memif_buffer_free (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (buf, max_buf); + for (i = 0; i < max_buf; i++) + ck_assert_ptr_eq (bufs[i].data, NULL); + ck_assert_uint_eq (ring->head, ring->tail); + + + /* test buffer free qid 2 (negative) */ + qid = 2; + free (bufs); + bufs = malloc (sizeof (memif_buffer_t) * max_buf); + + if ((err = + memif_buffer_free (conn, qid, bufs, max_buf, + &buf)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_QID, "err code: %u, err msg: %s", err, + memif_strerror (err)); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + free (bufs); + bufs = NULL; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_get_details) +{ + int err, i; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_details_t md; + memset (&md, 0, sizeof (md)); + ssize_t buflen = 2048; + char *buf = malloc (buflen); + memset (buf, 0, buflen); + + if ((err = memif_get_details (conn, &md, buf, buflen)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_str_eq (md.if_name, c->args.interface_name); + ck_assert_str_eq (md.inst_name, c->args.instance_name); + ck_assert_str_eq (md.remote_if_name, c->remote_if_name); + ck_assert_str_eq (md.remote_inst_name, c->remote_name); + ck_assert_str_eq (md.secret, c->args.secret); + ck_assert_str_eq (md.socket_filename, c->args.socket_filename); + + ck_assert_uint_eq (md.id, c->args.interface_id); + ck_assert_uint_ne (md.role, c->args.is_master); + ck_assert_uint_eq (md.mode, c->args.mode); + for (i = 0; i < md.rx_queues_num; i++) + { + ck_assert_uint_eq (md.rx_queues[i].qid, i); + ck_assert_uint_eq (md.rx_queues[i].ring_size, + (1 << c->args.log2_ring_size)); + ck_assert_uint_eq (md.rx_queues[i].buffer_size, c->args.buffer_size); + } + for (i = 0; i < md.tx_queues_num; i++) + { + ck_assert_uint_eq (md.tx_queues[i].qid, i); + ck_assert_uint_eq (md.tx_queues[i].ring_size, + (1 << c->args.log2_ring_size)); + ck_assert_uint_eq (md.tx_queues[i].buffer_size, c->args.buffer_size); + } + ck_assert_uint_eq (md.link_up_down, 0); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_init_regions_and_queues) +{ + int err; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_ptr_ne (c->regions, NULL); + ck_assert_ptr_ne (c->tx_queues, NULL); + ck_assert_ptr_ne (c->rx_queues, NULL); + + ck_assert_ptr_ne (c->regions->shm, NULL); + ck_assert_ptr_ne (c->tx_queues->ring, NULL); + ck_assert_ptr_ne (c->rx_queues->ring, NULL); + + ck_assert_int_ne (c->regions->fd, -1); + ck_assert_uint_eq (c->tx_queues->ring->cookie, MEMIF_COOKIE); + ck_assert_uint_eq (c->rx_queues->ring->cookie, MEMIF_COOKIE); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_connect1) +{ + int err; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if ((err = memif_connect1 (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST +START_TEST (test_disconnect_internal) +{ + int err; + ready_called = 0; + memif_conn_handle_t conn = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + args.num_s2m_rings = 2; + args.num_m2s_rings = 2; + + libmemif_main_t *lm = &libmemif_main; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + strncpy ((char *) args.interface_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = memif_create (&conn, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *c = (memif_connection_t *) conn; + + c->run_args.num_s2m_rings = 2; + c->run_args.num_m2s_rings = 2; + c->run_args.log2_ring_size = 10; + c->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if ((err = memif_disconnect_internal (c)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_int_eq (c->fd, -1); + + ck_assert_ptr_eq (c->tx_queues, NULL); + ck_assert_ptr_eq (c->rx_queues, NULL); + ck_assert_ptr_eq (c->regions, NULL); + ck_assert_ptr_eq (c->msg_queue, NULL); + + struct itimerspec timer; + timerfd_gettime (lm->timerfd, &timer); + + ck_assert_msg (timer.it_interval.tv_sec == lm->arm.it_interval.tv_sec, + "timerfd not armed!"); + + if (lm->timerfd > 0) + close (lm->timerfd); + lm->timerfd = -1; + + memif_delete (&conn); + ck_assert_ptr_eq (conn, NULL); +} + +END_TEST Suite * main_suite () +{ + Suite *s; + + TCase *tc_api; + TCase *tc_internal; + + /* create main test suite */ + s = suite_create ("Libmemif main"); + + /* create api test case */ + tc_api = tcase_create ("Api calls"); + /* add tests to test case */ + tcase_add_test (tc_api, test_init); + tcase_add_test (tc_api, test_init_epoll); + tcase_add_test (tc_api, test_create); + tcase_add_test (tc_api, test_create_master); + tcase_add_test (tc_api, test_create_mult); + tcase_add_test (tc_api, test_control_fd_handler); + tcase_add_test (tc_api, test_buffer_alloc); + tcase_add_test (tc_api, test_tx_burst); + tcase_add_test (tc_api, test_rx_burst); + tcase_add_test (tc_api, test_buffer_free); + tcase_add_test (tc_api, test_get_details); + + /* create internal test case */ + tc_internal = tcase_create ("Internal"); + /* add tests to test case */ + tcase_add_test (tc_internal, test_init_regions_and_queues); + tcase_add_test (tc_internal, test_connect1); + tcase_add_test (tc_internal, test_disconnect_internal); + + /* add test cases to test suite */ + suite_add_tcase (s, tc_api); + suite_add_tcase (s, tc_internal); + + /* return main test suite to test runner */ + return s; +} diff --git a/extras/libmemif/test/main_test.h b/extras/libmemif/test/main_test.h new file mode 100644 index 00000000000..300d8a8e46b --- /dev/null +++ b/extras/libmemif/test/main_test.h @@ -0,0 +1,25 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef _MAIN_TEST_H_ +#define _MAIN_TEST_H_ + +#include <unit_test.h> + +Suite *main_suite (); + +#endif /* _MAIN_TEST_H_ */ diff --git a/extras/libmemif/test/socket_test.c b/extras/libmemif/test/socket_test.c new file mode 100644 index 00000000000..f148495afb2 --- /dev/null +++ b/extras/libmemif/test/socket_test.c @@ -0,0 +1,625 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include <socket_test.h> + +#include <memif_private.h> +#include <socket.h> + +static int +get_queue_len (memif_msg_queue_elt_t * q) +{ + int r = 0; + memif_msg_queue_elt_t *c = q; + while (c != NULL) + { + r++; + c = c->next; + } + return r; +} + +static void +queue_free (memif_msg_queue_elt_t ** e) +{ + if (*e == NULL) + return; + queue_free (&(*e)->next); + free (*e); + *e = NULL; + return; +} + +START_TEST (test_msg_queue) +{ + memif_connection_t conn; + conn.msg_queue = NULL; + conn.fd = -1; + + int i, len = 10; + + for (i = 0; i < len; i++) + { + if (i % 2) + memif_msg_enq_ack (&conn); + else + memif_msg_enq_init (&conn); + } + + ck_assert_int_eq (len, get_queue_len (conn.msg_queue)); + + int pop = 6; + + for (i = 0; i < pop; i++) + { + if (i % 2) + { + ck_assert_uint_eq (conn.msg_queue->msg.type, MEMIF_MSG_TYPE_ACK); + } + else + { + ck_assert_uint_eq (conn.msg_queue->msg.type, MEMIF_MSG_TYPE_INIT); + } + conn.flags |= MEMIF_CONNECTION_FLAG_WRITE; + /* function will return -1 because no socket is created */ + memif_conn_fd_write_ready (&conn); + } + + ck_assert_int_eq ((len - pop), get_queue_len (conn.msg_queue)); + + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_enq_ack) +{ + int err; + memif_connection_t conn; + conn.msg_queue = NULL; + + if ((err = memif_msg_enq_ack (&conn)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + memif_msg_queue_elt_t *e = conn.msg_queue; + + ck_assert_uint_eq (e->msg.type, MEMIF_MSG_TYPE_ACK); + ck_assert_int_eq (e->fd, -1); + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_enq_init) +{ + int err; + memif_connection_t conn; + conn.msg_queue = NULL; + + conn.args.interface_id = 69; + conn.args.mode = 0; + + strncpy ((char *) conn.args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + strncpy ((char *) conn.args.secret, TEST_SECRET, strlen (TEST_SECRET)); + + if ((err = memif_msg_enq_init (&conn)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_queue_elt_t *e = conn.msg_queue; + + ck_assert_uint_eq (e->msg.type, MEMIF_MSG_TYPE_INIT); + ck_assert_int_eq (e->fd, -1); + + memif_msg_init_t *i = &e->msg.init; + + ck_assert_uint_eq (i->version, MEMIF_VERSION); + ck_assert_uint_eq (i->id, conn.args.interface_id); + ck_assert_uint_eq (i->mode, conn.args.mode); + ck_assert_str_eq (i->name, conn.args.instance_name); + ck_assert_str_eq (i->secret, conn.args.secret); + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_enq_add_region) +{ + int err; + memif_connection_t conn; + conn.msg_queue = NULL; + conn.regions = (memif_region_t *) malloc (sizeof (memif_region_t)); + memif_region_t *mr = conn.regions; + mr->fd = 5; + mr->region_size = 2048; + uint8_t region_index = 0; + + if ((err = + memif_msg_enq_add_region (&conn, region_index)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_queue_elt_t *e = conn.msg_queue; + + ck_assert_uint_eq (e->msg.type, MEMIF_MSG_TYPE_ADD_REGION); + ck_assert_int_eq (e->fd, mr->fd); + + memif_msg_add_region_t *ar = &e->msg.add_region; + + ck_assert_uint_eq (ar->index, region_index); + ck_assert_uint_eq (ar->size, mr->region_size); + + free (conn.regions); + conn.regions = NULL; + mr = NULL; + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_enq_add_ring) +{ + int err; + memif_connection_t conn; + conn.msg_queue = NULL; + conn.rx_queues = (memif_queue_t *) malloc (sizeof (memif_queue_t)); + conn.tx_queues = (memif_queue_t *) malloc (sizeof (memif_queue_t)); + + memif_queue_t *mq = conn.tx_queues; + uint8_t dir = MEMIF_RING_S2M; + mq->int_fd = 5; + mq->offset = 0; + mq->log2_ring_size = 10; + + if ((err = memif_msg_enq_add_ring (&conn, 0, dir)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_queue_elt_t *e = conn.msg_queue; + + ck_assert_uint_eq (e->msg.type, MEMIF_MSG_TYPE_ADD_RING); + ck_assert_int_eq (e->fd, mq->int_fd); + + memif_msg_add_ring_t *ar = &e->msg.add_ring; + + ck_assert_uint_eq (ar->index, 0); + ck_assert_uint_eq (ar->offset, mq->offset); + ck_assert_uint_eq (ar->log2_ring_size, mq->log2_ring_size); + ck_assert (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M); + + dir = MEMIF_RING_M2S; + if ((err = memif_msg_enq_add_ring (&conn, 0, dir)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_enq_connect) +{ + int err; + memif_connection_t conn; + conn.msg_queue = NULL; + memset (conn.args.interface_name, 0, sizeof (conn.args.interface_name)); + strncpy ((char *) conn.args.interface_name, TEST_IF_NAME, + strlen (TEST_IF_NAME)); + + if ((err = memif_msg_enq_connect (&conn)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_queue_elt_t *e = conn.msg_queue; + + ck_assert_uint_eq (e->msg.type, MEMIF_MSG_TYPE_CONNECT); + ck_assert_int_eq (e->fd, -1); + ck_assert_str_eq (e->msg.connect.if_name, TEST_IF_NAME); + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_enq_connected) +{ + int err; + memif_connection_t conn; + conn.msg_queue = NULL; + memset (conn.args.interface_name, 0, sizeof (conn.args.interface_name)); + strncpy ((char *) conn.args.interface_name, TEST_IF_NAME, + strlen (TEST_IF_NAME)); + + if ((err = memif_msg_enq_connected (&conn)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_queue_elt_t *e = conn.msg_queue; + + ck_assert_uint_eq (e->msg.type, MEMIF_MSG_TYPE_CONNECTED); + ck_assert_int_eq (e->fd, -1); + ck_assert_str_eq (e->msg.connect.if_name, TEST_IF_NAME); + queue_free (&conn.msg_queue); +} + +END_TEST +START_TEST (test_send) +{ + int err; + int fd = -1, afd = 5; + memif_msg_t msg; + memset (&msg, 0, sizeof (msg)); + + if ((err = memif_msg_send (fd, &msg, afd)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_BAD_FD, + "err code: %u, err msg: %s", err, memif_strerror (err)); +} + +END_TEST +START_TEST (test_send_hello) +{ + int err; + memif_connection_t conn; + conn.fd = -1; + memset (conn.args.instance_name, 0, sizeof (conn.args.instance_name)); + strncpy ((char *) conn.args.instance_name, TEST_APP_NAME, + strlen (TEST_APP_NAME)); + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if ((err = memif_msg_send_hello (conn.fd)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_BAD_FD, + "err code: %u, err msg: %s", err, memif_strerror (err)); +} + +END_TEST +START_TEST (test_send_disconnect) +{ + int err; + memif_connection_t conn; + conn.fd = -1; + + /* only possible fail if memif_msg_send fails... */ + /* obsolete without socket */ + if ((err = + memif_msg_send_disconnect (conn.fd, "unit_test_dc", + 0)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_BAD_FD, "err code: %u, err msg: %s", err, + memif_strerror (err)); +} + +END_TEST +START_TEST (test_recv_hello) +{ + int err; + memif_connection_t conn; + memif_msg_t msg; + + memif_msg_hello_t *h = &msg.hello; + + msg.type = MEMIF_MSG_TYPE_HELLO; + + h->min_version = MEMIF_VERSION; + h->max_version = MEMIF_VERSION; + h->max_s2m_ring = 1; + h->max_m2s_ring = 1; + h->max_log2_ring_size = 14; + strncpy ((char *) h->name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + memset (conn.remote_name, 0, sizeof (conn.remote_name)); + + conn.args.num_s2m_rings = 4; + conn.args.num_m2s_rings = 6; + conn.args.log2_ring_size = 10; + + if ((err = memif_msg_receive_hello (&conn, &msg)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_uint_eq (conn.run_args.num_s2m_rings, 2); + ck_assert_uint_eq (conn.run_args.num_m2s_rings, 2); + ck_assert_uint_eq (conn.run_args.log2_ring_size, 10); + ck_assert_str_eq (conn.remote_name, TEST_IF_NAME); + + h->max_version = 9; + if ((err = memif_msg_receive_hello (&conn, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_PROTO, + "err code: %u, err msg: %s", err, memif_strerror (err)); +} + +END_TEST +START_TEST (test_recv_init) +{ + int err; + memif_connection_t conn; + + conn.args.interface_id = 69; + conn.args.is_master = 1; + conn.fd = -1; + conn.args.mode = 0; + memset (conn.args.secret, '\0', 24); + strncpy ((char *) conn.args.secret, TEST_SECRET, strlen (TEST_SECRET)); + + memif_msg_t msg; + + memif_msg_init_t *i = &msg.init; + + msg.type = MEMIF_MSG_TYPE_INIT; + + i->version = MEMIF_VERSION; + i->id = 69; + i->mode = 0; + memset (i->name, '\0', 32); + memset (i->secret, '\0', 24); + strncpy ((char *) i->name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + strncpy ((char *) i->secret, TEST_SECRET, strlen (TEST_SECRET)); + + memif_socket_t ms; + ms.interface_list_len = 1; + ms.interface_list = malloc (sizeof (memif_list_elt_t)); + memif_list_elt_t elt; + elt.key = 69; + elt.data_struct = &conn; + add_list_elt (&elt, &ms.interface_list, &ms.interface_list_len); + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + i->version = 9; + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_PROTO, + "err code: %u, err msg: %s", err, memif_strerror (err)); + i->version = MEMIF_VERSION; + + i->id = 78; + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_ID, + "err code: %u, err msg: %s", err, memif_strerror (err)); + i->id = 69; + + i->mode = 1; + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_MODE, + "err code: %u, err msg: %s", err, memif_strerror (err)); + i->mode = 0; + + i->secret[0] = '\0'; + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_SECRET, + "err code: %u, err msg: %s", err, memif_strerror (err)); + strncpy ((char *) i->secret, TEST_SECRET, strlen (TEST_SECRET)); + + conn.args.is_master = 0; + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_ACCSLAVE, + "err code: %u, err msg: %s", err, memif_strerror (err)); + conn.args.is_master = 1; + + conn.fd = 5; + if ((err = memif_msg_receive_init (&ms, -1, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg ((err == MEMIF_ERR_ALRCONN) || (err == MEMIF_ERR_BAD_FD), + "err code: %u, err msg: %s", err, memif_strerror (err)); +} + +END_TEST +START_TEST (test_recv_add_region) +{ + int err; + memif_connection_t conn; + conn.regions = NULL; + memif_msg_t msg; + msg.type = MEMIF_MSG_TYPE_ADD_REGION; + msg.add_region.size = 2048; + msg.add_region.index = 0; + + int fd = 5; + + if ((err = + memif_msg_receive_add_region (&conn, &msg, fd)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_region_t *mr = conn.regions; + + ck_assert_uint_eq (mr->fd, fd); + ck_assert_uint_eq (mr->region_size, 2048); + ck_assert_ptr_eq (mr->shm, NULL); +} + +END_TEST +START_TEST (test_recv_add_ring) +{ + int err; + memif_connection_t conn; + int fd = 5; + memif_msg_t msg; + conn.args.num_s2m_rings = 2; + conn.args.num_m2s_rings = 2; + conn.rx_queues = NULL; + conn.tx_queues = NULL; + + msg.type = MEMIF_MSG_TYPE_ADD_RING; + memif_msg_add_ring_t *ar = &msg.add_ring; + + ar->log2_ring_size = 10; + ar->region = 0; + ar->offset = 0; + ar->flags = 0; + ar->flags |= MEMIF_MSG_ADD_RING_FLAG_S2M; + ar->index = 1; + + if ((err = + memif_msg_receive_add_ring (&conn, &msg, fd)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + + ar->offset = 2048; + ar->flags &= ~MEMIF_MSG_ADD_RING_FLAG_S2M; + + if ((err = + memif_msg_receive_add_ring (&conn, &msg, fd)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + +} + +END_TEST +START_TEST (test_recv_connect) +{ + int err; + memif_conn_handle_t c = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + + args.interface_id = 0; + args.is_master = 0; + args.mode = 0; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if ((err = memif_create (&c, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *conn = (memif_connection_t *) c; + + conn->run_args.num_s2m_rings = 1; + conn->run_args.num_m2s_rings = 1; + conn->run_args.log2_ring_size = 10; + conn->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (conn)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_t msg; + memset (&msg, 0, sizeof (msg)); + msg.type = MEMIF_MSG_TYPE_CONNECT; + + memset (msg.connect.if_name, 0, sizeof (msg.connect.if_name)); + strncpy ((char *) msg.connect.if_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + + if ((err = memif_msg_receive_connect (conn, &msg)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_str_eq (conn->remote_if_name, TEST_IF_NAME); +} + +END_TEST +START_TEST (test_recv_connected) +{ + int err; + memif_conn_handle_t c = NULL; + memif_conn_args_t args; + memset (&args, 0, sizeof (args)); + + args.interface_id = 0; + args.is_master = 0; + args.mode = 0; + + if ((err = + memif_init (control_fd_update, TEST_APP_NAME)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + if ((err = memif_create (&c, &args, on_connect, + on_disconnect, on_interrupt, + NULL)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_connection_t *conn = (memif_connection_t *) c; + + conn->run_args.num_s2m_rings = 1; + conn->run_args.num_m2s_rings = 1; + conn->run_args.log2_ring_size = 10; + conn->run_args.buffer_size = 2048; + + if ((err = memif_init_regions_and_queues (conn)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + memif_msg_t msg; + memset (&msg, 0, sizeof (msg)); + msg.type = MEMIF_MSG_TYPE_CONNECT; + + memset (msg.connect.if_name, 0, sizeof (msg.connect.if_name)); + strncpy ((char *) msg.connect.if_name, TEST_IF_NAME, strlen (TEST_IF_NAME)); + + if ((err = memif_msg_receive_connected (conn, &msg)) != MEMIF_ERR_SUCCESS) + ck_abort_msg ("err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_str_eq (conn->remote_if_name, TEST_IF_NAME); +} + +END_TEST +START_TEST (test_recv_disconnect) +{ + int err; + memif_connection_t conn; + memif_msg_t msg; + msg.type = MEMIF_MSG_TYPE_DISCONNECT; + memset (msg.disconnect.string, 0, sizeof (msg.disconnect.string)); + strncpy ((char *) msg.disconnect.string, "unit_test_dc", 12); + + if ((err = memif_msg_receive_disconnect (&conn, &msg)) != MEMIF_ERR_SUCCESS) + ck_assert_msg (err == MEMIF_ERR_DISCONNECT, + "err code: %u, err msg: %s", err, memif_strerror (err)); + + ck_assert_str_eq (conn.remote_disconnect_string, "unit_test_dc"); +} + +END_TEST Suite * socket_suite () +{ + Suite *s; + TCase *tc_msg_queue; + TCase *tc_msg_enq; + TCase *tc_msg_send; + TCase *tc_msg_recv; + + /* create socket test suite */ + s = suite_create ("Socket messaging"); + + /* create msg queue test case */ + tc_msg_queue = tcase_create ("Message queue"); + /* add tests to test case */ + tcase_add_test (tc_msg_queue, test_msg_queue); + + /* create msg enq test case */ + tc_msg_enq = tcase_create ("Message enqueue"); + /* add tests to test case */ + tcase_add_test (tc_msg_enq, test_enq_ack); + tcase_add_test (tc_msg_enq, test_enq_init); + tcase_add_test (tc_msg_enq, test_enq_add_region); + tcase_add_test (tc_msg_enq, test_enq_add_ring); + tcase_add_test (tc_msg_enq, test_enq_connect); + tcase_add_test (tc_msg_enq, test_enq_connected); + + /* create msg send test case */ + tc_msg_send = tcase_create ("Message send"); + /* add tests to test case */ + tcase_add_test (tc_msg_send, test_send); + tcase_add_test (tc_msg_send, test_send_hello); + tcase_add_test (tc_msg_send, test_send_disconnect); + + /* create msg recv test case */ + tc_msg_recv = tcase_create ("Message receive"); + /* add tests to test case */ + tcase_add_test (tc_msg_recv, test_recv_hello); + tcase_add_test (tc_msg_recv, test_recv_init); + tcase_add_test (tc_msg_recv, test_recv_add_region); + tcase_add_test (tc_msg_recv, test_recv_add_ring); + tcase_add_test (tc_msg_recv, test_recv_connect); + tcase_add_test (tc_msg_recv, test_recv_connected); + tcase_add_test (tc_msg_recv, test_recv_disconnect); + + /* add test cases to test suite */ + suite_add_tcase (s, tc_msg_queue); + suite_add_tcase (s, tc_msg_enq); + suite_add_tcase (s, tc_msg_send); + suite_add_tcase (s, tc_msg_recv); + + /* return socket test suite to test runner */ + return s; +} diff --git a/extras/libmemif/test/socket_test.h b/extras/libmemif/test/socket_test.h new file mode 100644 index 00000000000..02ec69cfbd7 --- /dev/null +++ b/extras/libmemif/test/socket_test.h @@ -0,0 +1,25 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef _SOCKET_TEST_H_ +#define _SOCKET_TEST_H_ + +#include <unit_test.h> + +Suite *socket_suite (); + +#endif /* _SOCKET_TEST_H_ */ diff --git a/extras/libmemif/test/unit_test.c b/extras/libmemif/test/unit_test.c new file mode 100644 index 00000000000..a305de93fbe --- /dev/null +++ b/extras/libmemif/test/unit_test.c @@ -0,0 +1,63 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include <main_test.h> +#include <socket_test.h> + +int +on_connect (memif_conn_handle_t conn, void *ctx) +{ + return 0; +} + +int +on_disconnect (memif_conn_handle_t conn, void *ctx) +{ + return 0; +} + +int +on_interrupt (memif_conn_handle_t conn, void *ctx, uint16_t qid) +{ + return 0; +} + +int +control_fd_update (int fd, uint8_t events) +{ + return 0; +} + +int +main (void) +{ + int num_fail; + Suite *main, *socket; + SRunner *sr; + + main = main_suite (); + socket = socket_suite (); + + sr = srunner_create (main); + + srunner_add_suite (sr, socket); + + srunner_run_all (sr, CK_VERBOSE); + num_fail = srunner_ntests_failed (sr); + srunner_free (sr); + return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/extras/libmemif/test/unit_test.h b/extras/libmemif/test/unit_test.h new file mode 100644 index 00000000000..fae3cbaae2a --- /dev/null +++ b/extras/libmemif/test/unit_test.h @@ -0,0 +1,38 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef _UNIT_TEST_H_ +#define _UNIT_TEST_H_ + +#include <stdlib.h> +#include <check.h> + +#include <libmemif.h> + +#define TEST_APP_NAME "unit_test_app" +#define TEST_IF_NAME "unit_test_if" +#define TEST_SECRET "psst" + +int on_connect (memif_conn_handle_t conn, void *ctx); + +int on_disconnect (memif_conn_handle_t conn, void *ctx); + +int on_interrupt (memif_conn_handle_t conn, void *ctx, uint16_t qid); + +int control_fd_update (int fd, uint8_t events); + +#endif /* _UNIT_TEST_H_ */ |