Files
bacnet_stack/src/bacnet/basic/sys/ringbuf.c
T
Steve Karg d50c190957 Issue 2 move folders and use deep path include file names to prevent collisions (#4)
* moving folders and files and adjust server demo build

* Fix Makefile for apps/server on Linux

* fix unit test source file folders

* fix datetime convert UTC functions. Add Code::Blocks project for datetime testing

* added some ignore extensions

* disable parallel make option

* fix build for abort, dcc, and epics apps

* fix build for dcc, epics, error, and getevent apps.

* Fixed building of all apps

* fix the ipv4 to ipv6 router app build

* Change indent style from Google to Webkit

* make pretty to re-format style

* removed common Makefile since we already had one and two was too many

* remove scripts from root folder that are no longer maintained or used

* remove mercurial EOL and ignore files for git repo

* remove .vscodeconfig files from repo

* tweak clang-format style

* clang-format src and apps with tweaked style

* added clang-tidy to fix readability if braces in src

* result of make tidy for src and apps

* fix clang-tidy mangling

* Added code::blocks project for BACnet server simulation

* added code::blocks linux project for WhoIs app

* update text files for EOL

* fix EOL in some files

* fixed make win32 apps for older gcc

* Removed Borland C++ Makefile in apps. Unable to maintain support for Borland C++ compiler.

* created codeblocks project for apps/epics for Windows

* fixing ports/xplained to work with new data structure.

* fix ports/xplained example for Atmel Studio compile

* fix ports/stm32f10x example for gcc Makefile compile

* fix ports/stm32f10x example for IAR EWARM compile

* fix ports/xplained timer callback

* fix ports/bdk_atxx_mspt build with subdirs

* fix ports/bdk_atxx_mspt build with subdirs

* updated git ignore for IAR build artifacts

* updated gitignore for non-tracked files and folders

* fixed bdk-atxx4-mstp port for Rowley Crossworks project file

* fixed bdk-atxx4-mstp port for GCC AVR Makefile

* fixed atmega168 port for IAR AVR and GCC AVR Makefile

* fixed at91sam7s port for IAR ARM and GCC ARM Makefile

* removed unmaintainable DOS, RTOS32, and atmega8 ports.  Updated rx62n (untested).

* changed arm7 to uip port
2019-12-13 15:19:10 -06:00

824 lines
25 KiB
C

/**
* @file
* @author Steve Karg
* @date 2004
* @brief Generic ring buffer library for deeply embedded system.
*
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic ring buffer library for deeply embedded system.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
* It uses separate variables for consumer and producer so it can
* be used in multithreaded environment.
*
* See the unit tests for usage examples.
*
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/basic/sys/ringbuf.h"
/**
* Returns the number of elements in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return Number of elements in the ring buffer
*/
unsigned Ringbuf_Count(RING_BUFFER const *b)
{
unsigned head, tail; /* used to avoid volatile decision */
if (b) {
head = b->head;
tail = b->tail;
return head - tail;
}
return 0;
}
/**
* Returns the empty/full status of the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return true if the ring buffer is full, false if it is not.
*/
bool Ringbuf_Full(RING_BUFFER const *b)
{
return (b ? (Ringbuf_Count(b) == b->element_count) : true);
}
/**
* Returns the empty/full status of the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return true if the ring buffer is empty, false if it is not.
*/
bool Ringbuf_Empty(RING_BUFFER const *b)
{
return (b ? (Ringbuf_Count(b) == 0) : true);
}
/**
* Updates the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
*/
static void Ringbuf_Depth_Update(RING_BUFFER *b)
{
unsigned count;
if (b) {
count = Ringbuf_Count(b);
if (count > b->depth) {
b->depth = count;
}
}
}
/**
* Updates the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
unsigned Ringbuf_Depth(RING_BUFFER const *b)
{
unsigned depth = 0;
if (b) {
depth = b->depth;
}
return depth;
}
/**
* Resets the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
unsigned Ringbuf_Depth_Reset(RING_BUFFER *b)
{
unsigned depth = 0;
if (b) {
depth = b->depth;
b->depth = 0;
}
return depth;
}
/**
* Gets the capacity of the ring buffer (number of possible elements)
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
unsigned Ringbuf_Size(RING_BUFFER const *b)
{
unsigned count = 0;
if (b) {
count = b->element_count;
}
return count;
}
/**
* Looks at the data from the head of the list without removing it
*
* @param b - pointer to RING_BUFFER structure
* @return pointer to the data, or NULL if nothing in the list
*/
volatile uint8_t *Ringbuf_Peek(RING_BUFFER const *b)
{
volatile uint8_t *data_element = NULL; /* return value */
if (!Ringbuf_Empty(b)) {
data_element = b->buffer;
data_element += ((b->tail % b->element_count) * b->element_size);
}
return data_element;
}
/**
* Looks at the data from the next element of the list without removing it
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - find the next element from this one
* @return pointer to the data, or NULL if nothing in the list
*/
volatile uint8_t *Ringbuf_Peek_Next(RING_BUFFER const *b, uint8_t *data_element)
{
unsigned index; /* list index */
volatile uint8_t *this_element;
volatile uint8_t *next_element = NULL; /* return value */
if (!Ringbuf_Empty(b) && data_element != NULL) {
/* Use (b->head-1) here to avoid walking off end of ring */
for (index = b->tail; index < b->head - 1; index++) {
/* Find the specified data_element */
this_element =
b->buffer + ((index % b->element_count) * b->element_size);
if (data_element == this_element) {
/* Found the current element, get the next one on the list */
next_element = b->buffer +
(((index + 1) % b->element_count) * b->element_size);
break;
}
}
}
return next_element;
}
/**
* Copy the data from the front of the list, and removes it
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - element of data that is loaded with data from ring
* @return true if data was copied, false if list is empty
*/
bool Ringbuf_Pop(RING_BUFFER *b, uint8_t *data_element)
{
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
unsigned i; /* loop counter */
if (!Ringbuf_Empty(b)) {
ring_data = b->buffer;
ring_data += ((b->tail % b->element_count) * b->element_size);
if (data_element) {
for (i = 0; i < b->element_size; i++) {
data_element[i] = ring_data[i];
}
}
b->tail++;
status = true;
}
return status;
}
/**
* Copy the data from the specified element, and removes it and moves other
* elements up the list
*
* @param b - pointer to RING_BUFFER structure
* @param this_element - element to find
* @param data_element - element of data that is loaded with data from ring
* @return true if data was copied, false if list is empty
*/
bool Ringbuf_Pop_Element(
RING_BUFFER *b, uint8_t *this_element, uint8_t *data_element)
{
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
volatile uint8_t *prev_data;
unsigned index; /* list index */
unsigned this_index = b->head; /* index of element to remove */
unsigned i; /* loop counter */
if (!Ringbuf_Empty(b) && this_element != NULL) {
for (index = b->tail; index < b->head; index++) {
/* Find the specified data_element */
ring_data =
b->buffer + ((index % b->element_count) * b->element_size);
if (this_element == ring_data) {
/* Found the specified element, copy the data if required */
this_index = index;
if (data_element) {
for (i = 0; i < b->element_size; i++) {
data_element[i] = ring_data[i];
}
}
break;
}
}
if (this_index < b->head) {
/* Found a match, move elements up the list to fill the gap */
for (index = this_index; index > b->tail; index--) {
/* Get pointers to current and previous data_elements */
ring_data =
b->buffer + ((index % b->element_count) * b->element_size);
prev_data = b->buffer +
(((index - 1) % b->element_count) * b->element_size);
for (i = 0; i < b->element_size; i++) {
ring_data[i] = prev_data[i];
}
}
}
b->tail++;
status = true;
}
return status;
}
/**
* Adds an element of data to the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - one element that is copied to the ring buffer
* @return true on succesful add, false if not added
*/
bool Ringbuf_Put(RING_BUFFER *b, uint8_t *data_element)
{
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
unsigned i; /* loop counter */
if (b && data_element) {
/* limit the amount of elements that we accept */
if (!Ringbuf_Full(b)) {
ring_data = b->buffer;
ring_data += ((b->head % b->element_count) * b->element_size);
for (i = 0; i < b->element_size; i++) {
ring_data[i] = data_element[i];
}
b->head++;
Ringbuf_Depth_Update(b);
status = true;
}
}
return status;
}
/**
* Adds an element of data to the front of the ring buffer
*
* Note that this function moves the tail on add instead of head,
* so this function cannot be used if you are keeping producer and
* consumer as separate processes (i.e. interrupt handlers)
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - one element to copy to the front of the ring
* @return true on succesful add, false if not added
*/
bool Ringbuf_Put_Front(RING_BUFFER *b, uint8_t *data_element)
{
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
unsigned i = 0; /* loop counter */
if (b && data_element) {
/* limit the amount of elements that we accept */
if (!Ringbuf_Full(b)) {
b->tail--;
ring_data = b->buffer;
ring_data += ((b->tail % b->element_count) * b->element_size);
/* copy the data to the ring data element */
for (i = 0; i < b->element_size; i++) {
ring_data[i] = data_element[i];
}
Ringbuf_Depth_Update(b);
status = true;
}
}
return status;
}
/**
* Gets a pointer to the next free data element of the buffer
* without adding it to the ring.
*
* @param b - pointer to RING_BUFFER structure
* @return pointer to the next data element, or NULL if the list is full
*/
volatile uint8_t *Ringbuf_Data_Peek(RING_BUFFER *b)
{
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
if (b) {
/* limit the amount of elements that we accept */
if (!Ringbuf_Full(b)) {
ring_data = b->buffer;
ring_data += ((b->head % b->element_count) * b->element_size);
}
}
return ring_data;
}
/**
* Adds the previously peeked element of data to the end of the
* ring buffer.
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - pointer to the peeked data element
* @return true if the buffer has space and the data element points to the
* same memory previously peeked.
*/
bool Ringbuf_Data_Put(RING_BUFFER *b, volatile uint8_t *data_element)
{
bool status = false;
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
if (b) {
/* limit the amount of elements that we accept */
if (!Ringbuf_Full(b)) {
ring_data = b->buffer;
ring_data += ((b->head % b->element_count) * b->element_size);
if (ring_data == data_element) {
/* same chunk of memory - okay to signal the head */
b->head++;
Ringbuf_Depth_Update(b);
status = true;
}
}
}
return status;
}
/**
* Test that the parameter is a power of two.
*
* @param x unsigned integer value to be tested
*
* @return true if the parameter is a power of 2
*/
static bool isPowerOfTwo(unsigned int x)
{
/* First x in the below expression is for the case when x is 0 */
return x && (!(x & (x - 1)));
}
/**
* Configures the ring buffer data buffer. Note that the element_count
* parameter must be a power of two.
*
* @param b - pointer to RING_BUFFER structure
* @param buffer - pointer to a data buffer that is used to store the ring data
* @param element_size - size of one element in the data block
* @param element_count - number elements in the data block
*
* @return true if ring buffer was initialized
*/
bool Ringbuf_Init(RING_BUFFER *b,
volatile uint8_t *buffer,
unsigned element_size,
unsigned element_count)
{
bool status = false;
if (b && isPowerOfTwo(element_count)) {
b->head = 0;
b->tail = 0;
b->buffer = buffer;
b->element_size = element_size;
b->element_count = element_count;
/* tuning diagnostics */
b->depth = 0;
status = true;
}
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include <limits.h>
#include "ctest.h"
/**
* Unit Test for the ring buffer
*
* @param pTest - test tracking pointer
* @param test_buffer - pointer to RING_BUFFER structure
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static void testRingAroundBuffer(Test *pTest,
RING_BUFFER *test_buffer,
uint8_t *data_element,
unsigned element_size,
unsigned element_count)
{
volatile uint8_t *test_data;
unsigned index;
unsigned data_index;
unsigned count;
uint8_t value;
bool status;
ct_test(pTest, Ringbuf_Empty(test_buffer));
/* test the ring around the buffer */
for (index = 0; index < element_count; index++) {
for (count = 1; count < 4; count++) {
value = (index * count) % 255;
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = value;
}
status = Ringbuf_Put(test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, Ringbuf_Count(test_buffer) == count);
}
for (count = 1; count < 4; count++) {
value = (index * count) % 255;
test_data = Ringbuf_Peek(test_buffer);
ct_test(pTest, test_data);
if (test_data) {
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == value);
}
}
status = Ringbuf_Pop(test_buffer, NULL);
ct_test(pTest, status == true);
}
}
ct_test(pTest, Ringbuf_Empty(test_buffer));
}
/**
* Unit Test for the ring buffer
*
* @param pTest - test tracking pointer
* @param data_store - buffer to store elements
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static bool testRingBuf(Test *pTest,
uint8_t *data_store,
uint8_t *data_element,
unsigned element_size,
unsigned element_count)
{
RING_BUFFER test_buffer;
volatile uint8_t *test_data;
unsigned index;
unsigned data_index;
bool status;
status =
Ringbuf_Init(&test_buffer, data_store, element_size, element_count);
if (!status) {
return false;
}
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 0);
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = data_index;
}
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 1);
test_data = Ringbuf_Peek(&test_buffer);
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == data_element[data_index]);
}
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
(void)Ringbuf_Pop(&test_buffer, NULL);
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 1);
/* fill to max */
for (index = 0; index < element_count; index++) {
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = index;
}
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == (index + 1));
}
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
/* verify actions on full buffer */
for (index = 0; index < element_count; index++) {
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = index;
}
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == false);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
}
/* check buffer full */
for (index = 0; index < element_count; index++) {
test_data = Ringbuf_Peek(&test_buffer);
ct_test(pTest, test_data);
if (test_data) {
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == index);
}
}
(void)Ringbuf_Pop(&test_buffer, NULL);
}
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
Ringbuf_Depth_Reset(&test_buffer);
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 0);
testRingAroundBuffer(
pTest, &test_buffer, data_element, element_size, element_count);
/* adjust the internal index of Ringbuf to test unsigned wrapping */
test_buffer.head = UINT_MAX - 1;
test_buffer.tail = UINT_MAX - 1;
testRingAroundBuffer(
pTest, &test_buffer, data_element, element_size, element_count);
return true;
}
/**
* Unit Test for the ring buffer with 16 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeSmall(Test *pTest)
{
bool status;
uint8_t data_element[5];
uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)];
status = testRingBuf(pTest, data_store, data_element, sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status);
}
/**
* Unit Test for the ring buffer with 32 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeLarge(Test *pTest)
{
bool status;
uint8_t data_element[16];
uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(99)];
status = testRingBuf(pTest, data_store, data_element, sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status);
}
/**
* Unit Test for the ring buffer with 32 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeInvalid(Test *pTest)
{
bool status;
uint8_t data_element[16];
uint8_t data_store[sizeof(data_element) * 99];
status = testRingBuf(pTest, data_store, data_element, sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status == false);
}
void testRingBufPowerOfTwo(Test *pTest)
{
ct_test(pTest, NEXT_POWER_OF_2(3) == 4);
ct_test(pTest, NEXT_POWER_OF_2(100) == 128);
ct_test(pTest, NEXT_POWER_OF_2(127) == 128);
ct_test(pTest, NEXT_POWER_OF_2(128) == 128);
ct_test(pTest, NEXT_POWER_OF_2(129) == 256);
ct_test(pTest, NEXT_POWER_OF_2(300) == 512);
ct_test(pTest, NEXT_POWER_OF_2(500) == 512);
}
/**
* Unit Test for the ring buffer peek/pop next element
*
* @param pTest - test tracking pointer
* @param data_store - buffer to store elements
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static bool testRingBufNextElement(Test *pTest,
uint8_t *data_store,
uint8_t *data_element,
unsigned element_size,
unsigned element_count)
{
RING_BUFFER test_buffer;
volatile uint8_t *test_data;
unsigned index;
unsigned data_index;
bool status;
status =
Ringbuf_Init(&test_buffer, data_store, element_size, element_count);
if (!status) {
return false;
}
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 0);
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = data_index;
}
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 1);
test_data = Ringbuf_Peek(&test_buffer);
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == data_element[data_index]);
}
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
(void)Ringbuf_Pop(&test_buffer, NULL);
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 1);
/* fill to max */
for (index = 0; index < element_count; index++) {
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = index;
}
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == (index + 1));
}
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count);
/* Walk through ring buffer */
test_data = Ringbuf_Peek(&test_buffer);
ct_test(pTest, test_data);
for (index = 1; index < element_count; index++) {
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
ct_test(pTest, test_data);
if (test_data) {
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == index);
}
}
}
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count);
/* Try to walk off end of buffer - should return NULL */
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
ct_test(pTest, (test_data == NULL));
/* Walk through ring buffer and pop alternate elements */
test_data = Ringbuf_Peek(&test_buffer);
ct_test(pTest, test_data);
for (index = 1; index < element_count / 2; index++) {
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
ct_test(pTest, test_data);
(void)Ringbuf_Pop_Element(&test_buffer, (uint8_t *)test_data, NULL);
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
}
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count / 2 + 1);
/* Walk through ring buffer and check data */
test_data = Ringbuf_Peek(&test_buffer);
ct_test(pTest, test_data);
for (index = 0; index < element_count / 2; index++) {
if (test_data) {
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == index * 2);
}
}
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
ct_test(pTest, test_data);
}
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count / 2 + 1);
return true;
}
/**
* Unit Test for the ring buffer with 16 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufNextElementSizeSmall(Test *pTest)
{
bool status;
uint8_t data_element[5];
uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)];
status = testRingBufNextElement(pTest, data_store, data_element,
sizeof(data_element), sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status);
}
#ifdef TEST_RING_BUFFER
/**
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("Ring Buffer", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testRingBufPowerOfTwo);
assert(rc);
rc = ct_addTestFunction(pTest, testRingBufSizeSmall);
assert(rc);
rc = ct_addTestFunction(pTest, testRingBufSizeLarge);
assert(rc);
rc = ct_addTestFunction(pTest, testRingBufSizeInvalid);
assert(rc);
rc = ct_addTestFunction(pTest, testRingBufNextElementSizeSmall);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif