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.ambadip...@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


Reply via email to