X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest%2Ftest_ring.c;h=0ae97d341e7eb3674dfd073799d74180a6cc1727;hb=cf9b3c36e5a297200c169dbbf9d6e655d8096948;hp=e5614de739f9a33ca6d6648ea9973d02c5f779d7;hpb=ff708facfcbf42f3dcb3c62d82ecd93e7b8c2506;p=dpdk.git diff --git a/app/test/test_ring.c b/app/test/test_ring.c index e5614de739..0ae97d341e 100644 --- a/app/test/test_ring.c +++ b/app/test/test_ring.c @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation */ #include @@ -43,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -53,1347 +23,1025 @@ #include #include #include +#include #include -#include #include #include #include "test.h" +#include "test_ring.h" /* * Ring * ==== * - * #. Basic tests: done on one core: - * - * - Using single producer/single consumer functions: - * - * - Enqueue one object, two objects, MAX_BULK objects - * - Dequeue one object, two objects, MAX_BULK objects - * - Check that dequeued pointers are correct - * - * - Using multi producers/multi consumers functions: - * - * - Enqueue one object, two objects, MAX_BULK objects - * - Dequeue one object, two objects, MAX_BULK objects - * - Check that dequeued pointers are correct + * #. Functional tests. Tests single/bulk/burst, default/SPSC/MPMC, + * legacy/custom element size (4B, 8B, 16B, 20B) APIs. + * Some tests incorporate unaligned addresses for objects. + * The enqueued/dequeued data is validated for correctness. * - * - Test watermark and default bulk enqueue/dequeue: - * - * - Set watermark - * - Set default bulk value - * - Enqueue objects, check that -EDQUOT is returned when - * watermark is exceeded - * - Check that dequeued pointers are correct - * - * #. Check live watermark change - * - * - Start a loop on another lcore that will enqueue and dequeue - * objects in a ring. It will monitor the value of watermark. - * - At the same time, change the watermark on the master lcore. - * - The slave lcore will check that watermark changes from 16 to 32. - * - * #. Performance tests. - * - * Tests done in test_ring_perf.c + * #. Performance tests are in test_ring_perf.c */ #define RING_SIZE 4096 #define MAX_BULK 32 -#define N 65536 -#define TIME_S 5 - -static rte_atomic32_t synchro; - -static struct rte_ring *r; #define TEST_RING_VERIFY(exp) \ if (!(exp)) { \ printf("error at %s:%d\tcondition " #exp " failed\n", \ __func__, __LINE__); \ rte_ring_dump(stdout, r); \ - return (-1); \ + return -1; \ } #define TEST_RING_FULL_EMTPY_ITER 8 -static int -check_live_watermark_change(__attribute__((unused)) void *dummy) +static const int esize[] = {-1, 4, 8, 16, 20}; + +static const struct { + const char *desc; + uint32_t api_type; + uint32_t create_flags; + struct { + unsigned int (*flegacy)(struct rte_ring *r, + void * const *obj_table, unsigned int n, + unsigned int *free_space); + unsigned int (*felem)(struct rte_ring *r, const void *obj_table, + unsigned int esize, unsigned int n, + unsigned int *free_space); + } enq; + struct { + unsigned int (*flegacy)(struct rte_ring *r, + void **obj_table, unsigned int n, + unsigned int *available); + unsigned int (*felem)(struct rte_ring *r, void *obj_table, + unsigned int esize, unsigned int n, + unsigned int *available); + } deq; +} test_enqdeq_impl[] = { + { + .desc = "MP/MC sync mode", + .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF, + .create_flags = 0, + .enq = { + .flegacy = rte_ring_enqueue_bulk, + .felem = rte_ring_enqueue_bulk_elem, + }, + .deq = { + .flegacy = rte_ring_dequeue_bulk, + .felem = rte_ring_dequeue_bulk_elem, + }, + }, + { + .desc = "SP/SC sync mode", + .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_SPSC, + .create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ, + .enq = { + .flegacy = rte_ring_sp_enqueue_bulk, + .felem = rte_ring_sp_enqueue_bulk_elem, + }, + .deq = { + .flegacy = rte_ring_sc_dequeue_bulk, + .felem = rte_ring_sc_dequeue_bulk_elem, + }, + }, + { + .desc = "MP/MC sync mode", + .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_MPMC, + .create_flags = 0, + .enq = { + .flegacy = rte_ring_mp_enqueue_bulk, + .felem = rte_ring_mp_enqueue_bulk_elem, + }, + .deq = { + .flegacy = rte_ring_mc_dequeue_bulk, + .felem = rte_ring_mc_dequeue_bulk_elem, + }, + }, + { + .desc = "MP_RTS/MC_RTS sync mode", + .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF, + .create_flags = RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ, + .enq = { + .flegacy = rte_ring_enqueue_bulk, + .felem = rte_ring_enqueue_bulk_elem, + }, + .deq = { + .flegacy = rte_ring_dequeue_bulk, + .felem = rte_ring_dequeue_bulk_elem, + }, + }, + { + .desc = "MP_HTS/MC_HTS sync mode", + .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF, + .create_flags = RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ, + .enq = { + .flegacy = rte_ring_enqueue_bulk, + .felem = rte_ring_enqueue_bulk_elem, + }, + .deq = { + .flegacy = rte_ring_dequeue_bulk, + .felem = rte_ring_dequeue_bulk_elem, + }, + }, + { + .desc = "MP/MC sync mode", + .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF, + .create_flags = 0, + .enq = { + .flegacy = rte_ring_enqueue_burst, + .felem = rte_ring_enqueue_burst_elem, + }, + .deq = { + .flegacy = rte_ring_dequeue_burst, + .felem = rte_ring_dequeue_burst_elem, + }, + }, + { + .desc = "SP/SC sync mode", + .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_SPSC, + .create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ, + .enq = { + .flegacy = rte_ring_sp_enqueue_burst, + .felem = rte_ring_sp_enqueue_burst_elem, + }, + .deq = { + .flegacy = rte_ring_sc_dequeue_burst, + .felem = rte_ring_sc_dequeue_burst_elem, + }, + }, + { + .desc = "MP/MC sync mode", + .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_MPMC, + .create_flags = 0, + .enq = { + .flegacy = rte_ring_mp_enqueue_burst, + .felem = rte_ring_mp_enqueue_burst_elem, + }, + .deq = { + .flegacy = rte_ring_mc_dequeue_burst, + .felem = rte_ring_mc_dequeue_burst_elem, + }, + }, + { + .desc = "MP_RTS/MC_RTS sync mode", + .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF, + .create_flags = RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ, + .enq = { + .flegacy = rte_ring_enqueue_burst, + .felem = rte_ring_enqueue_burst_elem, + }, + .deq = { + .flegacy = rte_ring_dequeue_burst, + .felem = rte_ring_dequeue_burst_elem, + }, + }, + { + .desc = "MP_HTS/MC_HTS sync mode", + .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF, + .create_flags = RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ, + .enq = { + .flegacy = rte_ring_enqueue_burst, + .felem = rte_ring_enqueue_burst_elem, + }, + .deq = { + .flegacy = rte_ring_dequeue_burst, + .felem = rte_ring_dequeue_burst_elem, + }, + }, +}; + +static unsigned int +test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n, + unsigned int test_idx) { - uint64_t hz = rte_get_timer_hz(); - void *obj_table[MAX_BULK]; - unsigned watermark, watermark_old = 16; - uint64_t cur_time, end_time; - int64_t diff = 0; - int i, ret; - unsigned count = 4; - - /* init the object table */ - memset(obj_table, 0, sizeof(obj_table)); - end_time = rte_get_timer_cycles() + (hz * 2); - - /* check that bulk and watermark are 4 and 32 (respectively) */ - while (diff >= 0) { - - /* add in ring until we reach watermark */ - ret = 0; - for (i = 0; i < 16; i ++) { - if (ret != 0) - break; - ret = rte_ring_enqueue_bulk(r, obj_table, count); - } + if (esize == -1) + return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL); + else + return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n, + NULL); +} - if (ret != -EDQUOT) { - printf("Cannot enqueue objects, or watermark not " - "reached (ret=%d)\n", ret); - return -1; - } +static unsigned int +test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n, + unsigned int test_idx) +{ + if (esize == -1) + return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL); + else + return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n, + NULL); +} - /* read watermark, the only change allowed is from 16 to 32 */ - watermark = r->prod.watermark; - if (watermark != watermark_old && - (watermark_old != 16 || watermark != 32)) { - printf("Bad watermark change %u -> %u\n", watermark_old, - watermark); - return -1; - } - watermark_old = watermark; - - /* dequeue objects from ring */ - while (i--) { - ret = rte_ring_dequeue_bulk(r, obj_table, count); - if (ret != 0) { - printf("Cannot dequeue (ret=%d)\n", ret); - return -1; - } - } +static void** +test_ring_inc_ptr(void **obj, int esize, unsigned int n) +{ + /* Legacy queue APIs? */ + if ((esize) == -1) + return ((void **)obj) + n; + else + return (void **)(((uint32_t *)obj) + + (n * esize / sizeof(uint32_t))); +} - cur_time = rte_get_timer_cycles(); - diff = end_time - cur_time; - } +static void +test_ring_mem_init(void *obj, unsigned int count, int esize) +{ + unsigned int i; - if (watermark_old != 32 ) { - printf(" watermark was not updated (wm=%u)\n", - watermark_old); - return -1; - } + /* Legacy queue APIs? */ + if (esize == -1) + for (i = 0; i < count; i++) + ((void **)obj)[i] = (void *)(unsigned long)i; + else + for (i = 0; i < (count * esize / sizeof(uint32_t)); i++) + ((uint32_t *)obj)[i] = i; +} - return 0; +static void +test_ring_print_test_string(const char *istr, unsigned int api_type, int esize) +{ + printf("\n%s: ", istr); + + if (esize == -1) + printf("legacy APIs: "); + else + printf("elem APIs: element size %dB ", esize); + + if (api_type == TEST_RING_IGNORE_API_TYPE) + return; + + if (api_type & TEST_RING_THREAD_DEF) + printf(": default enqueue/dequeue: "); + else if (api_type & TEST_RING_THREAD_SPSC) + printf(": SP/SC: "); + else if (api_type & TEST_RING_THREAD_MPMC) + printf(": MP/MC: "); + + if (api_type & TEST_RING_ELEM_SINGLE) + printf("single\n"); + else if (api_type & TEST_RING_ELEM_BULK) + printf("bulk\n"); + else if (api_type & TEST_RING_ELEM_BURST) + printf("burst\n"); } +/* + * Various negative test cases. + */ static int -test_live_watermark_change(void) +test_ring_negative_tests(void) { - unsigned lcore_id = rte_lcore_id(); - unsigned lcore_id2 = rte_get_next_lcore(lcore_id, 0, 1); + struct rte_ring *rp = NULL; + struct rte_ring *rt = NULL; + unsigned int i; + + /* Test with esize not a multiple of 4 */ + rp = test_ring_create("test_bad_element_size", 23, + RING_SIZE + 1, SOCKET_ID_ANY, 0); + if (rp != NULL) { + printf("Test failed to detect invalid element size\n"); + goto test_fail; + } - printf("Test watermark live modification\n"); - rte_ring_set_water_mark(r, 16); - /* launch a thread that will enqueue and dequeue, checking - * watermark and quota */ - rte_eal_remote_launch(check_live_watermark_change, NULL, lcore_id2); + for (i = 0; i < RTE_DIM(esize); i++) { + /* Test if ring size is not power of 2 */ + rp = test_ring_create("test_bad_ring_size", esize[i], + RING_SIZE + 1, SOCKET_ID_ANY, 0); + if (rp != NULL) { + printf("Test failed to detect odd count\n"); + goto test_fail; + } - rte_delay_ms(1000); - rte_ring_set_water_mark(r, 32); - rte_delay_ms(1000); + /* Test if ring size is exceeding the limit */ + rp = test_ring_create("test_bad_ring_size", esize[i], + RTE_RING_SZ_MASK + 1, SOCKET_ID_ANY, 0); + if (rp != NULL) { + printf("Test failed to detect limits\n"); + goto test_fail; + } - if (rte_eal_wait_lcore(lcore_id2) < 0) - return -1; + /* Tests if lookup returns NULL on non-existing ring */ + rp = rte_ring_lookup("ring_not_found"); + if (rp != NULL && rte_errno != ENOENT) { + printf("Test failed to detect NULL ring lookup\n"); + goto test_fail; + } - return 0; -} + /* Test to if a non-power of 2 count causes the create + * function to fail correctly + */ + rp = test_ring_create("test_ring_count", esize[i], 4097, + SOCKET_ID_ANY, 0); + if (rp != NULL) + goto test_fail; + + rp = test_ring_create("test_ring_negative", esize[i], RING_SIZE, + SOCKET_ID_ANY, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (rp == NULL) { + printf("test_ring_negative fail to create ring\n"); + goto test_fail; + } -/* Test for catch on invalid watermark values */ -static int -test_set_watermark( void ){ - unsigned count; - int setwm; - - struct rte_ring *r = rte_ring_lookup("test_ring_basic_ex"); - if(r == NULL){ - printf( " ring lookup failed\n" ); - goto error; - } - count = r->prod.size*2; - setwm = rte_ring_set_water_mark(r, count); - if (setwm != -EINVAL){ - printf("Test failed to detect invalid watermark count value\n"); - goto error; - } + if (rte_ring_lookup("test_ring_negative") != rp) + goto test_fail; + + if (rte_ring_empty(rp) != 1) { + printf("test_ring_nagative ring is not empty but it should be\n"); + goto test_fail; + } - count = 0; - rte_ring_set_water_mark(r, count); - if (r->prod.watermark != r->prod.size) { - printf("Test failed to detect invalid watermark count value\n"); - goto error; + /* Tests if it would always fail to create ring with an used + * ring name. + */ + rt = test_ring_create("test_ring_negative", esize[i], RING_SIZE, + SOCKET_ID_ANY, 0); + if (rt != NULL) + goto test_fail; + + rte_ring_free(rp); + rp = NULL; } + return 0; -error: +test_fail: + + rte_ring_free(rp); return -1; } /* - * helper routine for test_ring_basic + * Burst and bulk operations with sp/sc, mp/mc and default (during creation) + * Random number of elements are enqueued and dequeued. */ static int -test_ring_basic_full_empty(void * const src[], void *dst[]) -{ - unsigned i, rand; - const unsigned rsz = RING_SIZE - 1; - - printf("Basic full/empty test\n"); - - for (i = 0; TEST_RING_FULL_EMTPY_ITER != i; i++) { - - /* random shift in the ring */ - rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL); - printf("%s: iteration %u, random shift: %u;\n", - __func__, i, rand); - TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src, - rand)); - TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rand)); - - /* fill the ring */ - TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src, - rsz)); - TEST_RING_VERIFY(0 == rte_ring_free_count(r)); - TEST_RING_VERIFY(rsz == rte_ring_count(r)); - TEST_RING_VERIFY(rte_ring_full(r)); - TEST_RING_VERIFY(0 == rte_ring_empty(r)); - - /* empty the ring */ - TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rsz)); - TEST_RING_VERIFY(rsz == rte_ring_free_count(r)); - TEST_RING_VERIFY(0 == rte_ring_count(r)); - TEST_RING_VERIFY(0 == rte_ring_full(r)); - TEST_RING_VERIFY(rte_ring_empty(r)); - - /* check data */ - TEST_RING_VERIFY(0 == memcmp(src, dst, rsz)); - rte_ring_dump(stdout, r); - } - return (0); -} - -static int -test_ring_basic(void) +test_ring_burst_bulk_tests1(unsigned int test_idx) { + struct rte_ring *r; void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; int ret; - unsigned i, num_elems; - - /* alloc dummy object pointers */ - src = malloc(RING_SIZE*2*sizeof(void *)); - if (src == NULL) - goto fail; - - for (i = 0; i < RING_SIZE*2 ; i++) { - src[i] = (void *)(unsigned long)i; - } - cur_src = src; - - /* alloc some room for copied objects */ - dst = malloc(RING_SIZE*2*sizeof(void *)); - if (dst == NULL) - goto fail; - - memset(dst, 0, RING_SIZE*2*sizeof(void *)); - cur_dst = dst; - - printf("enqueue 1 obj\n"); - ret = rte_ring_sp_enqueue_bulk(r, cur_src, 1); - cur_src += 1; - if (ret != 0) - goto fail; - - printf("enqueue 2 objs\n"); - ret = rte_ring_sp_enqueue_bulk(r, cur_src, 2); - cur_src += 2; - if (ret != 0) - goto fail; - - printf("enqueue MAX_BULK objs\n"); - ret = rte_ring_sp_enqueue_bulk(r, cur_src, MAX_BULK); - cur_src += MAX_BULK; - if (ret != 0) - goto fail; - - printf("dequeue 1 obj\n"); - ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 1); - cur_dst += 1; - if (ret != 0) - goto fail; - - printf("dequeue 2 objs\n"); - ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 2); - cur_dst += 2; - if (ret != 0) - goto fail; - - printf("dequeue MAX_BULK objs\n"); - ret = rte_ring_sc_dequeue_bulk(r, cur_dst, MAX_BULK); - cur_dst += MAX_BULK; - if (ret != 0) - goto fail; - - /* check data */ - if (memcmp(src, dst, cur_dst - dst)) { - rte_hexdump(stdout, "src", src, cur_src - src); - rte_hexdump(stdout, "dst", dst, cur_dst - dst); - printf("data after dequeue is not the same\n"); - goto fail; - } - cur_src = src; - cur_dst = dst; - - printf("enqueue 1 obj\n"); - ret = rte_ring_mp_enqueue_bulk(r, cur_src, 1); - cur_src += 1; - if (ret != 0) - goto fail; - - printf("enqueue 2 objs\n"); - ret = rte_ring_mp_enqueue_bulk(r, cur_src, 2); - cur_src += 2; - if (ret != 0) - goto fail; - - printf("enqueue MAX_BULK objs\n"); - ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK); - cur_src += MAX_BULK; - if (ret != 0) - goto fail; - - printf("dequeue 1 obj\n"); - ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 1); - cur_dst += 1; - if (ret != 0) - goto fail; - - printf("dequeue 2 objs\n"); - ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 2); - cur_dst += 2; - if (ret != 0) - goto fail; - - printf("dequeue MAX_BULK objs\n"); - ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK); - cur_dst += MAX_BULK; - if (ret != 0) - goto fail; - - /* check data */ - if (memcmp(src, dst, cur_dst - dst)) { - rte_hexdump(stdout, "src", src, cur_src - src); - rte_hexdump(stdout, "dst", dst, cur_dst - dst); - printf("data after dequeue is not the same\n"); - goto fail; - } - cur_src = src; - cur_dst = dst; - - printf("fill and empty the ring\n"); - for (i = 0; istats[lcore_id]; - - printf("Test the ring stats.\n"); - - /* Reset the watermark in case it was set in another test. */ - rte_ring_set_water_mark(r, 0); - - /* Reset the ring stats. */ - memset(&r->stats[lcore_id], 0, sizeof(r->stats[lcore_id])); - - /* Allocate some dummy object pointers. */ - src = malloc(RING_SIZE*2*sizeof(void *)); - if (src == NULL) - goto fail; - - for (i = 0; i < RING_SIZE*2 ; i++) { - src[i] = (void *)(unsigned long)i; - } - - /* Allocate some memory for copied objects. */ - dst = malloc(RING_SIZE*2*sizeof(void *)); - if (dst == NULL) - goto fail; + unsigned int i, j; - memset(dst, 0, RING_SIZE*2*sizeof(void *)); + for (i = 0; i < RTE_DIM(esize); i++) { + test_ring_print_test_string(test_enqdeq_impl[test_idx].desc, + test_enqdeq_impl[test_idx].api_type, esize[i]); - /* Set the head and tail pointers. */ - cur_src = src; - cur_dst = dst; + /* Create the ring */ + r = test_ring_create("test_ring_burst_bulk_tests", esize[i], + RING_SIZE, SOCKET_ID_ANY, + test_enqdeq_impl[test_idx].create_flags); - /* Do Enqueue tests. */ - printf("Test the dequeue stats.\n"); - - /* Fill the ring up to RING_SIZE -1. */ - printf("Fill the ring.\n"); - for (i = 0; i< (RING_SIZE/MAX_BULK); i++) { - rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); - cur_src += MAX_BULK; - } - - /* Adjust for final enqueue = MAX_BULK -1. */ - cur_src--; - - printf("Verify that the ring is full.\n"); - if (rte_ring_full(r) != 1) - goto fail; - - - printf("Verify the enqueue success stats.\n"); - /* Stats should match above enqueue operations to fill the ring. */ - if (ring_stats->enq_success_bulk != (RING_SIZE/MAX_BULK)) - goto fail; - - /* Current max objects is RING_SIZE -1. */ - if (ring_stats->enq_success_objs != RING_SIZE -1) - goto fail; + /* alloc dummy object pointers */ + src = test_ring_calloc(RING_SIZE * 2, esize[i]); + if (src == NULL) + goto fail; + test_ring_mem_init(src, RING_SIZE * 2, esize[i]); + cur_src = src; - /* Shouldn't have any failures yet. */ - if (ring_stats->enq_fail_bulk != 0) - goto fail; - if (ring_stats->enq_fail_objs != 0) - goto fail; + /* alloc some room for copied objects */ + dst = test_ring_calloc(RING_SIZE * 2, esize[i]); + if (dst == NULL) + goto fail; + cur_dst = dst; + + printf("fill and empty the ring\n"); + for (j = 0; j < RING_SIZE / MAX_BULK; j++) { + ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, + test_idx); + if (ret != MAX_BULK) + goto fail; + cur_src = test_ring_inc_ptr(cur_src, esize[i], + MAX_BULK); + + ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK, + test_idx); + if (ret != MAX_BULK) + goto fail; + cur_dst = test_ring_inc_ptr(cur_dst, esize[i], + MAX_BULK); + } + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } - printf("Test stats for SP burst enqueue to a full ring.\n"); - num_items = 2; - ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); - if ((ret & RTE_RING_SZ_MASK) != 0) - goto fail; + /* Free memory before test completed */ + rte_ring_free(r); + rte_free(src); + rte_free(dst); + r = NULL; + src = NULL; + dst = NULL; + } - failed_enqueue_ops += 1; - failed_enqueue_items += num_items; + return 0; +fail: + rte_ring_free(r); + rte_free(src); + rte_free(dst); + return -1; +} - /* The enqueue should have failed. */ - if (ring_stats->enq_fail_bulk != failed_enqueue_ops) - goto fail; - if (ring_stats->enq_fail_objs != failed_enqueue_items) - goto fail; +/* + * Burst and bulk operations with sp/sc, mp/mc and default (during creation) + * Enqueue till the ring is full and dequeue till the ring becomes empty. + */ +static int +test_ring_burst_bulk_tests4(unsigned int test_idx) +{ + struct rte_ring *r; + void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; + int ret; + unsigned int i, j; + unsigned int api_type, num_elems; + api_type = test_enqdeq_impl[test_idx].api_type; - printf("Test stats for SP bulk enqueue to a full ring.\n"); - num_items = 4; - ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items); - if (ret != -ENOBUFS) - goto fail; + for (i = 0; i < RTE_DIM(esize); i++) { + test_ring_print_test_string(test_enqdeq_impl[test_idx].desc, + test_enqdeq_impl[test_idx].api_type, esize[i]); - failed_enqueue_ops += 1; - failed_enqueue_items += num_items; + /* Create the ring */ + r = test_ring_create("test_ring_burst_bulk_tests", esize[i], + RING_SIZE, SOCKET_ID_ANY, + test_enqdeq_impl[test_idx].create_flags); - /* The enqueue should have failed. */ - if (ring_stats->enq_fail_bulk != failed_enqueue_ops) - goto fail; - if (ring_stats->enq_fail_objs != failed_enqueue_items) - goto fail; + /* alloc dummy object pointers */ + src = test_ring_calloc(RING_SIZE * 2, esize[i]); + if (src == NULL) + goto fail; + test_ring_mem_init(src, RING_SIZE * 2, esize[i]); + cur_src = src; + /* alloc some room for copied objects */ + dst = test_ring_calloc(RING_SIZE * 2, esize[i]); + if (dst == NULL) + goto fail; + cur_dst = dst; + + printf("Test enqueue without enough memory space\n"); + for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) { + ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, + test_idx); + if (ret != MAX_BULK) + goto fail; + cur_src = test_ring_inc_ptr(cur_src, esize[i], + MAX_BULK); + } - printf("Test stats for MP burst enqueue to a full ring.\n"); - num_items = 8; - ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items); - if ((ret & RTE_RING_SZ_MASK) != 0) - goto fail; + printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n"); + ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx); + if (ret != 2) + goto fail; + cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); - failed_enqueue_ops += 1; - failed_enqueue_items += num_items; + printf("Enqueue the remaining entries = MAX_BULK - 3\n"); + /* Bulk APIs enqueue exact number of elements */ + if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK) + num_elems = MAX_BULK - 3; + else + num_elems = MAX_BULK; + /* Always one free entry left */ + ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems, + test_idx); + if (ret != MAX_BULK - 3) + goto fail; + cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3); - /* The enqueue should have failed. */ - if (ring_stats->enq_fail_bulk != failed_enqueue_ops) - goto fail; - if (ring_stats->enq_fail_objs != failed_enqueue_items) - goto fail; + printf("Test if ring is full\n"); + if (rte_ring_full(r) != 1) + goto fail; + printf("Test enqueue for a full entry\n"); + ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, + test_idx); + if (ret != 0) + goto fail; - printf("Test stats for MP bulk enqueue to a full ring.\n"); - num_items = 16; - ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items); - if (ret != -ENOBUFS) - goto fail; + printf("Test dequeue without enough objects\n"); + for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) { + ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK, + test_idx); + if (ret != MAX_BULK) + goto fail; + cur_dst = test_ring_inc_ptr(cur_dst, esize[i], + MAX_BULK); + } - failed_enqueue_ops += 1; - failed_enqueue_items += num_items; + /* Available memory space for the exact MAX_BULK entries */ + ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx); + if (ret != 2) + goto fail; + cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); - /* The enqueue should have failed. */ - if (ring_stats->enq_fail_bulk != failed_enqueue_ops) - goto fail; - if (ring_stats->enq_fail_objs != failed_enqueue_items) - goto fail; + /* Bulk APIs enqueue exact number of elements */ + if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK) + num_elems = MAX_BULK - 3; + else + num_elems = MAX_BULK; + ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems, + test_idx); + if (ret != MAX_BULK - 3) + goto fail; + cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3); + printf("Test if ring is empty\n"); + /* Check if ring is empty */ + if (rte_ring_empty(r) != 1) + goto fail; - /* Do Dequeue tests. */ - printf("Test the dequeue stats.\n"); + /* check data */ + if (memcmp(src, dst, cur_dst - dst)) { + rte_hexdump(stdout, "src", src, cur_src - src); + rte_hexdump(stdout, "dst", dst, cur_dst - dst); + printf("data after dequeue is not the same\n"); + goto fail; + } - printf("Empty the ring.\n"); - for (i = 0; ideq_success_bulk != (RING_SIZE/MAX_BULK)) - goto fail; - - /* Objects dequeued is RING_SIZE -1. */ - if (ring_stats->deq_success_objs != RING_SIZE -1) - goto fail; - - /* Shouldn't have any dequeue failure stats yet. */ - if (ring_stats->deq_fail_bulk != 0) - goto fail; - - printf("Test stats for SC burst dequeue with an empty ring.\n"); - num_items = 2; - ret = rte_ring_sc_dequeue_burst(r, cur_dst, num_items); - if ((ret & RTE_RING_SZ_MASK) != 0) - goto fail; - - failed_dequeue_ops += 1; - failed_dequeue_items += num_items; - - /* The dequeue should have failed. */ - if (ring_stats->deq_fail_bulk != failed_dequeue_ops) - goto fail; - if (ring_stats->deq_fail_objs != failed_dequeue_items) - goto fail; - - - printf("Test stats for SC bulk dequeue with an empty ring.\n"); - num_items = 4; - ret = rte_ring_sc_dequeue_bulk(r, cur_dst, num_items); - if (ret != -ENOENT) - goto fail; - - failed_dequeue_ops += 1; - failed_dequeue_items += num_items; - - /* The dequeue should have failed. */ - if (ring_stats->deq_fail_bulk != failed_dequeue_ops) - goto fail; - if (ring_stats->deq_fail_objs != failed_dequeue_items) - goto fail; - - - printf("Test stats for MC burst dequeue with an empty ring.\n"); - num_items = 8; - ret = rte_ring_mc_dequeue_burst(r, cur_dst, num_items); - if ((ret & RTE_RING_SZ_MASK) != 0) - goto fail; - failed_dequeue_ops += 1; - failed_dequeue_items += num_items; - - /* The dequeue should have failed. */ - if (ring_stats->deq_fail_bulk != failed_dequeue_ops) - goto fail; - if (ring_stats->deq_fail_objs != failed_dequeue_items) - goto fail; - - - printf("Test stats for MC bulk dequeue with an empty ring.\n"); - num_items = 16; - ret = rte_ring_mc_dequeue_bulk(r, cur_dst, num_items); - if (ret != -ENOENT) - goto fail; - - failed_dequeue_ops += 1; - failed_dequeue_items += num_items; - - /* The dequeue should have failed. */ - if (ring_stats->deq_fail_bulk != failed_dequeue_ops) - goto fail; - if (ring_stats->deq_fail_objs != failed_dequeue_items) - goto fail; - - - printf("Test total enqueue/dequeue stats.\n"); - /* At this point the enqueue and dequeue stats should be the same. */ - if (ring_stats->enq_success_bulk != ring_stats->deq_success_bulk) - goto fail; - if (ring_stats->enq_success_objs != ring_stats->deq_success_objs) - goto fail; - if (ring_stats->enq_fail_bulk != ring_stats->deq_fail_bulk) - goto fail; - if (ring_stats->enq_fail_objs != ring_stats->deq_fail_objs) - goto fail; - - - /* Watermark Tests. */ - printf("Test the watermark/quota stats.\n"); - - printf("Verify the initial watermark stats.\n"); - /* Watermark stats should be 0 since there is no watermark. */ - if (ring_stats->enq_quota_bulk != 0) - goto fail; - if (ring_stats->enq_quota_objs != 0) - goto fail; - - /* Set a watermark. */ - rte_ring_set_water_mark(r, 16); - - /* Reset pointers. */ - cur_src = src; - cur_dst = dst; - - last_enqueue_ops = ring_stats->enq_success_bulk; - last_enqueue_items = ring_stats->enq_success_objs; - - - printf("Test stats for SP burst enqueue below watermark.\n"); - num_items = 8; - ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); - if ((ret & RTE_RING_SZ_MASK) != num_items) - goto fail; - - /* Watermark stats should still be 0. */ - if (ring_stats->enq_quota_bulk != 0) - goto fail; - if (ring_stats->enq_quota_objs != 0) - goto fail; - - /* Success stats should have increased. */ - if (ring_stats->enq_success_bulk != last_enqueue_ops + 1) - goto fail; - if (ring_stats->enq_success_objs != last_enqueue_items + num_items) - goto fail; - - last_enqueue_ops = ring_stats->enq_success_bulk; - last_enqueue_items = ring_stats->enq_success_objs; - - - printf("Test stats for SP burst enqueue at watermark.\n"); - num_items = 8; - ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); - if ((ret & RTE_RING_SZ_MASK) != num_items) - goto fail; - - /* Watermark stats should have changed. */ - if (ring_stats->enq_quota_bulk != 1) - goto fail; - if (ring_stats->enq_quota_objs != num_items) - goto fail; - - last_quota_ops = ring_stats->enq_quota_bulk; - last_quota_items = ring_stats->enq_quota_objs; - - - printf("Test stats for SP burst enqueue above watermark.\n"); - num_items = 1; - ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); - if ((ret & RTE_RING_SZ_MASK) != num_items) - goto fail; - - /* Watermark stats should have changed. */ - if (ring_stats->enq_quota_bulk != last_quota_ops +1) - goto fail; - if (ring_stats->enq_quota_objs != last_quota_items + num_items) - goto fail; + return 0; +fail: + rte_ring_free(r); + rte_free(src); + rte_free(dst); + return -1; +} - last_quota_ops = ring_stats->enq_quota_bulk; - last_quota_items = ring_stats->enq_quota_objs; - - - printf("Test stats for MP burst enqueue above watermark.\n"); - num_items = 2; - ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items); - if ((ret & RTE_RING_SZ_MASK) != num_items) - goto fail; - - /* Watermark stats should have changed. */ - if (ring_stats->enq_quota_bulk != last_quota_ops +1) - goto fail; - if (ring_stats->enq_quota_objs != last_quota_items + num_items) - goto fail; +/* + * Test default, single element, bulk and burst APIs + */ +static int +test_ring_basic_ex(void) +{ + int ret = -1; + unsigned int i, j; + struct rte_ring *rp = NULL; + void *obj = NULL; + + for (i = 0; i < RTE_DIM(esize); i++) { + obj = test_ring_calloc(RING_SIZE, esize[i]); + if (obj == NULL) { + printf("%s: failed to alloc memory\n", __func__); + goto fail_test; + } - last_quota_ops = ring_stats->enq_quota_bulk; - last_quota_items = ring_stats->enq_quota_objs; - - - printf("Test stats for SP bulk enqueue above watermark.\n"); - num_items = 4; - ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items); - if (ret != -EDQUOT) - goto fail; + rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE, + SOCKET_ID_ANY, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (rp == NULL) { + printf("%s: failed to create ring\n", __func__); + goto fail_test; + } - /* Watermark stats should have changed. */ - if (ring_stats->enq_quota_bulk != last_quota_ops +1) - goto fail; - if (ring_stats->enq_quota_objs != last_quota_items + num_items) - goto fail; - - last_quota_ops = ring_stats->enq_quota_bulk; - last_quota_items = ring_stats->enq_quota_objs; + if (rte_ring_lookup("test_ring_basic_ex") != rp) { + printf("%s: failed to find ring\n", __func__); + goto fail_test; + } + if (rte_ring_empty(rp) != 1) { + printf("%s: ring is not empty but it should be\n", + __func__); + goto fail_test; + } - printf("Test stats for MP bulk enqueue above watermark.\n"); - num_items = 8; - ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items); - if (ret != -EDQUOT) - goto fail; + printf("%u ring entries are now free\n", + rte_ring_free_count(rp)); - /* Watermark stats should have changed. */ - if (ring_stats->enq_quota_bulk != last_quota_ops +1) - goto fail; - if (ring_stats->enq_quota_objs != last_quota_items + num_items) - goto fail; - - printf("Test watermark success stats.\n"); - /* Success stats should be same as last non-watermarked enqueue. */ - if (ring_stats->enq_success_bulk != last_enqueue_ops) - goto fail; - if (ring_stats->enq_success_objs != last_enqueue_items) - goto fail; + for (j = 0; j < RING_SIZE; j++) { + test_ring_enqueue(rp, obj, esize[i], 1, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); + } + if (rte_ring_full(rp) != 1) { + printf("%s: ring is not full but it should be\n", + __func__); + goto fail_test; + } - /* Cleanup. */ - - /* Empty the ring. */ - for (i = 0; istats[lcore_id], 0, sizeof(r->stats[lcore_id])); + /* Following tests use the configured flags to decide + * SP/SC or MP/MC. + */ + /* Covering the ring burst operation */ + ret = test_ring_enqueue(rp, obj, esize[i], 2, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST); + if (ret != 2) { + printf("%s: rte_ring_enqueue_burst fails\n", __func__); + goto fail_test; + } - /* Free memory before test completed */ - if (src) - free(src); - if (dst) - free(dst); - return 0; + ret = test_ring_dequeue(rp, obj, esize[i], 2, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST); + if (ret != 2) { + printf("%s: rte_ring_dequeue_burst fails\n", __func__); + goto fail_test; + } -fail: - if (src) - free(src); - if (dst) - free(dst); - return -1; -#endif -} + /* Covering the ring bulk operation */ + ret = test_ring_enqueue(rp, obj, esize[i], 2, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK); + if (ret != 2) { + printf("%s: rte_ring_enqueue_bulk fails\n", __func__); + goto fail_test; + } -/* - * it will always fail to create ring with a wrong ring size number in this function - */ -static int -test_ring_creation_with_wrong_size(void) -{ - struct rte_ring * rp = NULL; + ret = test_ring_dequeue(rp, obj, esize[i], 2, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK); + if (ret != 2) { + printf("%s: rte_ring_dequeue_bulk fails\n", __func__); + goto fail_test; + } - /* Test if ring size is not power of 2 */ - rp = rte_ring_create("test_bad_ring_size", RING_SIZE + 1, SOCKET_ID_ANY, 0); - if (NULL != rp) { - return -1; + rte_ring_free(rp); + rte_free(obj); + rp = NULL; + obj = NULL; } - /* Test if ring size is exceeding the limit */ - rp = rte_ring_create("test_bad_ring_size", (RTE_RING_SZ_MASK + 1), SOCKET_ID_ANY, 0); - if (NULL != rp) { - return -1; - } return 0; -} -/* - * it tests if it would always fail to create ring with an used ring name - */ -static int -test_ring_creation_with_an_used_name(void) -{ - struct rte_ring * rp; - - rp = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0); - if (NULL != rp) - return -1; - - return 0; -} - -/* - * Test to if a non-power of 2 count causes the create - * function to fail correctly - */ -static int -test_create_count_odd(void) -{ - struct rte_ring *r = rte_ring_create("test_ring_count", - 4097, SOCKET_ID_ANY, 0 ); - if(r != NULL){ - return -1; - } - return 0; -} +fail_test: + rte_ring_free(rp); + if (obj != NULL) + rte_free(obj); -static int -test_lookup_null(void) -{ - struct rte_ring *rlp = rte_ring_lookup("ring_not_found"); - if (rlp ==NULL) - if (rte_errno != ENOENT){ - printf( "test failed to returnn error on null pointer\n"); - return -1; - } - return 0; + return -1; } /* - * it tests some more basic ring operations + * Basic test cases with exact size ring. */ static int -test_ring_basic_ex(void) +test_ring_with_exact_size(void) { + struct rte_ring *std_r = NULL, *exact_sz_r = NULL; + void *obj_orig; + void *obj; + const unsigned int ring_sz = 16; + unsigned int i, j; int ret = -1; - unsigned i; - struct rte_ring * rp; - void **obj = NULL; - - obj = rte_calloc("test_ring_basic_ex_malloc", RING_SIZE, sizeof(void *), 0); - if (obj == NULL) { - printf("test_ring_basic_ex fail to rte_malloc\n"); - goto fail_test; - } - rp = rte_ring_create("test_ring_basic_ex", RING_SIZE, SOCKET_ID_ANY, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (rp == NULL) { - printf("test_ring_basic_ex fail to create ring\n"); - goto fail_test; - } - - if (rte_ring_lookup("test_ring_basic_ex") != rp) { - goto fail_test; - } - - if (rte_ring_empty(rp) != 1) { - printf("test_ring_basic_ex ring is not empty but it should be\n"); - goto fail_test; - } - - printf("%u ring entries are now free\n", rte_ring_free_count(rp)); - - for (i = 0; i < RING_SIZE; i ++) { - rte_ring_enqueue(rp, obj[i]); - } - - if (rte_ring_full(rp) != 1) { - printf("test_ring_basic_ex ring is not full but it should be\n"); - goto fail_test; - } + for (i = 0; i < RTE_DIM(esize); i++) { + test_ring_print_test_string("Test exact size ring", + TEST_RING_IGNORE_API_TYPE, + esize[i]); + + /* alloc object pointers. Allocate one extra object + * and create an unaligned address. + */ + obj_orig = test_ring_calloc(17, esize[i]); + if (obj_orig == NULL) + goto test_fail; + obj = ((char *)obj_orig) + 1; + + std_r = test_ring_create("std", esize[i], ring_sz, + rte_socket_id(), + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (std_r == NULL) { + printf("%s: error, can't create std ring\n", __func__); + goto test_fail; + } + exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz, + rte_socket_id(), + RING_F_SP_ENQ | RING_F_SC_DEQ | + RING_F_EXACT_SZ); + if (exact_sz_r == NULL) { + printf("%s: error, can't create exact size ring\n", + __func__); + goto test_fail; + } - for (i = 0; i < RING_SIZE; i ++) { - rte_ring_dequeue(rp, &obj[i]); - } + /* + * Check that the exact size ring is bigger than the + * standard ring + */ + if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) { + printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n", + __func__, + rte_ring_get_size(std_r), + rte_ring_get_size(exact_sz_r)); + goto test_fail; + } + /* + * check that the exact_sz_ring can hold one more element + * than the standard ring. (16 vs 15 elements) + */ + for (j = 0; j < ring_sz - 1; j++) { + test_ring_enqueue(std_r, obj, esize[i], 1, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); + test_ring_enqueue(exact_sz_r, obj, esize[i], 1, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); + } + ret = test_ring_enqueue(std_r, obj, esize[i], 1, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); + if (ret != -ENOBUFS) { + printf("%s: error, unexpected successful enqueue\n", + __func__); + goto test_fail; + } + ret = test_ring_enqueue(exact_sz_r, obj, esize[i], 1, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); + if (ret == -ENOBUFS) { + printf("%s: error, enqueue failed\n", __func__); + goto test_fail; + } - if (rte_ring_empty(rp) != 1) { - printf("test_ring_basic_ex ring is not empty but it should be\n"); - goto fail_test; - } + /* check that dequeue returns the expected number of elements */ + ret = test_ring_dequeue(exact_sz_r, obj, esize[i], ring_sz, + TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST); + if (ret != (int)ring_sz) { + printf("%s: error, failed to dequeue expected nb of elements\n", + __func__); + goto test_fail; + } - /* Covering the ring burst operation */ - ret = rte_ring_enqueue_burst(rp, obj, 2); - if ((ret & RTE_RING_SZ_MASK) != 2) { - printf("test_ring_basic_ex: rte_ring_enqueue_burst fails \n"); - goto fail_test; - } + /* check that the capacity function returns expected value */ + if (rte_ring_get_capacity(exact_sz_r) != ring_sz) { + printf("%s: error, incorrect ring capacity reported\n", + __func__); + goto test_fail; + } - ret = rte_ring_dequeue_burst(rp, obj, 2); - if (ret != 2) { - printf("test_ring_basic_ex: rte_ring_dequeue_burst fails \n"); - goto fail_test; + rte_free(obj_orig); + rte_ring_free(std_r); + rte_ring_free(exact_sz_r); + obj_orig = NULL; + std_r = NULL; + exact_sz_r = NULL; } - ret = 0; -fail_test: - if (obj != NULL) - rte_free(obj); + return 0; - return ret; +test_fail: + rte_free(obj_orig); + rte_ring_free(std_r); + rte_ring_free(exact_sz_r); + return -1; } static int test_ring(void) { - /* some more basic operations */ - if (test_ring_basic_ex() < 0) - return -1; - - rte_atomic32_init(&synchro); - - if (r == NULL) - r = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0); - if (r == NULL) - return -1; + int32_t rc; + unsigned int i; - /* retrieve the ring from its name */ - if (rte_ring_lookup("test") != r) { - printf("Cannot lookup ring from its name\n"); - return -1; - } - - /* burst operations */ - if (test_ring_burst_basic() < 0) - return -1; + /* Negative test cases */ + if (test_ring_negative_tests() < 0) + goto test_fail; - /* basic operations */ - if (test_ring_basic() < 0) - return -1; + /* Some basic operations */ + if (test_ring_basic_ex() < 0) + goto test_fail; - /* ring stats */ - if (test_ring_stats() < 0) - return -1; + if (test_ring_with_exact_size() < 0) + goto test_fail; - /* basic operations */ - if (test_live_watermark_change() < 0) - return -1; + /* Burst and bulk operations with sp/sc, mp/mc and default. + * The test cases are split into smaller test cases to + * help clang compile faster. + */ + for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) { - if ( test_set_watermark() < 0){ - printf ("Test failed to detect invalid parameter\n"); - return -1; - } - else - printf ( "Test detected forced bad watermark values\n"); - if ( test_create_count_odd() < 0){ - printf ("Test failed to detect odd count\n"); - return -1; - } - else - printf ( "Test detected odd count\n"); + rc = test_ring_burst_bulk_tests1(i); + if (rc < 0) + goto test_fail; - if ( test_lookup_null() < 0){ - printf ("Test failed to detect NULL ring lookup\n"); - return -1; - } - else - printf ( "Test detected NULL ring lookup \n"); + rc = test_ring_burst_bulk_tests2(i); + if (rc < 0) + goto test_fail; - /* test of creating ring with wrong size */ - if (test_ring_creation_with_wrong_size() < 0) - return -1; + rc = test_ring_burst_bulk_tests3(i); + if (rc < 0) + goto test_fail; - /* test of creation ring with an used name */ - if (test_ring_creation_with_an_used_name() < 0) - return -1; + rc = test_ring_burst_bulk_tests4(i); + if (rc < 0) + goto test_fail; + } /* dump the ring status */ rte_ring_list_dump(stdout); return 0; + +test_fail: + + return -1; } -static struct test_command ring_cmd = { - .command = "ring_autotest", - .callback = test_ring, -}; -REGISTER_TEST_COMMAND(ring_cmd); +REGISTER_TEST_COMMAND(ring_autotest, test_ring);