Renames shadow variables found by -Wshadow. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
1004 lines
28 KiB
C
1004 lines
28 KiB
C
/*
|
|
* Copyright (c) 2016 Intel Corporation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <zephyr/ztest.h>
|
|
#include <zephyr/irq_offload.h>
|
|
#include <zephyr/sys/ring_buffer.h>
|
|
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(test);
|
|
|
|
/**
|
|
* @defgroup lib_ringbuffer_tests Ringbuffer
|
|
* @ingroup all_tests
|
|
* @{
|
|
* @}
|
|
*/
|
|
|
|
RING_BUF_ITEM_DECLARE_POW2(ring_buf1, 8);
|
|
|
|
#define TYPE 1
|
|
#define VALUE 2
|
|
#define INITIAL_SIZE 2
|
|
|
|
|
|
#define RINGBUFFER_SIZE 5
|
|
#define DATA_MAX_SIZE 3
|
|
#define POW 2
|
|
extern void test_ringbuffer_concurrent(void);
|
|
extern void test_ringbuffer_zerocpy_stress(void);
|
|
extern void test_ringbuffer_cpy_stress(void);
|
|
extern void test_ringbuffer_item_stress(void);
|
|
/**
|
|
* @brief Test APIs of ring buffer
|
|
*
|
|
* @details
|
|
* Test Objective:
|
|
* - Define and initialize a ring buffer and
|
|
* the ring buffer copy data out of the array by
|
|
* ring_buf_item_put(), and then ring buffer data
|
|
* is copied into the array by ring_buf_item_get()
|
|
* return error when full/empty.
|
|
*
|
|
* Testing techniques:
|
|
* - Interface testing
|
|
* - Dynamic analysis and testing
|
|
* - Equivalence classes and input partition testing
|
|
* - Structural test coverage(entry points,statements,branches)
|
|
*
|
|
* Prerequisite Conditions:
|
|
* - Define and initialize a ringbuffer by using macro
|
|
* RING_BUF_ITEM_DECLARE_POW2
|
|
*
|
|
* Input Specifications:
|
|
* - N/A
|
|
*
|
|
* Test Procedure:
|
|
* -# Defined an array with some data items that ready for being
|
|
* put.
|
|
* -# Put data items with "while loop".
|
|
* -# Check if an error will be seen when the ringbuffer is full.
|
|
* -# Get data items from the ringbuffer.
|
|
* -# Check if the data put are equal to the data got.
|
|
* -# Going on getting data from the ringbuffer.
|
|
* -# Check if an error will be seen when the ringbuffer is empty.
|
|
*
|
|
* Expected Test Result:
|
|
* - Data items pushed shall be equal to what are gotten. And
|
|
* An error shall be shown up when an item is put into a full ringbuffer or
|
|
* get some items from an empty ringbuffer.
|
|
*
|
|
* Pass/Fail Criteria:
|
|
* - Success if test result of step 3.5,7 is passed. Otherwise, failure.
|
|
*
|
|
* Assumptions and Constraints:
|
|
* - N/A
|
|
*
|
|
* @ingroup lib_ringbuffer_tests
|
|
*
|
|
* @see ring_buf_item_put, ring_buf_item_get
|
|
*/
|
|
ZTEST(ringbuffer_api, test_ring_buffer_main)
|
|
{
|
|
int ret, put_count, i;
|
|
uint32_t getdata[6];
|
|
uint8_t getsize, getval;
|
|
uint16_t gettype;
|
|
int dsize = INITIAL_SIZE;
|
|
|
|
__aligned(sizeof(uint32_t)) char rb_data[] = "ABCDEFGHIJKLMNOPQRSTUVWX";
|
|
put_count = 0;
|
|
|
|
while (1) {
|
|
ret = ring_buf_item_put(&ring_buf1, TYPE, VALUE,
|
|
(uint32_t *)rb_data, dsize);
|
|
if (ret == -EMSGSIZE) {
|
|
LOG_DBG("ring buffer is full");
|
|
break;
|
|
}
|
|
LOG_DBG("inserted %d chunks, %d remaining", dsize,
|
|
ring_buf_space_get(&ring_buf1));
|
|
dsize = (dsize + 1) % RING_BUF_ITEM_SIZEOF(rb_data);
|
|
put_count++;
|
|
}
|
|
|
|
getsize = INITIAL_SIZE - 1;
|
|
ret = ring_buf_item_get(&ring_buf1, &gettype, &getval,
|
|
getdata, &getsize);
|
|
if (ret != -EMSGSIZE) {
|
|
LOG_DBG("Allowed retrieval with insufficient "
|
|
"destination buffer space");
|
|
zassert_true((getsize == INITIAL_SIZE),
|
|
"Correct size wasn't reported back to the caller");
|
|
}
|
|
|
|
for (i = 0; i < put_count; i++) {
|
|
getsize = RING_BUF_ITEM_SIZEOF(getdata);
|
|
ret = ring_buf_item_get(&ring_buf1, &gettype, &getval, getdata,
|
|
&getsize);
|
|
zassert_true((ret == 0), "Couldn't retrieve a stored value");
|
|
LOG_DBG("got %u chunks of type %u and val %u, %u remaining",
|
|
getsize, gettype, getval,
|
|
ring_buf_item_space_get(&ring_buf1));
|
|
|
|
zassert_true((memcmp((char *)getdata, rb_data,
|
|
getsize * sizeof(uint32_t)) == 0), "data corrupted");
|
|
zassert_true((gettype == TYPE), "type information corrupted");
|
|
zassert_true((getval == VALUE), "value information corrupted");
|
|
}
|
|
|
|
getsize = RING_BUF_ITEM_SIZEOF(getdata);
|
|
ret = ring_buf_item_get(&ring_buf1, &gettype, &getval, getdata,
|
|
&getsize);
|
|
zassert_true((ret == -EAGAIN), "Got data out of an empty buffer");
|
|
}
|
|
|
|
/**TESTPOINT: init via RING_BUF_ITEM_DECLARE_POW2*/
|
|
RING_BUF_ITEM_DECLARE_POW2(ringbuf_pow2, POW);
|
|
|
|
/**TESTPOINT: init via RING_BUF_ITEM_DECLARE*/
|
|
/**
|
|
* @brief define a ring buffer with arbitrary size
|
|
*
|
|
* @see RING_BUF_ITEM_DECLARE(), RING_BUF_DECLARE()
|
|
*/
|
|
RING_BUF_ITEM_DECLARE(ringbuf_size, RINGBUFFER_SIZE);
|
|
|
|
RING_BUF_DECLARE(ringbuf_raw, RINGBUFFER_SIZE);
|
|
|
|
static struct ring_buf ringbuf, *pbuf;
|
|
|
|
static uint32_t buffer[RINGBUFFER_SIZE];
|
|
|
|
static struct {
|
|
uint8_t length;
|
|
uint8_t value;
|
|
uint16_t type;
|
|
uint32_t buffer[DATA_MAX_SIZE];
|
|
} static_data[] = {
|
|
{ 0, 32, 1, {} },
|
|
{ 1, 76, 54, { 0x89ab } },
|
|
{ 3, 0xff, 0xffff, { 0x0f0f, 0xf0f0, 0xff00 } }
|
|
};
|
|
|
|
/*entry of contexts*/
|
|
static void tringbuf_put(const void *p)
|
|
{
|
|
int index = POINTER_TO_INT(p);
|
|
/**TESTPOINT: ring buffer put*/
|
|
int ret = ring_buf_item_put(pbuf, static_data[index].type, static_data[index].value,
|
|
static_data[index].buffer, static_data[index].length);
|
|
|
|
zassert_equal(ret, 0);
|
|
}
|
|
|
|
static void tringbuf_get(const void *p)
|
|
{
|
|
uint16_t type;
|
|
uint8_t value, size32 = DATA_MAX_SIZE;
|
|
uint32_t rx_data[DATA_MAX_SIZE];
|
|
int ret, index = POINTER_TO_INT(p);
|
|
|
|
/**TESTPOINT: ring buffer get*/
|
|
ret = ring_buf_item_get(pbuf, &type, &value, rx_data, &size32);
|
|
zassert_equal(ret, 0);
|
|
zassert_equal(type, static_data[index].type);
|
|
zassert_equal(value, static_data[index].value);
|
|
zassert_equal(size32, static_data[index].length);
|
|
zassert_equal(memcmp(rx_data, static_data[index].buffer, size32), 0);
|
|
}
|
|
|
|
static void tringbuf_get_discard(const void *p)
|
|
{
|
|
uint16_t type;
|
|
uint8_t value, size32;
|
|
int ret, index = POINTER_TO_INT(p);
|
|
|
|
/**TESTPOINT: ring buffer get*/
|
|
ret = ring_buf_item_get(pbuf, &type, &value, NULL, &size32);
|
|
zassert_equal(ret, 0);
|
|
zassert_equal(type, static_data[index].type);
|
|
zassert_equal(value, static_data[index].value);
|
|
zassert_equal(size32, static_data[index].length);
|
|
}
|
|
|
|
/*test cases*/
|
|
ZTEST(ringbuffer_api, test_ringbuffer_init)
|
|
{
|
|
/**TESTPOINT: init via ring_buf_item_init*/
|
|
ring_buf_item_init(&ringbuf, RINGBUFFER_SIZE, buffer);
|
|
zassert_true(ring_buf_is_empty(&ringbuf));
|
|
zassert_equal(ring_buf_item_space_get(&ringbuf), RINGBUFFER_SIZE);
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_declare_pow2)
|
|
{
|
|
zassert_true(ring_buf_is_empty(&ringbuf_pow2));
|
|
zassert_equal(ring_buf_item_space_get(&ringbuf_pow2), (1 << POW));
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_declare_size)
|
|
{
|
|
zassert_true(ring_buf_is_empty(&ringbuf_size));
|
|
zassert_equal(ring_buf_item_space_get(&ringbuf_size), RINGBUFFER_SIZE,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* @brief verify that ringbuffer can be placed in any user-controlled memory
|
|
*
|
|
* @details
|
|
* Test Objective:
|
|
* - define and initialize a ring buffer by struct ring_buf,
|
|
* then passing data by thread to verify the ringbuffer
|
|
* if it works to be placed in any user-controlled memory.
|
|
*
|
|
* Testing techniques:
|
|
* - Interface testing
|
|
* - Dynamic analysis and testing
|
|
* - Structural test coverage(entry points,statements,branches)
|
|
*
|
|
* Prerequisite Conditions:
|
|
* - Define and initialize a ringbuffer by using struct ring_buf
|
|
* - Define a pointer of ring buffer type.
|
|
*
|
|
* Input Specifications:
|
|
* - N/A
|
|
*
|
|
* Test Procedure:
|
|
* -# Put data items into a ringbuffer
|
|
* -# Get data items from a ringbuffer
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
* -# Repeat 1,2,3 to verify the ringbuffer is working normally.
|
|
*
|
|
* Expected Test Result:
|
|
* - data items pushed shall be equal to what are gotten.
|
|
*
|
|
* Pass/Fail Criteria:
|
|
* - Success if test result of step 3,4 is passed. Otherwise, failure.
|
|
*
|
|
* Assumptions and Constraints:
|
|
* - N/A
|
|
*
|
|
* @ingroup lib_ringbuffer_tests
|
|
*
|
|
* @see ring_buf_item_put, ring_buf_item_get
|
|
*/
|
|
ZTEST(ringbuffer_api, test_ringbuffer_put_get_thread)
|
|
{
|
|
pbuf = &ringbuf;
|
|
for (int i = 0; i < 1000; i++) {
|
|
tringbuf_put((const void *)0);
|
|
tringbuf_put((const void *)1);
|
|
tringbuf_get((const void *)0);
|
|
tringbuf_get((const void *)1);
|
|
tringbuf_put((const void *)2);
|
|
zassert_false(ring_buf_is_empty(pbuf));
|
|
tringbuf_get((const void *)2);
|
|
zassert_true(ring_buf_is_empty(pbuf));
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_put_get_isr)
|
|
{
|
|
pbuf = &ringbuf;
|
|
irq_offload(tringbuf_put, (const void *)0);
|
|
irq_offload(tringbuf_put, (const void *)1);
|
|
irq_offload(tringbuf_get, (const void *)0);
|
|
irq_offload(tringbuf_get, (const void *)1);
|
|
irq_offload(tringbuf_put, (const void *)2);
|
|
zassert_false(ring_buf_is_empty(pbuf));
|
|
irq_offload(tringbuf_get, (const void *)2);
|
|
zassert_true(ring_buf_is_empty(pbuf));
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_put_get_thread_isr)
|
|
{
|
|
pbuf = &ringbuf;
|
|
tringbuf_put((const void *)0);
|
|
irq_offload(tringbuf_put, (const void *)1);
|
|
tringbuf_get((const void *)0);
|
|
irq_offload(tringbuf_get, (const void *)1);
|
|
tringbuf_put((const void *)2);
|
|
irq_offload(tringbuf_get, (const void *)2);
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_put_get_discard)
|
|
{
|
|
pbuf = &ringbuf;
|
|
tringbuf_put((const void *)0);
|
|
tringbuf_put((const void *)1);
|
|
zassert_false(ring_buf_is_empty(pbuf));
|
|
tringbuf_get_discard((const void *)0);
|
|
tringbuf_get_discard((const void *)1);
|
|
zassert_true(ring_buf_is_empty(pbuf));
|
|
}
|
|
|
|
/**
|
|
* @brief verify that ringbuffer can be placed in any user-controlled memory
|
|
*
|
|
* @details
|
|
* Test Objective:
|
|
* - define and initialize a ring buffer by macro RING_BUF_ITEM_DECLARE_POW2,
|
|
* then passing data by thread and isr to verify the ringbuffer
|
|
* if it works to be placed in any user-controlled memory.
|
|
*
|
|
* Testing techniques:
|
|
* - Interface testing
|
|
* - Dynamic analysis and testing
|
|
* - Structural test coverage(entry points,statements,branches)
|
|
*
|
|
* Prerequisite Conditions:
|
|
* - Define and initialize a ringbuffer by RING_BUF_ITEM_DECLARE_POW2
|
|
* - Define a pointer of ring_buffer type.
|
|
*
|
|
* Input Specifications:
|
|
* - N/A
|
|
*
|
|
* Test Procedure:
|
|
* -# Put data items into the ringbuffer by a thread
|
|
* -# Put data items into the ringbuffer by a ISR
|
|
* -# Get data items from the ringbuffer by the thread
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
* -# Get data items from the ringbuffer by the ISR
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
* -# Put data items into the ringbuffer by the thread
|
|
* -# Get data items from the ringbuffer by the ISR
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
*
|
|
* Expected Test Result:
|
|
* - data items pushed shall be equal to what are gotten.
|
|
*
|
|
* Pass/Fail Criteria:
|
|
* - Success if test result of step 4,6,9 is passed. Otherwise, failure.
|
|
*
|
|
* Assumptions and Constraints:
|
|
* - N/A
|
|
*
|
|
* @ingroup lib_ringbuffer_tests
|
|
*
|
|
* @see ring_buf_item_put, ring_buf_item_get
|
|
*/
|
|
ZTEST(ringbuffer_api, test_ringbuffer_pow2_put_get_thread_isr)
|
|
{
|
|
pbuf = &ringbuf_pow2;
|
|
tringbuf_put((const void *)0);
|
|
irq_offload(tringbuf_put, (const void *)1);
|
|
tringbuf_get((const void *)0);
|
|
irq_offload(tringbuf_get, (const void *)1);
|
|
tringbuf_put((const void *)1);
|
|
irq_offload(tringbuf_get, (const void *)1);
|
|
}
|
|
|
|
/**
|
|
* @brief verify that ringbuffer can be placed in any user-controlled memory
|
|
*
|
|
* @details
|
|
* Test Objective:
|
|
* - define and initialize a ring buffer by macro RING_BUF_ITEM_DECLARE,
|
|
* then passing data by thread and isr to verify the ringbuffer
|
|
* if it works to be placed in any user-controlled memory.
|
|
*
|
|
* Testing techniques:
|
|
* - Interface testing
|
|
* - Dynamic analysis and testing
|
|
* - Structural test coverage(entry points,statements,branches)
|
|
*
|
|
* Prerequisite Conditions:
|
|
* - Define and initialize a ringbuffer by RING_BUF_ITEM_DECLARE
|
|
* - Define a pointer of ring buffer type.
|
|
*
|
|
* Input Specifications:
|
|
* - N/A
|
|
*
|
|
* Test Procedure:
|
|
* -# Put data items into the ringbuffer by a thread
|
|
* -# Put data items into the ringbuffer by a ISR
|
|
* -# Get data items from the ringbuffer by the thread
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
* -# Get data items from the ringbuffer by the ISR
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
* -# Put data items into the ringbuffer by the thread
|
|
* -# Get data items from the ringbuffer by the ISR
|
|
* -# Check if data items pushed are equal to what are gotten.
|
|
*
|
|
* Expected Test Result:
|
|
* - data items pushed shall be equal to what are gotten.
|
|
*
|
|
* Pass/Fail Criteria:
|
|
* - Success if test result of step 4,6,9 is passed. Otherwise, failure.
|
|
*
|
|
* Assumptions and Constraints:
|
|
* - N/A
|
|
*
|
|
* @ingroup lib_ringbuffer_tests
|
|
*
|
|
* @see ring_buf_item_put, ring_buf_item_get
|
|
*/
|
|
ZTEST(ringbuffer_api, test_ringbuffer_size_put_get_thread_isr)
|
|
{
|
|
pbuf = &ringbuf_size;
|
|
tringbuf_put((const void *)0);
|
|
irq_offload(tringbuf_put, (const void *)1);
|
|
tringbuf_get((const void *)0);
|
|
irq_offload(tringbuf_get, (const void *)1);
|
|
tringbuf_put((const void *)2);
|
|
irq_offload(tringbuf_get, (const void *)2);
|
|
}
|
|
|
|
/**
|
|
* @brief verify that ringbuffer can be placed in any user-controlled memory
|
|
*
|
|
* @details
|
|
* Test Objective:
|
|
* - define and initialize a ring buffer by macro RING_BUF_DECLARE,
|
|
* then verify data is passed between ring buffer and array
|
|
*
|
|
* Testing techniques:
|
|
* - Interface testing
|
|
* - Dynamic analysis and testing
|
|
* - Structural test coverage(entry points,statements,branches)
|
|
*
|
|
* Prerequisite Conditions:
|
|
* - Define and initialize a ringbuffer by RING_BUF_DECLARE
|
|
*
|
|
* Input Specifications:
|
|
* - N/A
|
|
*
|
|
* Test Procedure:
|
|
* -# Define two arrays(inbuf,outbuf) and initialize inbuf
|
|
* -# Put and get data with "for loop"
|
|
* -# Check if data size pushed is equal to what are gotten.
|
|
* -# Then initialize the output buffer
|
|
* -# Put data with different size to check if data size
|
|
* pushed is equal to what are gotten.
|
|
*
|
|
* Expected Test Result:
|
|
* - data items pushed shall be equal to what are gotten.
|
|
*
|
|
* Pass/Fail Criteria:
|
|
* - Success if test result of step 4,5 is passed. Otherwise, failure.
|
|
*
|
|
* Assumptions and Constraints:
|
|
* - N/A
|
|
*
|
|
* @ingroup lib_ringbuffer_tests
|
|
*
|
|
* @see ring_buf_put, ring_buf_get
|
|
*/
|
|
ZTEST(ringbuffer_api, test_ringbuffer_raw)
|
|
{
|
|
int i;
|
|
uint8_t inbuf[RINGBUFFER_SIZE];
|
|
uint8_t outbuf[RINGBUFFER_SIZE];
|
|
size_t in_size;
|
|
size_t out_size;
|
|
|
|
/* Initialize test buffer. */
|
|
for (i = 0; i < RINGBUFFER_SIZE; i++) {
|
|
inbuf[i] = i;
|
|
}
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
memset(outbuf, 0, sizeof(outbuf));
|
|
in_size = ring_buf_put(&ringbuf_raw, inbuf,
|
|
RINGBUFFER_SIZE - 2);
|
|
out_size = ring_buf_get(&ringbuf_raw, outbuf,
|
|
RINGBUFFER_SIZE - 2);
|
|
|
|
zassert_true(in_size == RINGBUFFER_SIZE - 2);
|
|
zassert_true(in_size == out_size);
|
|
zassert_true(memcmp(inbuf, outbuf, RINGBUFFER_SIZE - 2) == 0,
|
|
NULL);
|
|
}
|
|
|
|
memset(outbuf, 0, sizeof(outbuf));
|
|
in_size = ring_buf_put(&ringbuf_raw, inbuf,
|
|
RINGBUFFER_SIZE);
|
|
zassert_equal(in_size, RINGBUFFER_SIZE);
|
|
|
|
in_size = ring_buf_put(&ringbuf_raw, inbuf,
|
|
1);
|
|
zassert_equal(in_size, 0);
|
|
|
|
out_size = ring_buf_get(&ringbuf_raw, outbuf,
|
|
RINGBUFFER_SIZE);
|
|
|
|
zassert_true(out_size == RINGBUFFER_SIZE);
|
|
|
|
out_size = ring_buf_get(&ringbuf_raw, outbuf,
|
|
RINGBUFFER_SIZE + 1);
|
|
zassert_true(out_size == 0);
|
|
zassert_true(ring_buf_is_empty(&ringbuf_raw));
|
|
|
|
/* Validate that raw bytes can be discarded */
|
|
in_size = ring_buf_put(&ringbuf_raw, inbuf,
|
|
RINGBUFFER_SIZE);
|
|
zassert_equal(in_size, RINGBUFFER_SIZE);
|
|
|
|
out_size = ring_buf_get(&ringbuf_raw, NULL,
|
|
RINGBUFFER_SIZE);
|
|
zassert_true(out_size == RINGBUFFER_SIZE);
|
|
|
|
out_size = ring_buf_get(&ringbuf_raw, NULL,
|
|
RINGBUFFER_SIZE + 1);
|
|
zassert_true(out_size == 0);
|
|
zassert_true(ring_buf_is_empty(&ringbuf_raw));
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_alloc_put)
|
|
{
|
|
uint8_t outputbuf[RINGBUFFER_SIZE];
|
|
uint8_t inputbuf[] = {1, 2, 3, 4};
|
|
uint32_t read_size;
|
|
uint32_t allocated;
|
|
uint8_t *data;
|
|
int err;
|
|
|
|
ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
|
|
|
|
allocated = ring_buf_put_claim(&ringbuf_raw, &data, 1);
|
|
zassert_true(allocated == 1U);
|
|
|
|
|
|
allocated = ring_buf_put_claim(&ringbuf_raw, &data,
|
|
RINGBUFFER_SIZE - 1);
|
|
zassert_true(allocated == RINGBUFFER_SIZE - 1);
|
|
|
|
/* Putting too much returns error */
|
|
err = ring_buf_put_finish(&ringbuf_raw, RINGBUFFER_SIZE + 1);
|
|
zassert_true(err != 0);
|
|
|
|
err = ring_buf_put_finish(&ringbuf_raw, 1);
|
|
zassert_true(err == 0);
|
|
|
|
err = ring_buf_put_finish(&ringbuf_raw, RINGBUFFER_SIZE - 1);
|
|
zassert_true(err == -EINVAL);
|
|
|
|
read_size = ring_buf_get(&ringbuf_raw, outputbuf,
|
|
RINGBUFFER_SIZE);
|
|
zassert_true(read_size == 1);
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
allocated = ring_buf_put_claim(&ringbuf_raw, &data, 2);
|
|
if (allocated == 2U) {
|
|
data[0] = inputbuf[0];
|
|
data[1] = inputbuf[1];
|
|
} else {
|
|
data[0] = inputbuf[0];
|
|
ring_buf_put_claim(&ringbuf_raw, &data, 1);
|
|
data[0] = inputbuf[1];
|
|
}
|
|
|
|
allocated = ring_buf_put_claim(&ringbuf_raw, &data, 2);
|
|
if (allocated == 2U) {
|
|
data[0] = inputbuf[2];
|
|
data[1] = inputbuf[3];
|
|
} else {
|
|
data[0] = inputbuf[2];
|
|
ring_buf_put_claim(&ringbuf_raw, &data, 1);
|
|
data[0] = inputbuf[3];
|
|
}
|
|
|
|
err = ring_buf_put_finish(&ringbuf_raw, 4);
|
|
zassert_true(err == 0);
|
|
|
|
read_size = ring_buf_get(&ringbuf_raw,
|
|
outputbuf, 4);
|
|
zassert_true(read_size == 4U);
|
|
|
|
zassert_true(memcmp(outputbuf, inputbuf, 4) == 0);
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_byte_put_free)
|
|
{
|
|
uint8_t indata[] = {1, 2, 3, 4, 5};
|
|
int err;
|
|
uint32_t granted;
|
|
uint8_t *data;
|
|
|
|
ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
|
|
|
|
/* Ring buffer is empty */
|
|
granted = ring_buf_get_claim(&ringbuf_raw, &data, RINGBUFFER_SIZE);
|
|
zassert_true(granted == 0U);
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
ring_buf_put(&ringbuf_raw, indata,
|
|
RINGBUFFER_SIZE-2);
|
|
|
|
granted = ring_buf_get_claim(&ringbuf_raw, &data,
|
|
RINGBUFFER_SIZE);
|
|
|
|
if (granted == (RINGBUFFER_SIZE-2)) {
|
|
zassert_true(memcmp(indata, data, granted) == 0);
|
|
} else if (granted < (RINGBUFFER_SIZE-2)) {
|
|
/* When buffer wraps, operation is split. */
|
|
uint32_t granted_1 = granted;
|
|
|
|
zassert_true(memcmp(indata, data, granted) == 0);
|
|
granted = ring_buf_get_claim(&ringbuf_raw, &data,
|
|
RINGBUFFER_SIZE);
|
|
|
|
zassert_true((granted + granted_1) ==
|
|
RINGBUFFER_SIZE - 2, NULL);
|
|
zassert_true(memcmp(&indata[granted_1], data, granted)
|
|
== 0, NULL);
|
|
} else {
|
|
zassert_true(false);
|
|
}
|
|
|
|
/* Freeing more than possible case. */
|
|
err = ring_buf_get_finish(&ringbuf_raw, RINGBUFFER_SIZE-1);
|
|
zassert_true(err != 0);
|
|
|
|
err = ring_buf_get_finish(&ringbuf_raw, RINGBUFFER_SIZE-2);
|
|
zassert_true(err == 0);
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_capacity)
|
|
{
|
|
uint32_t capacity;
|
|
|
|
ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
|
|
|
|
capacity = ring_buf_capacity_get(&ringbuf_raw);
|
|
zassert_equal(RINGBUFFER_SIZE, capacity,
|
|
"Unexpected capacity");
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_size)
|
|
{
|
|
uint32_t size;
|
|
static uint8_t buf[RINGBUFFER_SIZE];
|
|
|
|
ring_buf_init(&ringbuf_raw, sizeof(buf), ringbuf_raw.buffer);
|
|
|
|
/* Test 0 */
|
|
size = ring_buf_size_get(&ringbuf_raw);
|
|
zassert_equal(0, size, "wrong size: exp: %u act: %u", 0, size);
|
|
|
|
/* Test 1 */
|
|
ring_buf_put(&ringbuf_raw, "x", 1);
|
|
size = ring_buf_size_get(&ringbuf_raw);
|
|
zassert_equal(1, size, "wrong size: exp: %u act: %u", 1, size);
|
|
|
|
/* Test N */
|
|
ring_buf_reset(&ringbuf_raw);
|
|
ring_buf_put(&ringbuf_raw, buf, sizeof(buf));
|
|
size = ring_buf_size_get(&ringbuf_raw);
|
|
zassert_equal(sizeof(buf), size, "wrong size: exp: %u: actual: %u", sizeof(buf), size);
|
|
|
|
/* Test N - 2 with wrap-around */
|
|
ring_buf_put(&ringbuf_raw, buf, sizeof(buf));
|
|
ring_buf_get(&ringbuf_raw, NULL, 3);
|
|
ring_buf_put(&ringbuf_raw, "x", 1);
|
|
|
|
size = ring_buf_size_get(&ringbuf_raw);
|
|
zassert_equal(sizeof(buf) - 2, size, "wrong size: exp: %u: actual: %u", sizeof(buf) - 2,
|
|
size);
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_peek)
|
|
{
|
|
uint32_t size;
|
|
uint8_t byte = 0x42;
|
|
static uint8_t buf[RINGBUFFER_SIZE];
|
|
|
|
ring_buf_init(&ringbuf_raw, sizeof(buf), ringbuf_raw.buffer);
|
|
|
|
/* Test 0 */
|
|
size = ring_buf_peek(&ringbuf_raw, (uint8_t *)0x1, 42424242);
|
|
zassert_equal(0, size, "wrong peek size: exp: %u: actual: %u", 0, size);
|
|
|
|
/* Test 1 */
|
|
ring_buf_put(&ringbuf_raw, "*", 1);
|
|
size = ring_buf_peek(&ringbuf_raw, &byte, 1);
|
|
zassert_equal(1, size, "wrong peek size: exp: %u: actual: %u", 1, size);
|
|
zassert_equal('*', byte, "wrong buffer contents: exp: %u: actual: %u", '*', byte);
|
|
size = ring_buf_size_get(&ringbuf_raw);
|
|
zassert_equal(1, size, "wrong buffer size: exp: %u: actual: %u", 1, size);
|
|
|
|
/* Test N */
|
|
ring_buf_reset(&ringbuf_raw);
|
|
for (size = 0; size < sizeof(buf); ++size) {
|
|
buf[size] = 'A' + (size % ('Z' - 'A' + 1));
|
|
}
|
|
|
|
ring_buf_put(&ringbuf_raw, buf, sizeof(buf));
|
|
memset(buf, '*', sizeof(buf)); /* fill with pattern */
|
|
|
|
size = ring_buf_peek(&ringbuf_raw, buf, sizeof(buf));
|
|
zassert_equal(sizeof(buf), size, "wrong peek size: exp: %u: actual: %u", sizeof(buf), size);
|
|
size = ring_buf_size_get(&ringbuf_raw);
|
|
zassert_equal(sizeof(buf), size, "wrong buffer size: exp: %u: actual: %u", sizeof(buf),
|
|
size);
|
|
|
|
for (size = 0; size < sizeof(buf); ++size) {
|
|
ringbuf_raw.buffer[size] = 'A' + (size % ('Z' - 'A' + 1));
|
|
}
|
|
|
|
zassert_equal(0, memcmp(buf, ringbuf_raw.buffer, sizeof(buf)),
|
|
"content validation failed");
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_reset)
|
|
{
|
|
uint8_t indata[] = {1, 2, 3, 4, 5};
|
|
uint8_t outdata[RINGBUFFER_SIZE];
|
|
uint8_t *outbuf;
|
|
uint32_t len;
|
|
uint32_t out_len;
|
|
uint32_t granted;
|
|
uint32_t space;
|
|
|
|
ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
|
|
|
|
len = 3;
|
|
out_len = ring_buf_put(&ringbuf_raw, indata, len);
|
|
zassert_equal(out_len, len);
|
|
|
|
out_len = ring_buf_get(&ringbuf_raw, outdata, len);
|
|
zassert_equal(out_len, len);
|
|
|
|
space = ring_buf_space_get(&ringbuf_raw);
|
|
zassert_equal(space, RINGBUFFER_SIZE);
|
|
|
|
/* Even though ringbuffer is empty, full buffer cannot be allocated
|
|
* because internal pointers are not at the beginning.
|
|
*/
|
|
granted = ring_buf_put_claim(&ringbuf_raw, &outbuf, RINGBUFFER_SIZE);
|
|
zassert_false(granted == RINGBUFFER_SIZE);
|
|
|
|
/* After reset full buffer can be allocated. */
|
|
ring_buf_reset(&ringbuf_raw);
|
|
granted = ring_buf_put_claim(&ringbuf_raw, &outbuf, RINGBUFFER_SIZE);
|
|
zassert_true(granted == RINGBUFFER_SIZE);
|
|
}
|
|
|
|
static uint32_t ringbuf_stored[RINGBUFFER_SIZE];
|
|
|
|
/**
|
|
* @brief verify the array stored by ringbuf
|
|
*
|
|
* @details
|
|
* Test Objective:
|
|
* - Define a buffer stored by ringbuffer. Verify that the address
|
|
* of the buffer is contiguous.And also verify that data can pass
|
|
* between buffer and ringbuffer.
|
|
*
|
|
* Testing techniques:
|
|
* - Interface testing
|
|
* - Dynamic analysis and testing
|
|
* - Structural test coverage(entry points,statements,branches)
|
|
*
|
|
* Prerequisite Conditions:
|
|
* - Define an array that changes as the system changes.
|
|
*
|
|
* Input Specifications:
|
|
* - N/A
|
|
*
|
|
* Test Procedure:
|
|
* -# Define two buffers(input and output)
|
|
* -# Put data from input buffer into the ringbuffer
|
|
* and check if put data are successful.
|
|
* -# Check if the address stored by ringbuf is contiguous.
|
|
* -# Get data from the ringbuffer and put them into output buffer
|
|
* and check if getting data are successful.
|
|
*
|
|
* Expected Test Result:
|
|
* - All assertions can pass.
|
|
*
|
|
* Pass/Fail Criteria:
|
|
* - Success if test result of step 2,3,4,5 is passed. Otherwise, failure.
|
|
*
|
|
* Assumptions and Constraints:
|
|
* - N/A
|
|
*
|
|
* @ingroup lib_ringbuffer_tests
|
|
*
|
|
* @see ring_buf_item_put, ring_buf_item_get
|
|
*/
|
|
ZTEST(ringbuffer_api, test_ringbuffer_array_perf)
|
|
{
|
|
struct ring_buf buf_ii;
|
|
uint32_t input[3] = {0xaa, 0xbb, 0xcc};
|
|
uint32_t output[3] = {0};
|
|
uint16_t type = 0;
|
|
uint8_t value = 0, size = 3;
|
|
|
|
ring_buf_item_init(&buf_ii, RINGBUFFER_SIZE, ringbuf_stored);
|
|
|
|
/*Data from the beginning of the array can be copied into the ringbuf*/
|
|
zassert_true(ring_buf_item_put(&buf_ii, 1, 2, input, 3) == 0);
|
|
|
|
/*Verify the address stored by ringbuf is contiguous*/
|
|
for (int i = 0; i < 3; i++) {
|
|
uint32_t *buf32 = (uint32_t *)buf_ii.buffer;
|
|
|
|
zassert_equal(input[i], buf32[i+1]);
|
|
}
|
|
|
|
/*Data from the end of the ringbuf can be copied into the array*/
|
|
zassert_true(ring_buf_item_get(&buf_ii, &type, &value,
|
|
output, &size) == 0, NULL);
|
|
|
|
/*Verify the ringbuf defined is working*/
|
|
for (int i = 0; i < 3; i++) {
|
|
zassert_equal(input[i], output[i]);
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_partial_putting)
|
|
{
|
|
uint8_t indata[RINGBUFFER_SIZE];
|
|
uint8_t outdata[RINGBUFFER_SIZE];
|
|
uint32_t len;
|
|
uint32_t len2;
|
|
uint32_t req_len;
|
|
uint8_t *ptr;
|
|
|
|
ring_buf_reset(&ringbuf_raw);
|
|
|
|
for (int i = 0; i < 100; i++) {
|
|
req_len = (i % RINGBUFFER_SIZE) + 1;
|
|
len = ring_buf_put(&ringbuf_raw, indata, req_len);
|
|
zassert_equal(req_len, len);
|
|
|
|
len = ring_buf_get(&ringbuf_raw, outdata, req_len);
|
|
zassert_equal(req_len, len);
|
|
|
|
req_len = 2;
|
|
len = ring_buf_put_claim(&ringbuf_raw, &ptr, req_len);
|
|
zassert_equal(len, req_len);
|
|
|
|
req_len = RINGBUFFER_SIZE;
|
|
len = ring_buf_put_claim(&ringbuf_raw, &ptr, req_len);
|
|
len2 = ring_buf_put_claim(&ringbuf_raw, &ptr, req_len);
|
|
zassert_equal(len + len2, req_len - 2);
|
|
|
|
ring_buf_put_finish(&ringbuf_raw, req_len);
|
|
|
|
len = ring_buf_get(&ringbuf_raw, indata, req_len);
|
|
zassert_equal(len, req_len);
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_partial_getting)
|
|
{
|
|
uint8_t indata[RINGBUFFER_SIZE];
|
|
uint8_t outdata[RINGBUFFER_SIZE];
|
|
uint32_t len;
|
|
uint32_t len2;
|
|
uint32_t req_len;
|
|
uint8_t *ptr;
|
|
|
|
ring_buf_reset(&ringbuf_raw);
|
|
|
|
for (int i = 0; i < 100; i++) {
|
|
req_len = (i % RINGBUFFER_SIZE) + 1;
|
|
len = ring_buf_put(&ringbuf_raw, indata, req_len);
|
|
zassert_equal(req_len, len);
|
|
|
|
len = ring_buf_get(&ringbuf_raw, outdata, req_len);
|
|
zassert_equal(req_len, len);
|
|
|
|
req_len = sizeof(indata);
|
|
len = ring_buf_put(&ringbuf_raw, indata, req_len);
|
|
zassert_equal(req_len, len);
|
|
|
|
len = ring_buf_get_claim(&ringbuf_raw, &ptr, 2);
|
|
zassert_equal(len, 2);
|
|
|
|
len = ring_buf_get_claim(&ringbuf_raw, &ptr, RINGBUFFER_SIZE);
|
|
len2 = ring_buf_get_claim(&ringbuf_raw, &ptr, RINGBUFFER_SIZE);
|
|
zassert_equal(len + len2, RINGBUFFER_SIZE - 2);
|
|
|
|
ring_buf_get_finish(&ringbuf_raw, RINGBUFFER_SIZE);
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_equal_bufs)
|
|
{
|
|
struct ring_buf buf_ii;
|
|
uint8_t *data;
|
|
uint32_t claimed;
|
|
uint8_t buf[8];
|
|
size_t halfsize = sizeof(buf)/2;
|
|
|
|
ring_buf_init(&buf_ii, sizeof(buf), buf);
|
|
|
|
for (int i = 0; i < 100; i++) {
|
|
claimed = ring_buf_put_claim(&buf_ii, &data, halfsize);
|
|
zassert_equal(claimed, halfsize);
|
|
ring_buf_put_finish(&buf_ii, claimed);
|
|
|
|
claimed = ring_buf_get_claim(&buf_ii, &data, halfsize);
|
|
zassert_equal(claimed, halfsize);
|
|
ring_buf_get_finish(&buf_ii, claimed);
|
|
}
|
|
}
|
|
|
|
ZTEST(ringbuffer_api, test_ringbuffer_performance)
|
|
{
|
|
uint8_t buf[16];
|
|
static struct ring_buf rbuf;
|
|
uint8_t indata[16];
|
|
uint8_t outdata[16];
|
|
uint8_t *ptr;
|
|
uint32_t timestamp;
|
|
int loop = 1000;
|
|
|
|
ring_buf_init(&rbuf, sizeof(buf), buf);
|
|
|
|
/* Test performance of copy put get 1 byte */
|
|
timestamp = k_cycle_get_32();
|
|
for (int i = 0; i < loop; i++) {
|
|
ring_buf_put(&rbuf, indata, 1);
|
|
ring_buf_get(&rbuf, outdata, 1);
|
|
}
|
|
timestamp = k_cycle_get_32() - timestamp;
|
|
PRINT("1 byte put-get, avg cycles: %d\n", timestamp/loop);
|
|
|
|
/* Test performance of copy put get 1 byte */
|
|
ring_buf_reset(&rbuf);
|
|
timestamp = k_cycle_get_32();
|
|
for (int i = 0; i < loop; i++) {
|
|
ring_buf_put(&rbuf, indata, 4);
|
|
ring_buf_get(&rbuf, outdata, 4);
|
|
}
|
|
timestamp = k_cycle_get_32() - timestamp;
|
|
PRINT("4 byte put-get, avg cycles: %d\n", timestamp/loop);
|
|
|
|
/* Test performance of put claim finish 1 byte */
|
|
ring_buf_reset(&rbuf);
|
|
timestamp = k_cycle_get_32();
|
|
for (int i = 0; i < loop; i++) {
|
|
ring_buf_put_claim(&rbuf, &ptr, 1);
|
|
ring_buf_put_finish(&rbuf, 1);
|
|
ring_buf_get(&rbuf, outdata, 1);
|
|
}
|
|
timestamp = k_cycle_get_32() - timestamp;
|
|
PRINT("1 byte put claim-finish, avg cycles: %d\n", timestamp/loop);
|
|
|
|
/* Test performance of put claim finish 5 byte */
|
|
ring_buf_reset(&rbuf);
|
|
timestamp = k_cycle_get_32();
|
|
for (int i = 0; i < loop; i++) {
|
|
ring_buf_put_claim(&rbuf, &ptr, 5);
|
|
ring_buf_put_finish(&rbuf, 5);
|
|
ring_buf_get(&rbuf, outdata, 5);
|
|
}
|
|
timestamp = k_cycle_get_32() - timestamp;
|
|
PRINT("5 byte put claim-finish, avg cycles: %d\n", timestamp/loop);
|
|
|
|
/* Test performance of copy put claim finish 5 byte */
|
|
ring_buf_reset(&rbuf);
|
|
timestamp = k_cycle_get_32();
|
|
for (int i = 0; i < loop; i++) {
|
|
ring_buf_put(&rbuf, indata, 5);
|
|
ring_buf_get_claim(&rbuf, &ptr, 5);
|
|
ring_buf_get_finish(&rbuf, 5);
|
|
}
|
|
timestamp = k_cycle_get_32() - timestamp;
|
|
PRINT("5 byte get claim-finish, avg cycles: %d\n", timestamp/loop);
|
|
}
|
|
|
|
/*test case main entry*/
|
|
ZTEST_SUITE(ringbuffer_api, NULL, NULL, NULL, NULL, NULL);
|