Add functional tests for rte_ring_xxx_elem APIs. At this point these are derived mainly from existing rte_ring_xxx test cases.
Signed-off-by: Honnappa Nagarahalli <honnappa.nagaraha...@arm.com> --- app/test/Makefile | 1 + app/test/meson.build | 1 + app/test/test_ring_elem.c | 859 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 861 insertions(+) create mode 100644 app/test/test_ring_elem.c diff --git a/app/test/Makefile b/app/test/Makefile index 26ba6fe2b..483865b4a 100644 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -77,6 +77,7 @@ SRCS-y += test_external_mem.c SRCS-y += test_rand_perf.c SRCS-y += test_ring.c +SRCS-y += test_ring_elem.c SRCS-y += test_ring_perf.c SRCS-y += test_pmd_perf.c diff --git a/app/test/meson.build b/app/test/meson.build index ec40943bd..1ca25c00a 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -100,6 +100,7 @@ test_sources = files('commands.c', 'test_red.c', 'test_reorder.c', 'test_ring.c', + 'test_ring_elem.c', 'test_ring_perf.c', 'test_rwlock.c', 'test_sched.c', diff --git a/app/test/test_ring_elem.c b/app/test/test_ring_elem.c new file mode 100644 index 000000000..54ae35a71 --- /dev/null +++ b/app/test/test_ring_elem.c @@ -0,0 +1,859 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_log.h> +#include <rte_memory.h> +#include <rte_launch.h> +#include <rte_cycles.h> +#include <rte_eal.h> +#include <rte_per_lcore.h> +#include <rte_lcore.h> +#include <rte_atomic.h> +#include <rte_branch_prediction.h> +#include <rte_malloc.h> +#include <rte_ring.h> +#include <rte_ring_elem.h> +#include <rte_random.h> +#include <rte_errno.h> +#include <rte_hexdump.h> + +#include "test.h" + +/* + * Ring + * ==== + * + * #. Basic tests: done on one core: + * + * - Using single producer/single consumer functions: + * + * - Enqueue one object, two objects, MAX_BULK objects + * - Dequeue one object, two objects, MAX_BULK objects + * - Check that dequeued pointers are correct + * + * - Using multi producers/multi consumers functions: + * + * - Enqueue one object, two objects, MAX_BULK objects + * - Dequeue one object, two objects, MAX_BULK objects + * - Check that dequeued pointers are correct + * + * #. Performance tests. + * + * Tests done in test_ring_perf.c + */ + +#define RING_SIZE 4096 +#define MAX_BULK 32 + +static rte_atomic32_t synchro; + +#define TEST_RING_VERIFY(exp) \ + if (!(exp)) { \ + printf("error at %s:%d\tcondition " #exp " failed\n", \ + __func__, __LINE__); \ + rte_ring_dump(stdout, r); \ + return -1; \ + } + +#define TEST_RING_FULL_EMTPY_ITER 8 + +/* + * helper routine for test_ring_basic + */ +static int +test_ring_basic_full_empty(struct rte_ring *r, void * const src, void *dst) +{ + unsigned i, rand; + const unsigned rsz = RING_SIZE - 1; + + printf("Basic full/empty test\n"); + + for (i = 0; TEST_RING_FULL_EMTPY_ITER != i; i++) { + + /* random shift in the ring */ + rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL); + printf("%s: iteration %u, random shift: %u;\n", + __func__, i, rand); + TEST_RING_VERIFY(rte_ring_enqueue_bulk_elem(r, src, 8, rand, + NULL) != 0); + TEST_RING_VERIFY(rte_ring_dequeue_bulk_elem(r, dst, 8, rand, + NULL) == rand); + + /* fill the ring */ + TEST_RING_VERIFY(rte_ring_enqueue_bulk_elem(r, src, 8, rsz, NULL) != 0); + TEST_RING_VERIFY(0 == rte_ring_free_count(r)); + TEST_RING_VERIFY(rsz == rte_ring_count(r)); + TEST_RING_VERIFY(rte_ring_full(r)); + TEST_RING_VERIFY(0 == rte_ring_empty(r)); + + /* empty the ring */ + TEST_RING_VERIFY(rte_ring_dequeue_bulk_elem(r, dst, 8, rsz, + NULL) == rsz); + TEST_RING_VERIFY(rsz == rte_ring_free_count(r)); + TEST_RING_VERIFY(0 == rte_ring_count(r)); + TEST_RING_VERIFY(0 == rte_ring_full(r)); + TEST_RING_VERIFY(rte_ring_empty(r)); + + /* check data */ + TEST_RING_VERIFY(0 == memcmp(src, dst, rsz)); + rte_ring_dump(stdout, r); + } + return 0; +} + +static int +test_ring_basic(struct rte_ring *r) +{ + void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; + int ret; + unsigned i, num_elems; + + /* alloc dummy object pointers */ + src = malloc(RING_SIZE*2*sizeof(void *)); + if (src == NULL) + goto fail; + + for (i = 0; i < RING_SIZE*2 ; i++) { + src[i] = (void *)(unsigned long)i; + } + cur_src = src; + + /* alloc some room for copied objects */ + dst = malloc(RING_SIZE*2*sizeof(void *)); + if (dst == NULL) + goto fail; + + memset(dst, 0, RING_SIZE*2*sizeof(void *)); + cur_dst = dst; + + printf("enqueue 1 obj\n"); + ret = rte_ring_sp_enqueue_bulk_elem(r, cur_src, 8, 1, NULL); + cur_src += 1; + if (ret == 0) + goto fail; + + printf("enqueue 2 objs\n"); + ret = rte_ring_sp_enqueue_bulk_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret == 0) + goto fail; + + printf("enqueue MAX_BULK objs\n"); + ret = rte_ring_sp_enqueue_bulk_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret == 0) + goto fail; + + printf("dequeue 1 obj\n"); + ret = rte_ring_sc_dequeue_bulk_elem(r, cur_dst, 8, 1, NULL); + cur_dst += 1; + if (ret == 0) + goto fail; + + printf("dequeue 2 objs\n"); + ret = rte_ring_sc_dequeue_bulk_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret == 0) + goto fail; + + printf("dequeue MAX_BULK objs\n"); + ret = rte_ring_sc_dequeue_bulk_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret == 0) + goto fail; + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + cur_src = src; + cur_dst = dst; + + printf("enqueue 1 obj\n"); + ret = rte_ring_mp_enqueue_bulk_elem(r, cur_src, 8, 1, NULL); + cur_src += 1; + if (ret == 0) + goto fail; + + printf("enqueue 2 objs\n"); + ret = rte_ring_mp_enqueue_bulk_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret == 0) + goto fail; + + printf("enqueue MAX_BULK objs\n"); + ret = rte_ring_mp_enqueue_bulk_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret == 0) + goto fail; + + printf("dequeue 1 obj\n"); + ret = rte_ring_mc_dequeue_bulk_elem(r, cur_dst, 8, 1, NULL); + cur_dst += 1; + if (ret == 0) + goto fail; + + printf("dequeue 2 objs\n"); + ret = rte_ring_mc_dequeue_bulk_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret == 0) + goto fail; + + printf("dequeue MAX_BULK objs\n"); + ret = rte_ring_mc_dequeue_bulk_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret == 0) + goto fail; + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + cur_src = src; + cur_dst = dst; + + printf("fill and empty the ring\n"); + for (i = 0; i<RING_SIZE/MAX_BULK; i++) { + ret = rte_ring_mp_enqueue_bulk_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret == 0) + goto fail; + ret = rte_ring_mc_dequeue_bulk_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret == 0) + goto fail; + } + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + if (test_ring_basic_full_empty(r, src, dst) != 0) + goto fail; + + cur_src = src; + cur_dst = dst; + + printf("test default bulk enqueue / dequeue\n"); + num_elems = 16; + + cur_src = src; + cur_dst = dst; + + ret = rte_ring_enqueue_bulk_elem(r, cur_src, 8, num_elems, NULL); + cur_src += num_elems; + if (ret == 0) { + printf("Cannot enqueue\n"); + goto fail; + } + ret = rte_ring_enqueue_bulk_elem(r, cur_src, 8, num_elems, NULL); + cur_src += num_elems; + if (ret == 0) { + printf("Cannot enqueue\n"); + goto fail; + } + ret = rte_ring_dequeue_bulk_elem(r, cur_dst, 8, num_elems, NULL); + cur_dst += num_elems; + if (ret == 0) { + printf("Cannot dequeue\n"); + goto fail; + } + ret = rte_ring_dequeue_bulk_elem(r, cur_dst, 8, num_elems, NULL); + cur_dst += num_elems; + if (ret == 0) { + printf("Cannot dequeue2\n"); + goto fail; + } + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + cur_src = src; + cur_dst = dst; + + ret = rte_ring_mp_enqueue_elem(r, cur_src, 8); + if (ret != 0) + goto fail; + + ret = rte_ring_mc_dequeue_elem(r, cur_dst, 8); + if (ret != 0) + goto fail; + + free(src); + free(dst); + return 0; + + fail: + free(src); + free(dst); + return -1; +} + +static int +test_ring_burst_basic(struct rte_ring *r) +{ + void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; + int ret; + unsigned i; + + /* alloc dummy object pointers */ + src = malloc(RING_SIZE*2*sizeof(void *)); + if (src == NULL) + goto fail; + + for (i = 0; i < RING_SIZE*2 ; i++) { + src[i] = (void *)(unsigned long)i; + } + cur_src = src; + + /* alloc some room for copied objects */ + dst = malloc(RING_SIZE*2*sizeof(void *)); + if (dst == NULL) + goto fail; + + memset(dst, 0, RING_SIZE*2*sizeof(void *)); + cur_dst = dst; + + printf("Test SP & SC basic functions \n"); + printf("enqueue 1 obj\n"); + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, 1, NULL); + cur_src += 1; + if (ret != 1) + goto fail; + + printf("enqueue 2 objs\n"); + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret != 2) + goto fail; + + printf("enqueue MAX_BULK objs\n"); + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + + printf("dequeue 1 obj\n"); + ret = rte_ring_sc_dequeue_burst_elem(r, cur_dst, 8, 1, NULL); + cur_dst += 1; + if (ret != 1) + goto fail; + + printf("dequeue 2 objs\n"); + ret = rte_ring_sc_dequeue_burst_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret != 2) + goto fail; + + printf("dequeue MAX_BULK objs\n"); + ret = rte_ring_sc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + cur_src = src; + cur_dst = dst; + + printf("Test enqueue without enough memory space \n"); + for (i = 0; i < (RING_SIZE/MAX_BULK - 1); i++) { + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + } + + printf("Enqueue 2 objects, free entries = MAX_BULK - 2 \n"); + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret != 2) + goto fail; + + printf("Enqueue the remaining entries = MAX_BULK - 2 \n"); + /* Always one free entry left */ + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK - 3; + if (ret != MAX_BULK - 3) + goto fail; + + printf("Test if ring is full \n"); + if (rte_ring_full(r) != 1) + goto fail; + + printf("Test enqueue for a full entry \n"); + ret = rte_ring_sp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + if (ret != 0) + goto fail; + + printf("Test dequeue without enough objects \n"); + for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) { + ret = rte_ring_sc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + } + + /* Available memory space for the exact MAX_BULK entries */ + ret = rte_ring_sc_dequeue_burst_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret != 2) + goto fail; + + ret = rte_ring_sc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK - 3; + if (ret != MAX_BULK - 3) + goto fail; + + printf("Test if ring is empty \n"); + /* Check if ring is empty */ + if (1 != rte_ring_empty(r)) + goto fail; + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + cur_src = src; + cur_dst = dst; + + printf("Test MP & MC basic functions \n"); + + printf("enqueue 1 obj\n"); + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, 1, NULL); + cur_src += 1; + if (ret != 1) + goto fail; + + printf("enqueue 2 objs\n"); + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret != 2) + goto fail; + + printf("enqueue MAX_BULK objs\n"); + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + + printf("dequeue 1 obj\n"); + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, 1, NULL); + cur_dst += 1; + if (ret != 1) + goto fail; + + printf("dequeue 2 objs\n"); + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret != 2) + goto fail; + + printf("dequeue MAX_BULK objs\n"); + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + cur_src = src; + cur_dst = dst; + + printf("fill and empty the ring\n"); + for (i = 0; i < RING_SIZE/MAX_BULK; i++) { + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + } + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + cur_src = src; + cur_dst = dst; + + printf("Test enqueue without enough memory space \n"); + for (i = 0; i < RING_SIZE/MAX_BULK - 1; i++) { + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + } + + /* Available memory space for the exact MAX_BULK objects */ + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret != 2) + goto fail; + + ret = rte_ring_mp_enqueue_burst_elem(r, cur_src, 8, MAX_BULK, NULL); + cur_src += MAX_BULK - 3; + if (ret != MAX_BULK - 3) + goto fail; + + + printf("Test dequeue without enough objects \n"); + for (i = 0; i < RING_SIZE/MAX_BULK - 1; i++) { + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK; + if (ret != MAX_BULK) + goto fail; + } + + /* Available objects - the exact MAX_BULK */ + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret != 2) + goto fail; + + ret = rte_ring_mc_dequeue_burst_elem(r, cur_dst, 8, MAX_BULK, NULL); + cur_dst += MAX_BULK - 3; + if (ret != MAX_BULK - 3) + goto fail; + + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } + + cur_src = src; + cur_dst = dst; + + printf("Covering rte_ring_enqueue_burst functions \n"); + + ret = rte_ring_enqueue_burst_elem(r, cur_src, 8, 2, NULL); + cur_src += 2; + if (ret != 2) + goto fail; + + ret = rte_ring_dequeue_burst_elem(r, cur_dst, 8, 2, NULL); + cur_dst += 2; + if (ret != 2) + goto fail; + + /* Free memory before test completed */ + free(src); + free(dst); + return 0; + + fail: + free(src); + free(dst); + return -1; +} + +/* + * it will always fail to create ring with a wrong ring size number in this function + */ +static int +test_ring_creation_with_wrong_size(void) +{ + struct rte_ring * rp = NULL; + + /* Test if ring size is not power of 2 */ + rp = rte_ring_create_elem("test_bad_ring_size", RING_SIZE + 1, 8, SOCKET_ID_ANY, 0); + if (NULL != rp) { + return -1; + } + + /* Test if ring size is exceeding the limit */ + rp = rte_ring_create_elem("test_bad_ring_size", (RTE_RING_SZ_MASK + 1), 8, SOCKET_ID_ANY, 0); + if (NULL != rp) { + return -1; + } + return 0; +} + +/* + * it tests if it would always fail to create ring with an used ring name + */ +static int +test_ring_creation_with_an_used_name(void) +{ + struct rte_ring * rp; + + rp = rte_ring_create_elem("test", RING_SIZE, 8, SOCKET_ID_ANY, 0); + if (NULL != rp) + return -1; + + return 0; +} + +/* + * Test to if a non-power of 2 count causes the create + * function to fail correctly + */ +static int +test_create_count_odd(void) +{ + struct rte_ring *r = rte_ring_create_elem("test_ring_count", + 4097, 8, SOCKET_ID_ANY, 0 ); + if(r != NULL){ + return -1; + } + return 0; +} + +/* + * it tests some more basic ring operations + */ +static int +test_ring_basic_ex(void) +{ + int ret = -1; + unsigned i; + struct rte_ring *rp = NULL; + void **obj = NULL; + + obj = rte_calloc("test_ring_basic_ex_malloc", RING_SIZE, sizeof(void *), 0); + if (obj == NULL) { + printf("test_ring_basic_ex fail to rte_malloc\n"); + goto fail_test; + } + + rp = rte_ring_create_elem("test_ring_basic_ex", RING_SIZE, 8, SOCKET_ID_ANY, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (rp == NULL) { + printf("test_ring_basic_ex fail to create ring\n"); + goto fail_test; + } + + if (rte_ring_lookup("test_ring_basic_ex") != rp) { + goto fail_test; + } + + if (rte_ring_empty(rp) != 1) { + printf("test_ring_basic_ex ring is not empty but it should be\n"); + goto fail_test; + } + + printf("%u ring entries are now free\n", rte_ring_free_count(rp)); + + for (i = 0; i < RING_SIZE; i ++) { + rte_ring_enqueue_elem(rp, &obj[i], 8); + } + + if (rte_ring_full(rp) != 1) { + printf("test_ring_basic_ex ring is not full but it should be\n"); + goto fail_test; + } + + for (i = 0; i < RING_SIZE; i ++) { + rte_ring_dequeue_elem(rp, &obj[i], 8); + } + + if (rte_ring_empty(rp) != 1) { + printf("test_ring_basic_ex ring is not empty but it should be\n"); + goto fail_test; + } + + /* Covering the ring burst operation */ + ret = rte_ring_enqueue_burst_elem(rp, obj, 8, 2, NULL); + if (ret != 2) { + printf("test_ring_basic_ex: rte_ring_enqueue_burst fails \n"); + goto fail_test; + } + + ret = rte_ring_dequeue_burst_elem(rp, obj, 8, 2, NULL); + if (ret != 2) { + printf("test_ring_basic_ex: rte_ring_dequeue_burst fails \n"); + goto fail_test; + } + + ret = 0; +fail_test: + rte_ring_free(rp); + if (obj != NULL) + rte_free(obj); + + return ret; +} + +static int +test_ring_with_exact_size(void) +{ + struct rte_ring *std_ring = NULL, *exact_sz_ring = NULL; + void *ptr_array[16]; + static const unsigned int ring_sz = RTE_DIM(ptr_array); + unsigned int i; + int ret = -1; + + std_ring = rte_ring_create_elem("std", ring_sz, 8, rte_socket_id(), + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (std_ring == NULL) { + printf("%s: error, can't create std ring\n", __func__); + goto end; + } + exact_sz_ring = rte_ring_create_elem("exact sz", ring_sz, 8, rte_socket_id(), + RING_F_SP_ENQ | RING_F_SC_DEQ | RING_F_EXACT_SZ); + if (exact_sz_ring == NULL) { + printf("%s: error, can't create exact size ring\n", __func__); + goto end; + } + + /* + * Check that the exact size ring is bigger than the standard ring + */ + if (rte_ring_get_size(std_ring) >= rte_ring_get_size(exact_sz_ring)) { + printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n", + __func__, + rte_ring_get_size(std_ring), + rte_ring_get_size(exact_sz_ring)); + goto end; + } + /* + * check that the exact_sz_ring can hold one more element than the + * standard ring. (16 vs 15 elements) + */ + for (i = 0; i < ring_sz - 1; i++) { + rte_ring_enqueue_elem(std_ring, ptr_array, 8); + rte_ring_enqueue_elem(exact_sz_ring, ptr_array, 8); + } + if (rte_ring_enqueue_elem(std_ring, ptr_array, 8) != -ENOBUFS) { + printf("%s: error, unexpected successful enqueue\n", __func__); + goto end; + } + if (rte_ring_enqueue_elem(exact_sz_ring, ptr_array, 8) == -ENOBUFS) { + printf("%s: error, enqueue failed\n", __func__); + goto end; + } + + /* check that dequeue returns the expected number of elements */ + if (rte_ring_dequeue_burst_elem(exact_sz_ring, ptr_array, 8, + RTE_DIM(ptr_array), NULL) != ring_sz) { + printf("%s: error, failed to dequeue expected nb of elements\n", + __func__); + goto end; + } + + /* check that the capacity function returns expected value */ + if (rte_ring_get_capacity(exact_sz_ring) != ring_sz) { + printf("%s: error, incorrect ring capacity reported\n", + __func__); + goto end; + } + + ret = 0; /* all ok if we get here */ +end: + rte_ring_free(std_ring); + rte_ring_free(exact_sz_ring); + return ret; +} + +static int +test_ring(void) +{ + struct rte_ring *r = NULL; + + /* some more basic operations */ + if (test_ring_basic_ex() < 0) + goto test_fail; + + rte_atomic32_init(&synchro); + + r = rte_ring_create_elem("test", RING_SIZE, 8, SOCKET_ID_ANY, 0); + if (r == NULL) + goto test_fail; + + /* retrieve the ring from its name */ + if (rte_ring_lookup("test") != r) { + printf("Cannot lookup ring from its name\n"); + goto test_fail; + } + + /* burst operations */ + if (test_ring_burst_basic(r) < 0) + goto test_fail; + + /* basic operations */ + if (test_ring_basic(r) < 0) + goto test_fail; + + /* basic operations */ + if ( test_create_count_odd() < 0){ + printf("Test failed to detect odd count\n"); + goto test_fail; + } else + printf("Test detected odd count\n"); + + /* test of creating ring with wrong size */ + if (test_ring_creation_with_wrong_size() < 0) + goto test_fail; + + /* test of creation ring with an used name */ + if (test_ring_creation_with_an_used_name() < 0) + goto test_fail; + + if (test_ring_with_exact_size() < 0) + goto test_fail; + + /* dump the ring status */ + rte_ring_list_dump(stdout); + + rte_ring_free(r); + + return 0; + +test_fail: + rte_ring_free(r); + + return -1; +} + +REGISTER_TEST_COMMAND(ring_elem_autotest, test_ring); -- 2.17.1