From: Aditya Ambadipudi <aditya.ambadipudi@arm.com>
To: dev@dpdk.org, jackmin@nvidia.com, stephen@networkplumber.org,
matan@nvidia.com, viacheslavo@nvidia.com,
roretzla@linux.microsoft.com, konstantin.ananyev@huawei.com,
mb@smartsharesystems.com, hofors@lysator.liu.se
Cc: wathsala.vithanage@arm.com, dhruv.tripathi@arm.com,
honnappa.nagarahalli@arm.com, nd@arm.com,
Aditya Ambadipudi <aditya.ambadipudi@arm.com>
Subject: [PATCH v2 2/2] deque: add unit tests for the deque library
Date: Wed, 24 Apr 2024 08:42:33 -0500 [thread overview]
Message-ID: <20240424134233.1336370-3-aditya.ambadipudi@arm.com> (raw)
In-Reply-To: <20240424134233.1336370-1-aditya.ambadipudi@arm.com>
Add unit test cases that test all of the enqueue/dequeue functions.
Both normal enqueue/dequeue functions and the zerocopy API functions.
Signed-off-by: Aditya Ambadipudi <aditya.ambadipudi@arm.com>
Change-Id: Ida5bdefdd9d001b792a8d4be011387ff4f84c154
---
v2:
* Addressed the spell check warning issue with the word "Deque"
* Tried to rename all objects that are named deque to avoid collision with
std::deque
app/test/meson.build | 2 +
app/test/test_deque_enqueue_dequeue.c | 1228 ++++++++++++++++++++++++
app/test/test_deque_helper_functions.c | 169 ++++
3 files changed, 1399 insertions(+)
create mode 100644 app/test/test_deque_enqueue_dequeue.c
create mode 100644 app/test/test_deque_helper_functions.c
diff --git a/app/test/meson.build b/app/test/meson.build
index 7d909039ae..8913050c9b 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -60,6 +60,8 @@ source_file_deps = {
'test_cryptodev_security_tls_record.c': ['cryptodev', 'security'],
'test_cycles.c': [],
'test_debug.c': [],
+ 'test_deque_enqueue_dequeue.c': ['deque'],
+ 'test_deque_helper_functions.c': ['deque'],
'test_devargs.c': ['kvargs'],
'test_dispatcher.c': ['dispatcher'],
'test_distributor.c': ['distributor'],
diff --git a/app/test/test_deque_enqueue_dequeue.c b/app/test/test_deque_enqueue_dequeue.c
new file mode 100644
index 0000000000..5816218235
--- /dev/null
+++ b/app/test/test_deque_enqueue_dequeue.c
@@ -0,0 +1,1228 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Arm Limited
+ */
+
+
+#include "test.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_deque.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+
+static const int esize[] = {4, 8, 16, 20};
+#define DEQUE_SIZE 4096
+#define MAX_BULK 32
+#define TEST_DEQUE_FULL_EMPTY_ITER 8
+
+/*
+ * Validate the return value of test cases and print details of the
+ * deque if validation fails
+ *
+ * @param exp
+ * Expression to validate return value.
+ * @param r
+ * A pointer to the deque structure.
+ */
+#define TEST_DEQUE_VERIFY(exp, d, errst) do { \
+ if (!(exp)) { \
+ printf("error at %s:%d\tcondition " #exp " failed\n", \
+ __func__, __LINE__); \
+ rte_deque_dump(stdout, (d)); \
+ errst; \
+ } \
+} while (0)
+
+static int
+test_deque_mem_cmp(void *src, void *dst, unsigned int size)
+{
+ int ret;
+
+ ret = memcmp(src, dst, size);
+ if (ret) {
+ rte_hexdump(stdout, "src", src, size);
+ rte_hexdump(stdout, "dst", dst, size);
+ printf("data after dequeue is not the same\n");
+ }
+
+ return ret;
+}
+
+static int
+test_deque_mem_cmp_rvs(void *src, void *dst,
+ unsigned int count, unsigned int esize)
+{
+ int ret = 0;
+ uint32_t *src32 = ((uint32_t *)src), *dst32 = ((uint32_t *)dst);
+ uint32_t scale = esize/(sizeof(uint32_t));
+
+ /* Start at the end of the dst and compare from there.*/
+ dst32 += (count - 1) * scale;
+ for (unsigned int i = 0; i < count; i++) {
+ for (unsigned int j = 0; j < scale; j++) {
+ if (src32[j] != dst32[j]) {
+ ret = -1;
+ break;
+ }
+ }
+ if (ret)
+ break;
+ dst32 -= scale;
+ src32 += scale;
+ }
+ if (ret) {
+ rte_hexdump(stdout, "src", src, count * esize);
+ rte_hexdump(stdout, "dst", dst, count * esize);
+ printf("data after dequeue is not the same\n");
+ }
+
+ return ret;
+}
+
+static inline void *
+test_deque_calloc(unsigned int dsize, int esize)
+{
+ void *p;
+
+ p = rte_zmalloc(NULL, dsize * esize, RTE_CACHE_LINE_SIZE);
+ if (p == NULL)
+ printf("Failed to allocate memory\n");
+
+ return p;
+}
+
+static void
+test_deque_mem_init(void *obj, unsigned int count, int esize)
+{
+ for (unsigned int i = 0; i < (count * esize / sizeof(uint32_t)); i++)
+ ((uint32_t *)obj)[i] = i;
+}
+
+static inline void *
+test_deque_inc_ptr(void *obj, int esize, unsigned int n)
+{
+ return (void *)((uint32_t *)obj + (n * esize / sizeof(uint32_t)));
+}
+
+/* Copy to the deque memory */
+static inline void
+test_deque_zc_copy_to_deque(struct rte_deque_zc_data *zcd, const void *src, int esize,
+ unsigned int num)
+{
+ memcpy(zcd->ptr1, src, esize * zcd->n1);
+ if (zcd->n1 != num) {
+ const void *inc_src = (const void *)((const char *)src +
+ (zcd->n1 * esize));
+ memcpy(zcd->ptr2, inc_src, esize * (num - zcd->n1));
+ }
+}
+
+static inline void
+test_deque_zc_copy_to_deque_rev(struct rte_deque_zc_data *zcd, const void *src,
+ int esize, unsigned int num)
+{
+ void *ptr1 = zcd->ptr1;
+ for (unsigned int i = 0; i < zcd->n1; i++) {
+ memcpy(ptr1, src, esize);
+ src = (const void *)((const char *)src + esize);
+ ptr1 = (void *)((char *)ptr1 - esize);
+ }
+ if (zcd->n1 != num) {
+ void *ptr2 = zcd->ptr2;
+ for (unsigned int i = 0; i < (num - zcd->n1); i++) {
+ memcpy(ptr2, src, esize);
+ src = (const void *)((const char *)src + esize);
+ ptr2 = (void *)((char *)ptr2 - esize);
+ }
+ }
+}
+
+/* Copy from the deque memory */
+static inline void
+test_deque_zc_copy_from_deque(struct rte_deque_zc_data *zcd, void *dst, int esize,
+ unsigned int num)
+{
+ memcpy(dst, zcd->ptr1, esize * zcd->n1);
+
+ if (zcd->n1 != num) {
+ dst = test_deque_inc_ptr(dst, esize, zcd->n1);
+ memcpy(dst, zcd->ptr2, esize * (num - zcd->n1));
+ }
+}
+
+static inline void
+test_deque_zc_copy_from_deque_rev(struct rte_deque_zc_data *zcd, void *dst, int esize,
+ unsigned int num)
+{
+ void *ptr1 = zcd->ptr1;
+ for (unsigned int i = 0; i < zcd->n1; i++) {
+ memcpy(dst, ptr1, esize);
+ dst = (void *)((char *)dst + esize);
+ ptr1 = (void *)((char *)ptr1 - esize);
+ }
+ if (zcd->n1 != num) {
+ void *ptr2 = zcd->ptr2;
+ for (unsigned int i = 0; i < (num - zcd->n1); i++) {
+ memcpy(dst, ptr2, esize);
+ dst = (void *)((char *)dst + esize);
+ ptr2 = (void *)((char *)ptr2 - esize);
+ }
+ }
+}
+
+/* Wrappers around the zero-copy APIs. The wrappers match
+ * the normal enqueue/dequeue API declarations.
+ */
+static unsigned int
+test_deque_head_enqueue_zc_bulk_elem(struct rte_deque *d, const void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *free_space)
+{
+ uint32_t ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_head_enqueue_zc_bulk_elem_start(d, esize, n,
+ &zcd, free_space);
+ if (ret != 0) {
+ /* Copy the data to the deque */
+ test_deque_zc_copy_to_deque(&zcd, obj_table, esize, ret);
+ rte_deque_head_enqueue_zc_elem_finish(d, ret);
+ }
+
+ return ret;
+}
+
+static unsigned int
+test_deque_tail_dequeue_zc_bulk_elem(struct rte_deque *d, void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *available)
+{
+ unsigned int ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_tail_dequeue_zc_bulk_elem_start(d, esize, n,
+ &zcd, available);
+ if (ret != 0) {
+ /* Copy the data from the deque */
+ test_deque_zc_copy_from_deque(&zcd, obj_table, esize, ret);
+ rte_deque_tail_dequeue_zc_elem_finish(d, ret);
+ }
+
+ return ret;
+}
+
+static unsigned int
+test_deque_head_enqueue_zc_burst_elem(struct rte_deque *d, const void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *free_space)
+{
+ uint32_t ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_head_enqueue_zc_burst_elem_start(d, esize, n,
+ &zcd, free_space);
+ if (ret != 0) {
+ /* Copy the data to the deque */
+ test_deque_zc_copy_to_deque(&zcd, obj_table, esize, ret);
+ rte_deque_head_enqueue_zc_elem_finish(d, ret);
+ }
+
+ return ret;
+}
+
+static unsigned int
+test_deque_tail_dequeue_zc_burst_elem(struct rte_deque *d, void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *available)
+{
+ unsigned int ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_tail_dequeue_zc_burst_elem_start(d, esize, n,
+ &zcd, available);
+ if (ret != 0) {
+ /* Copy the data from the deque */
+ test_deque_zc_copy_from_deque(&zcd, obj_table, esize, ret);
+ rte_deque_tail_dequeue_zc_elem_finish(d, ret);
+ }
+ return ret;
+}
+
+static unsigned int
+test_deque_tail_enqueue_zc_bulk_elem(struct rte_deque *d, const void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *free_space)
+{
+ uint32_t ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_tail_enqueue_zc_bulk_elem_start(d, esize, n,
+ &zcd, free_space);
+ if (ret != 0) {
+ /* Copy the data to the deque */
+ test_deque_zc_copy_to_deque_rev(&zcd, obj_table, esize, ret);
+ rte_deque_tail_enqueue_zc_elem_finish(d, ret);
+ }
+
+ return ret;
+}
+
+static unsigned int
+test_deque_head_dequeue_zc_bulk_elem(struct rte_deque *d, void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *available)
+{
+ unsigned int ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_head_dequeue_zc_bulk_elem_start(d, esize, n,
+ &zcd, available);
+ if (ret != 0) {
+ /* Copy the data from the deque */
+ test_deque_zc_copy_from_deque_rev(&zcd, obj_table, esize, ret);
+ rte_deque_head_dequeue_zc_elem_finish(d, ret);
+ }
+ return ret;
+}
+
+static unsigned int
+test_deque_tail_enqueue_zc_burst_elem(struct rte_deque *d,
+ const void *obj_table, unsigned int esize, unsigned int n,
+ unsigned int *free_space)
+{
+ uint32_t ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_tail_enqueue_zc_burst_elem_start(d, esize, n,
+ &zcd, free_space);
+ if (ret != 0) {
+ /* Copy the data to the deque */
+ test_deque_zc_copy_to_deque_rev(&zcd, obj_table, esize, ret);
+ rte_deque_tail_enqueue_zc_elem_finish(d, ret);
+ }
+
+ return ret;
+}
+
+static unsigned int
+test_deque_head_dequeue_zc_burst_elem(struct rte_deque *d, void *obj_table,
+ unsigned int esize, unsigned int n, unsigned int *available)
+{
+ unsigned int ret;
+ struct rte_deque_zc_data zcd;
+
+ ret = rte_deque_head_dequeue_zc_burst_elem_start(d, esize, n,
+ &zcd, available);
+ if (ret != 0) {
+ /* Copy the data from the deque */
+ test_deque_zc_copy_from_deque_rev(&zcd, obj_table, esize, ret);
+ rte_deque_head_dequeue_zc_elem_finish(d, ret);
+ }
+ return ret;
+}
+
+#define TEST_DEQUE_ELEM_BULK 8
+#define TEST_DEQUE_ELEM_BURST 16
+static const struct {
+ const char *desc;
+ const int api_flags;
+ unsigned int (*enq)(struct rte_deque *d, const void *obj_table,
+ unsigned int esize, unsigned int n,
+ unsigned int *free_space);
+ unsigned int (*deq)(struct rte_deque *d, void *obj_table,
+ unsigned int esize, unsigned int n,
+ unsigned int *available);
+ /* This dequeues in the opposite direction of enqueue.
+ * This is used for testing stack behavior
+ */
+ unsigned int (*deq_opp)(struct rte_deque *d, void *obj_table,
+ unsigned int esize, unsigned int n,
+ unsigned int *available);
+} test_enqdeq_impl[] = {
+ {
+ .desc = "Deque forward direction bulkmode",
+ .api_flags = TEST_DEQUE_ELEM_BULK,
+ .enq = rte_deque_head_enqueue_bulk_elem,
+ .deq = rte_deque_tail_dequeue_bulk_elem,
+ .deq_opp = rte_deque_head_dequeue_bulk_elem,
+ },
+ {
+ .desc = "Deque forward direction burstmode",
+ .api_flags = TEST_DEQUE_ELEM_BURST,
+ .enq = rte_deque_head_enqueue_burst_elem,
+ .deq = rte_deque_tail_dequeue_burst_elem,
+ .deq_opp = rte_deque_head_dequeue_burst_elem,
+ },
+ {
+ .desc = "Deque reverse direction bulkmode",
+ .api_flags = TEST_DEQUE_ELEM_BULK,
+ .enq = rte_deque_tail_enqueue_bulk_elem,
+ .deq = rte_deque_head_dequeue_bulk_elem,
+ .deq_opp = rte_deque_tail_dequeue_bulk_elem,
+ },
+ {
+ .desc = "Deque reverse direction burstmode",
+ .api_flags = TEST_DEQUE_ELEM_BURST,
+ .enq = rte_deque_tail_enqueue_burst_elem,
+ .deq = rte_deque_head_dequeue_burst_elem,
+ .deq_opp = rte_deque_tail_dequeue_burst_elem,
+ },
+ {
+ .desc = "Deque forward direction bulkmode zero copy",
+ .api_flags = TEST_DEQUE_ELEM_BULK,
+ .enq = test_deque_head_enqueue_zc_bulk_elem,
+ .deq = test_deque_tail_dequeue_zc_bulk_elem,
+ .deq_opp = test_deque_head_dequeue_zc_bulk_elem,
+ },
+ {
+ .desc = "Deque forward direction burstmode zero copy",
+ .api_flags = TEST_DEQUE_ELEM_BURST,
+ .enq = test_deque_head_enqueue_zc_burst_elem,
+ .deq = test_deque_tail_dequeue_zc_burst_elem,
+ .deq_opp = test_deque_head_dequeue_zc_burst_elem,
+ },
+ {
+ .desc = "Deque reverse direction bulkmode zero copy",
+ .api_flags = TEST_DEQUE_ELEM_BULK,
+ .enq = test_deque_tail_enqueue_zc_bulk_elem,
+ .deq = test_deque_head_dequeue_zc_bulk_elem,
+ .deq_opp = test_deque_tail_dequeue_zc_bulk_elem,
+ },
+ {
+ .desc = "Deque reverse direction burstmode zero copy",
+ .api_flags = TEST_DEQUE_ELEM_BURST,
+ .enq = test_deque_tail_enqueue_zc_burst_elem,
+ .deq = test_deque_head_dequeue_zc_burst_elem,
+ .deq_opp = test_deque_tail_dequeue_zc_burst_elem,
+ },
+};
+
+/*
+ * Burst and bulk operations in regular mode and zero copy mode.
+ * Random number of elements are enqueued and dequeued.
+ */
+static int
+test_deque_burst_bulk_tests1(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ unsigned int ret;
+ unsigned int i, j, temp_sz, free_space, available;
+ const unsigned int dsz = DEQUE_SIZE - 1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Over the boundary deque.";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("Random full/empty test\n");
+
+ for (j = 0; j != TEST_DEQUE_FULL_EMPTY_ITER; j++) {
+ /* random shift in the deque */
+ int rand = RTE_MAX(rte_rand() % DEQUE_SIZE, 1UL);
+ printf("%s: iteration %u, random shift: %u;\n",
+ __func__, i, rand);
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ rand, &free_space);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)rand, d, goto fail);
+
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ rand, &available);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)rand, d, goto fail);
+
+ /* fill the deque */
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src,
+ esize[i], dsz,
+ &free_space);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)dsz, d, goto fail);
+
+ TEST_DEQUE_VERIFY(rte_deque_free_count(d) == 0, d,
+ goto fail);
+ TEST_DEQUE_VERIFY(dsz == rte_deque_count(d), d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_full(d), d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_empty(d) == 0, d, goto fail);
+
+ /* empty the deque */
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst,
+ esize[i], dsz,
+ &available);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)dsz, d, goto fail);
+
+ TEST_DEQUE_VERIFY(dsz == rte_deque_free_count(d), d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_count(d) == 0, d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_full(d) == 0, d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_empty(d), d, goto fail);
+
+ /* check data */
+ temp_sz = dsz * esize[i];
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp(src, dst, temp_sz) == 0,
+ d, goto fail);
+ }
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with regular & zero copy mode.
+ * Sequence of simple enqueues/dequeues and validate the enqueued and
+ * dequeued data.
+ */
+static int
+test_deque_burst_bulk_tests2(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ int ret;
+ unsigned int i, free_space, available;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Multiple enqs, deqs.";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("enqueue 1 obj\n");
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ 1, &free_space);
+ TEST_DEQUE_VERIFY(ret == 1, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], 1);
+
+ printf("enqueue 2 objs\n");
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ 2, &free_space);
+ TEST_DEQUE_VERIFY(ret == 2, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], 2);
+
+ printf("enqueue MAX_BULK objs\n");
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ MAX_BULK, &free_space);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+
+ printf("dequeue 1 obj\n");
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ 1, &available);
+ TEST_DEQUE_VERIFY(ret == 1, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], 1);
+
+ printf("dequeue 2 objs\n");
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ 2, &available);
+ TEST_DEQUE_VERIFY(ret == 2, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], 2);
+
+ printf("dequeue MAX_BULK objs\n");
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ MAX_BULK, &available);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], MAX_BULK);
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp(src, dst,
+ RTE_PTR_DIFF(cur_dst, dst)) == 0,
+ d, goto fail);
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with normal mode & zero copy mode.
+ * Enqueue and dequeue to cover the entire deque length.
+ */
+static int
+test_deque_burst_bulk_tests3(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ int ret;
+ unsigned int i, j, free_space, available;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Full deque length test";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("fill and empty the deque\n");
+ for (j = 0; j < DEQUE_SIZE / MAX_BULK; j++) {
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src,
+ esize[i], MAX_BULK,
+ &free_space);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i],
+ MAX_BULK);
+
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst,
+ esize[i], MAX_BULK,
+ &available);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i],
+ MAX_BULK);
+ }
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp(src, dst,
+ RTE_PTR_DIFF(cur_dst, dst)) == 0,
+ d, goto fail);
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with normal mode & zero copy mode.
+ * Enqueue till the deque is full and dequeue till the deque becomes empty.
+ */
+static int
+test_deque_burst_bulk_tests4(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ int ret;
+ unsigned int i, j, available, free_space;
+ unsigned int num_elems, api_type;
+ api_type = test_enqdeq_impl[test_idx].api_flags;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Full deque length test";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("Test enqueue without enough memory space\n");
+ for (j = 0; j < (DEQUE_SIZE/MAX_BULK - 1); j++) {
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src,
+ esize[i], MAX_BULK,
+ &free_space);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i],
+ MAX_BULK);
+ }
+
+ printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ 2, &free_space);
+ TEST_DEQUE_VERIFY(ret == 2, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], 2);
+
+ printf("Enqueue the remaining entries = MAX_BULK - 3\n");
+ /* Bulk APIs enqueue exact number of elements */
+ if ((api_type & TEST_DEQUE_ELEM_BULK))
+ num_elems = MAX_BULK - 3;
+ else
+ num_elems = MAX_BULK;
+ /* Always one free entry left */
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ num_elems, &free_space);
+ TEST_DEQUE_VERIFY(ret == (MAX_BULK - 3), d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i],
+ (MAX_BULK - 3));
+
+ printf("Test if deque is full\n");
+ TEST_DEQUE_VERIFY(rte_deque_full(d) == 1, d, goto fail);
+
+ printf("Test enqueue for a full entry\n");
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ 1, &free_space);
+ TEST_DEQUE_VERIFY(ret == 0, d, goto fail);
+
+ printf("Test dequeue without enough objects\n");
+ for (j = 0; j < DEQUE_SIZE / MAX_BULK - 1; j++) {
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ MAX_BULK, &available);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i],
+ MAX_BULK);
+ }
+
+ /* Available memory space for the exact MAX_BULK entries */
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ 2, &available);
+ TEST_DEQUE_VERIFY(ret == 2, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], 2);
+
+ /* Bulk APIs enqueue exact number of elements */
+ if ((api_type & TEST_DEQUE_ELEM_BULK))
+ num_elems = MAX_BULK - 3;
+ else
+ num_elems = MAX_BULK;
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst, esize[i],
+ num_elems, &available);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK - 3, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
+
+ printf("Test if deque is empty\n");
+ /* Check if deque is empty */
+ TEST_DEQUE_VERIFY(rte_deque_empty(d) == 1, d, goto fail);
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp(src, dst,
+ RTE_PTR_DIFF(cur_dst, dst)) == 0,
+ d, goto fail);
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Basic test cases with exact size deque.
+ */
+static int
+test_deque_with_exact_size(void)
+{
+ struct rte_deque *std_d = NULL, *exact_sz_d = NULL;
+ void *src_orig = NULL, *dst_orig = NULL;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ const unsigned int deque_sz = 16;
+ unsigned int i, j, free_space, available;
+ int ret = -1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("\nTest exact size deque. Esize: %d\n", esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "std sized deque";
+ std_d = rte_deque_create(DEQUE_NAME, esize[i], deque_sz, 0, 0);
+
+ if (std_d == NULL) {
+ printf("%s: error, can't create std deque\n", __func__);
+ goto test_fail;
+ }
+ static const char *DEQUE_NAME2 = "Exact sized deque";
+ exact_sz_d = rte_deque_create(DEQUE_NAME2, esize[i], deque_sz,
+ 0, RTE_DEQUE_F_EXACT_SZ);
+ if (exact_sz_d == NULL) {
+ printf("%s: error, can't create exact size deque\n",
+ __func__);
+ goto test_fail;
+ }
+
+ /* alloc object pointers. Allocate one extra object
+ * and create an unaligned address.
+ */
+ src_orig = test_deque_calloc(17, esize[i]);
+ if (src_orig == NULL)
+ goto test_fail;
+ test_deque_mem_init(src_orig, 17, esize[i]);
+ src = (void *)((uintptr_t)src_orig + 1);
+ cur_src = src;
+
+ dst_orig = test_deque_calloc(17, esize[i]);
+ if (dst_orig == NULL)
+ goto test_fail;
+ dst = (void *)((uintptr_t)dst_orig + 1);
+ cur_dst = dst;
+
+ /*
+ * Check that the exact size deque is bigger than the
+ * standard deque
+ */
+ TEST_DEQUE_VERIFY(rte_deque_get_size(std_d) <=
+ rte_deque_get_size(exact_sz_d),
+ std_d, goto test_fail);
+
+ /*
+ * check that the exact_sz_deque can hold one more element
+ * than the standard deque. (16 vs 15 elements)
+ */
+ for (j = 0; j < deque_sz - 1; j++) {
+ ret = test_enqdeq_impl[0].enq(std_d, cur_src, esize[i],
+ 1, &free_space);
+ TEST_DEQUE_VERIFY(ret == 1, std_d, goto test_fail);
+ ret = test_enqdeq_impl[0].enq(exact_sz_d, cur_src,
+ esize[i], 1, &free_space);
+ TEST_DEQUE_VERIFY(ret == 1, exact_sz_d, goto test_fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], 1);
+ }
+ ret = test_enqdeq_impl[0].enq(std_d, cur_src, esize[i], 1,
+ &free_space);
+ TEST_DEQUE_VERIFY(ret == 0, std_d, goto test_fail);
+ ret = test_enqdeq_impl[0].enq(exact_sz_d, cur_src, esize[i], 1,
+ &free_space);
+ TEST_DEQUE_VERIFY(ret == 1, exact_sz_d, goto test_fail);
+
+ /* check that dequeue returns the expected number of elements */
+ ret = test_enqdeq_impl[0].deq(exact_sz_d, cur_dst, esize[i],
+ deque_sz, &available);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)deque_sz, exact_sz_d,
+ goto test_fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], deque_sz);
+
+ /* check that the capacity function returns expected value */
+ TEST_DEQUE_VERIFY(rte_deque_get_capacity(exact_sz_d) == deque_sz,
+ exact_sz_d, goto test_fail);
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp(src, dst,
+ RTE_PTR_DIFF(cur_dst, dst)) == 0,
+ exact_sz_d, goto test_fail);
+
+ rte_free(src_orig);
+ rte_free(dst_orig);
+ rte_deque_free(std_d);
+ rte_deque_free(exact_sz_d);
+ src_orig = NULL;
+ dst_orig = NULL;
+ std_d = NULL;
+ exact_sz_d = NULL;
+ }
+
+ return 0;
+
+test_fail:
+ rte_free(src_orig);
+ rte_free(dst_orig);
+ rte_deque_free(std_d);
+ rte_deque_free(exact_sz_d);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations in regular mode and zero copy mode.
+ * Random number of elements are enqueued and dequeued first.
+ * Which would bring both head and tail to somewhere in the middle of
+ * the deque. From that point, stack behavior of the deque is tested.
+ */
+static int
+test_deque_stack_random_tests1(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ unsigned int ret;
+ unsigned int i, j, free_space, available;
+ const unsigned int dsz = DEQUE_SIZE - 1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("Stackmode tests1.\n");
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Over the boundary deque.";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("Random starting point stack test\n");
+
+ for (j = 0; j != TEST_DEQUE_FULL_EMPTY_ITER; j++) {
+ /* random shift in the deque */
+ int rand = RTE_MAX(rte_rand() % DEQUE_SIZE, 1UL);
+ printf("%s: iteration %u, random shift: %u;\n",
+ __func__, i, rand);
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src,
+ esize[i], rand,
+ &free_space);
+ TEST_DEQUE_VERIFY(ret != 0, d, goto fail);
+
+ ret = test_enqdeq_impl[test_idx].deq(d, cur_dst,
+ esize[i], rand,
+ &available);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)rand, d,
+ goto fail);
+
+ /* fill the deque */
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ dsz, &free_space);
+ TEST_DEQUE_VERIFY(ret != 0, d, goto fail);
+
+ TEST_DEQUE_VERIFY(rte_deque_free_count(d) == 0, d,
+ goto fail);
+ TEST_DEQUE_VERIFY(dsz == rte_deque_count(d), d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_full(d), d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_empty(d) == 0, d,
+ goto fail);
+
+ /* empty the deque */
+ ret = test_enqdeq_impl[test_idx].deq_opp(d, cur_dst,
+ esize[i], dsz,
+ &available);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)dsz, d, goto fail);
+
+ TEST_DEQUE_VERIFY(dsz == rte_deque_free_count(d), d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_count(d) == 0, d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_full(d) == 0, d,
+ goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_empty(d), d, goto fail);
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp_rvs(src, dst,
+ dsz, esize[i]) == 0, d, goto fail);
+ }
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/* Tests both standard mode and zero-copy mode.
+ * Keep enqueuing 1, 2, MAX_BULK elements till the deque is full.
+ * Then deque them all and make sure the data is opposite of what
+ * was enqued.
+ */
+static int
+test_deque_stack_random_tests2(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ unsigned int ret;
+ unsigned int i, free_space, available;
+ const unsigned int dsz = DEQUE_SIZE - 1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("Stackmode tests2.\n");
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Multiple enqs, deqs.";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+
+ printf("Enqueue objs till the deque is full.\n");
+ unsigned int count = 0;
+ const unsigned int perIterCount = 1 + 2 + MAX_BULK;
+ while (count + perIterCount < DEQUE_SIZE - 1) {
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ 1, &free_space);
+ TEST_DEQUE_VERIFY(ret == 1, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], 1);
+
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ 2, &free_space);
+ TEST_DEQUE_VERIFY(ret == 2, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], 2);
+
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ MAX_BULK, &free_space);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], MAX_BULK);
+ count += perIterCount;
+ }
+ unsigned int leftOver = DEQUE_SIZE - 1 - count;
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ leftOver, &free_space);
+ TEST_DEQUE_VERIFY(ret == leftOver, d, goto fail);
+ cur_src = test_deque_inc_ptr(cur_src, esize[i], leftOver);
+
+ printf("Deque all the enqued objs.\n");
+ count = 0;
+ while (count + perIterCount < DEQUE_SIZE - 1) {
+ ret = test_enqdeq_impl[test_idx].deq_opp(d, cur_dst,
+ esize[i], 1, &available);
+ TEST_DEQUE_VERIFY(ret == 1, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], 1);
+
+ ret = test_enqdeq_impl[test_idx].deq_opp(d, cur_dst,
+ esize[i], 2,
+ &available);
+ TEST_DEQUE_VERIFY(ret == 2, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], 2);
+
+ ret = test_enqdeq_impl[test_idx].deq_opp(d, cur_dst,
+ esize[i],
+ MAX_BULK,
+ &available);
+ TEST_DEQUE_VERIFY(ret == MAX_BULK, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], MAX_BULK);
+ count += perIterCount;
+ }
+ leftOver = DEQUE_SIZE - 1 - count;
+ ret = test_enqdeq_impl[test_idx].deq_opp(d, cur_dst, esize[i],
+ leftOver, &available);
+ TEST_DEQUE_VERIFY(ret == leftOver, d, goto fail);
+ cur_dst = test_deque_inc_ptr(cur_dst, esize[i], leftOver);
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp_rvs(src, dst,
+ dsz, esize[i]) == 0, d,
+ goto fail);
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Tests both normal mode and zero-copy mode.
+ * Fill up the whole deque, and drain the deque.
+ * Make sure the data matches in reverse order.
+ */
+static int
+test_deque_stack_random_tests3(unsigned int test_idx)
+{
+ struct rte_deque *d;
+ void *src = NULL, *cur_src = NULL, *dst = NULL, *cur_dst = NULL;
+ int ret;
+ unsigned int i, available, free_space;
+ const unsigned int dsz = DEQUE_SIZE - 1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ printf("Stackmode tests3.\n");
+ printf("\n%s, esize: %d\n", test_enqdeq_impl[test_idx].desc,
+ esize[i]);
+
+ /* Create the deque */
+ static const char *DEQUE_NAME = "Full deque length test";
+ d = rte_deque_create(DEQUE_NAME, esize[i], DEQUE_SIZE, 0, 0);
+
+ /* alloc dummy object pointers */
+ src = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_deque_mem_init(src, DEQUE_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_deque_calloc(DEQUE_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ /* fill the deque */
+ printf("Fill the whole deque using 1 "
+ "single enqueue operation.\n");
+ ret = test_enqdeq_impl[test_idx].enq(d, cur_src, esize[i],
+ dsz, &free_space);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)dsz, d, goto fail);
+
+ TEST_DEQUE_VERIFY(rte_deque_free_count(d) == 0, d, goto fail);
+ TEST_DEQUE_VERIFY(dsz == rte_deque_count(d), d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_full(d), d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_empty(d) == 0, d, goto fail);
+
+ /* empty the deque */
+ printf("Empty the whole deque.\n");
+ ret = test_enqdeq_impl[test_idx].deq_opp(d, cur_dst, esize[i],
+ dsz, &available);
+ TEST_DEQUE_VERIFY(ret == (unsigned int)dsz, d, goto fail);
+
+ TEST_DEQUE_VERIFY(dsz == rte_deque_free_count(d), d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_count(d) == 0, d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_full(d) == 0, d, goto fail);
+ TEST_DEQUE_VERIFY(rte_deque_empty(d), d, goto fail);
+
+ /* check data */
+ TEST_DEQUE_VERIFY(test_deque_mem_cmp_rvs(src, dst,
+ dsz, esize[i]) == 0, d, goto fail);
+
+ /* Free memory before test completed */
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ d = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_deque_free(d);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+static int
+deque_enqueue_dequeue_autotest_fn(void)
+{
+ if (test_deque_with_exact_size() != 0)
+ goto fail;
+ int (*test_fns[])(unsigned int test_fn_idx) = {
+ test_deque_burst_bulk_tests1,
+ test_deque_burst_bulk_tests2,
+ test_deque_burst_bulk_tests3,
+ test_deque_burst_bulk_tests4,
+ test_deque_stack_random_tests1,
+ test_deque_stack_random_tests2,
+ test_deque_stack_random_tests3
+ };
+ for (unsigned int test_impl_idx = 0;
+ test_impl_idx < RTE_DIM(test_enqdeq_impl); test_impl_idx++) {
+ for (unsigned int test_fn_idx = 0;
+ test_fn_idx < RTE_DIM(test_fns); test_fn_idx++) {
+ if (test_fns[test_fn_idx](test_impl_idx) != 0)
+ goto fail;
+ }
+ }
+ return 0;
+fail:
+ return -1;
+}
+
+REGISTER_FAST_TEST(deque_enqueue_dequeue_autotest, true, true,
+ deque_enqueue_dequeue_autotest_fn);
diff --git a/app/test/test_deque_helper_functions.c b/app/test/test_deque_helper_functions.c
new file mode 100644
index 0000000000..0e47db7fcb
--- /dev/null
+++ b/app/test/test_deque_helper_functions.c
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Arm Limited
+ */
+
+#include "test.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_deque.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_tailq.h>
+
+static int
+test_deque_get_memsize(void)
+{
+ const ssize_t RTE_DEQUE_SZ = sizeof(struct rte_deque);
+ /* (1) Should return EINVAL when the supplied size of deque is not a
+ * power of 2.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_get_memsize_elem(4, 9), -EINVAL,
+ "Get memsize function failed.");
+
+ /* (2) Should return EINVAL when the supplied size of deque is not a
+ * multiple of 4.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_get_memsize_elem(5, 8), -EINVAL,
+ "Get memsize function failed.");
+
+ /* (3) Requested size of the deque should be less than or equal to
+ * RTE_DEQUEUE_SZ_MASK
+ */
+ TEST_ASSERT_EQUAL(rte_deque_get_memsize_elem(4, RTE_DEQUE_SZ_MASK), -EINVAL,
+ "Get memsize function failed.");
+
+ /* (4) A deque of count 1, where the element size is 0, should not allocate
+ * any more memory than necessary to hold the dequeu structure.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_get_memsize_elem(0, 1), RTE_DEQUE_SZ,
+ "Get memsize function failed.");
+
+ /* (5) Make sure the function is calculating the size correctly.
+ * size of deque: 128. Size for two elements each of size esize: 8
+ * total: 128 + 8 = 132
+ * Cache align'd size = 192.
+ */
+ const ssize_t calculated_sz = RTE_ALIGN(RTE_DEQUE_SZ + 8, RTE_CACHE_LINE_SIZE);
+ TEST_ASSERT_EQUAL(rte_deque_get_memsize_elem(4, 2), calculated_sz,
+ "Get memsize function failed.");
+ return 0;
+}
+
+/* Define a Test macro that will allow us to correctly free all the rte_deque
+ * objects that were created as a part of the test in case of a failure.
+ */
+
+#define TEST_DEQUE_MEMSAFE(exp, msg, stmt) do { \
+ if (!(exp)) { \
+ printf("error at %s:%d\tcondition " #exp " failed. Msg: %s\n", \
+ __func__, __LINE__, msg); \
+ stmt; \
+ } \
+} while (0)
+
+static int
+test_deque_init(void)
+{
+ {
+ /* (1) Make sure init fails when the flags are not correctly passed in. */
+ struct rte_deque deque;
+
+ /* Calling init with undefined flags should fail. */
+ TEST_ASSERT_EQUAL(rte_deque_init(&deque, "Deque", 10, 0x8),
+ -EINVAL, "Init failed.");
+
+ /* Calling init with a count that is not a power of 2
+ * And also not the setting the RTE_DEQUE_F_EXACT_SZ
+ * flag should fail.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_init(&deque, "Deque", 10, 0),
+ -EINVAL, "Init failed.");
+
+ /* Calling init with a count that is not a power of 2
+ * Should succeed only if the RTE_DEQUE_F_EXACT_SZ flag is set.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_init(&deque, "Deque", 10, RTE_DEQUE_F_EXACT_SZ),
+ 0, "Init failed.");
+ }
+
+ {
+ /* Make sure all the fields are being correctly set when creating a
+ * Deque of a size that is not a power of 2.
+ */
+ struct rte_deque deque;
+ static const char NAME[] = "Deque";
+
+ /* Calling init with a count that is not a power of 2
+ * But with RTE_DEQUE_F_EXACT_SZ should succeed.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_init(&deque, NAME, 10, RTE_DEQUE_F_EXACT_SZ),
+ 0, "Init failed.");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(deque.name, NAME, sizeof(NAME), "Init failed.");
+ TEST_ASSERT_EQUAL(deque.flags, RTE_DEQUE_F_EXACT_SZ, "Init failed.");
+ TEST_ASSERT_EQUAL(deque.size, 16, "Init failed.");
+ TEST_ASSERT_EQUAL(deque.mask, 15, "Init failed.");
+ TEST_ASSERT_EQUAL(deque.capacity, 10, "Init failed.");
+ }
+
+ {
+ /* Make sure all the fields are being correctly set when creating a
+ * Deque of a size that is a power of 2.
+ */
+ struct rte_deque deque;
+ static const char NAME[] = "Deque";
+
+ /* Calling init with a count that is not a power of 2
+ * But with RTE_DEQUE_F_EXACT_SZ should succeed.
+ */
+ TEST_ASSERT_EQUAL(rte_deque_init(&deque, NAME, 16, 0), 0, "Init failed.");
+
+ TEST_ASSERT_EQUAL(deque.size, 16, "Init failed.");
+ TEST_ASSERT_EQUAL(deque.mask, 15, "Init failed.");
+ TEST_ASSERT_EQUAL(deque.capacity, 15, "Init failed.");
+ }
+ return 0;
+}
+
+static int
+test_deque_create(void)
+{
+ struct rte_deque *deque;
+ const char *NAME = "Deque";
+ deque = rte_deque_create(NAME, 4, 16, 0, 0);
+
+ /* Make sure the deque creation is successful. */
+ TEST_DEQUE_MEMSAFE(deque != NULL, "Deque creation failed.", goto fail);
+ TEST_DEQUE_MEMSAFE(deque->memzone != NULL, "Deque creation failed.", goto fail);
+ return 0;
+fail:
+ rte_free(deque);
+ return -1;
+}
+
+#undef TEST_DEQUE_MEMSAFE
+
+static struct unit_test_suite deque_helper_functions_testsuite = {
+ .suite_name = "Deque library helper functions test suite",
+ .unit_test_cases = {
+ TEST_CASE(test_deque_get_memsize),
+ TEST_CASE(test_deque_init),
+ TEST_CASE(test_deque_create),
+ TEST_CASES_END(), /**< NULL terminate unit test array */
+ },
+};
+
+static int
+deque_helper_functions_autotest_fn(void)
+{
+ return unit_test_suite_runner(&deque_helper_functions_testsuite);
+}
+
+REGISTER_FAST_TEST(deque_helper_functions_autotest, true, true,
+ deque_helper_functions_autotest_fn);
--
2.25.1
next prev parent reply other threads:[~2024-04-24 13:42 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-21 6:04 [RFC] lib/st_ring: add single thread ring Honnappa Nagarahalli
2023-08-21 7:37 ` Morten Brørup
2023-08-22 5:47 ` Honnappa Nagarahalli
2023-08-24 8:05 ` Morten Brørup
2023-08-24 10:52 ` Mattias Rönnblom
2023-08-24 11:22 ` Morten Brørup
2023-08-26 23:34 ` Honnappa Nagarahalli
2023-08-21 21:14 ` Mattias Rönnblom
2023-08-22 5:43 ` Honnappa Nagarahalli
2023-08-22 8:04 ` Mattias Rönnblom
2023-08-22 16:28 ` Honnappa Nagarahalli
2023-09-04 10:13 ` Konstantin Ananyev
2023-09-04 18:10 ` Honnappa Nagarahalli
2023-09-05 8:19 ` Konstantin Ananyev
2024-04-01 1:37 ` [PATCH v1 0/2] deque: add multithread unsafe deque library Aditya Ambadipudi
2024-04-01 1:37 ` [PATCH v1 1/2] deque: add multi-thread unsafe double ended queue Aditya Ambadipudi
2024-04-06 9:35 ` Morten Brørup
2024-04-24 13:42 ` [PATCH v2 0/2] deque: add multithread unsafe deque library Aditya Ambadipudi
2024-04-24 13:42 ` [PATCH v2 1/2] deque: add multi-thread unsafe double ended queue Aditya Ambadipudi
2024-04-24 15:16 ` Morten Brørup
2024-04-24 17:21 ` Patrick Robb
2024-04-25 7:43 ` Ali Alnubani
2024-04-24 23:28 ` Mattias Rönnblom
2024-05-02 20:19 ` [PATCH v3 0/2] deque: add multithread unsafe deque library Aditya Ambadipudi
2024-05-02 20:19 ` [PATCH v3 1/2] deque: add multi-thread unsafe double ended queue Aditya Ambadipudi
2024-05-02 20:19 ` [PATCH v3 2/2] deque: add unit tests for the deque library Aditya Ambadipudi
2024-05-02 20:29 ` [PATCH v3 0/2] deque: add multithread unsafe " Aditya Ambadipudi
2024-06-27 15:03 ` Thomas Monjalon
2024-06-28 20:05 ` Wathsala Wathawana Vithanage
2024-04-24 13:42 ` Aditya Ambadipudi [this message]
2024-04-01 1:37 ` [PATCH v1 2/2] deque: add unit tests for the " Aditya Ambadipudi
2024-04-01 14:05 ` [PATCH v1 0/2] deque: add multithread unsafe " Stephen Hemminger
2024-04-01 22:28 ` Aditya Ambadipudi
2024-04-02 0:05 ` Tyler Retzlaff
2024-04-02 0:47 ` Stephen Hemminger
2024-04-02 1:35 ` Honnappa Nagarahalli
2024-04-02 2:00 ` Stephen Hemminger
2024-04-02 2:14 ` Honnappa Nagarahalli
2024-04-02 2:53 ` Stephen Hemminger
[not found] ` <PAVPR08MB9185DC373708CBD16A38EFA8EF3E2@PAVPR08MB9185.eurprd08.prod.outlook.com>
2024-04-02 4:20 ` Tyler Retzlaff
2024-04-02 23:44 ` Stephen Hemminger
2024-04-03 0:12 ` Honnappa Nagarahalli
2024-04-03 23:52 ` Variable name issues with codespell Stephen Hemminger
2024-04-02 4:20 ` [PATCH v1 0/2] deque: add multithread unsafe deque library Tyler Retzlaff
2024-04-03 16:50 ` Honnappa Nagarahalli
2024-04-03 17:46 ` Tyler Retzlaff
2024-04-02 6:05 ` Mattias Rönnblom
2024-04-02 15:25 ` Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240424134233.1336370-3-aditya.ambadipudi@arm.com \
--to=aditya.ambadipudi@arm.com \
--cc=dev@dpdk.org \
--cc=dhruv.tripathi@arm.com \
--cc=hofors@lysator.liu.se \
--cc=honnappa.nagarahalli@arm.com \
--cc=jackmin@nvidia.com \
--cc=konstantin.ananyev@huawei.com \
--cc=matan@nvidia.com \
--cc=mb@smartsharesystems.com \
--cc=nd@arm.com \
--cc=roretzla@linux.microsoft.com \
--cc=stephen@networkplumber.org \
--cc=viacheslavo@nvidia.com \
--cc=wathsala.vithanage@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).