From 7261d40214a19f0d3b4997a0aa72d5c427694ff4 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Sun, 1 Jan 2017 06:20:13 +0100 Subject: [PATCH] [r3089] Updated ringbuffer library to remove alloc and include data-peek and data-put. --- include/ringbuf.h | 122 ++++++------ src/ringbuf.c | 484 +++++++++++++++++++++++++++++++--------------- 2 files changed, 396 insertions(+), 210 deletions(-) diff --git a/include/ringbuf.h b/include/ringbuf.h index 4c28efb..61bfae9 100644 --- a/include/ringbuf.h +++ b/include/ringbuf.h @@ -1,82 +1,88 @@ -/************************************************************************** +/** +* @file +* @author Steve Karg +* @date 2004 * -* Copyright (C) 2012 Steve Karg -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*********************************************************************/ +* Generic ring buffer library for deeply embedded system. +* See the unit tests for usage examples. +*/ #ifndef RINGBUF_H #define RINGBUF_H -/* Functional Description: Generic ring buffer library for deeply - embedded system. See the unit tests for usage examples. */ - #include #include +/** +* ring buffer power of two alignment macro +* +* @{ +*/ +#ifndef NEXT_POWER_OF_2 +#define B2(x) ( (x) | ( (x) >> 1) ) +#define B4(x) ( B2(x) | ( B2(x) >> 2) ) +#define B8(x) ( B4(x) | ( B4(x) >> 4) ) +#define B16(x) ( B8(x) | ( B8(x) >> 8) ) +#define B32(x) (B16(x) | (B16(x) >>16) ) +#define NEXT_POWER_OF_2(x) (B32((x)-1) + 1) +#endif +/** @} */ + +/** +* ring buffer data structure +* +* @{ +*/ struct ring_buffer_t { - volatile uint8_t *buffer; /* block of memory or array of data */ - unsigned element_size; /* how many bytes for each chunk */ - unsigned element_count; /* number of chunks of data */ - volatile unsigned head; /* where the writes go */ - volatile unsigned tail; /* where the reads come from */ + /** block of memory or array of data */ + volatile uint8_t *buffer; + /** how many bytes for each chunk */ + unsigned element_size; + /** number of chunks of data */ + unsigned element_count; + /** where the writes go */ + volatile unsigned head; + /** where the reads come from */ + volatile unsigned tail; + /* maximum depth reached */ + volatile unsigned depth; }; typedef struct ring_buffer_t RING_BUFFER; +/** @} */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - unsigned Ringbuf_Count( - RING_BUFFER const *b); - bool Ringbuf_Full( - RING_BUFFER const *b); - bool Ringbuf_Empty( - RING_BUFFER const *b); - volatile uint8_t *Ringbuf_Peek( - RING_BUFFER const *b); - bool Ringbuf_Pop( - RING_BUFFER * b, + unsigned Ringbuf_Count(RING_BUFFER const *b); + unsigned Ringbuf_Depth(RING_BUFFER const *b); + unsigned Ringbuf_Depth_Reset(RING_BUFFER *b); + unsigned Ringbuf_Size(RING_BUFFER const *b); + bool Ringbuf_Full(RING_BUFFER const *b); + bool Ringbuf_Empty(RING_BUFFER const *b); + /* tail */ + volatile uint8_t *Ringbuf_Peek(RING_BUFFER const *b); + bool Ringbuf_Pop(RING_BUFFER * b, uint8_t * data_element); - bool Ringbuf_Put( - RING_BUFFER * b, /* ring buffer structure */ - uint8_t * data_element); /* one element to add to the ring */ - bool Ringbuf_Put_Front( - RING_BUFFER * b, /* ring buffer structure */ + bool Ringbuf_Put_Front(RING_BUFFER * b, uint8_t * data_element); - volatile uint8_t *Ringbuf_Data_Peek( - RING_BUFFER * b); - bool Ringbuf_Data_Put( - RING_BUFFER * b, volatile uint8_t *data_element); + /* head */ + bool Ringbuf_Put(RING_BUFFER * b, + uint8_t * data_element); + /* pair of functions to use head memory directly */ + volatile uint8_t *Ringbuf_Data_Peek(RING_BUFFER * b); + bool Ringbuf_Data_Put(RING_BUFFER * b, volatile uint8_t *data_element); /* Note: element_count must be a power of two */ - void Ringbuf_Init( - RING_BUFFER * b, /* ring buffer structure */ - volatile uint8_t * buffer, /* data block or array of data */ - unsigned element_size, /* size of one element in the data block */ - unsigned element_count); /* number of elements in the data block */ + bool Ringbuf_Init(RING_BUFFER * b, + volatile uint8_t * buffer, + unsigned element_size, + unsigned element_count); #ifdef TEST #include "ctest.h" - void testRingBufSize16( - Test * pTest); - void testRingBufSize32( - Test * pTest); + void testRingBufPowerOfTwo(Test * pTest); + void testRingBufSizeSmall(Test * pTest); + void testRingBufSizeLarge(Test * pTest); + void testRingBufSizeInvalid(Test * pTest); #endif #ifdef __cplusplus diff --git a/src/ringbuf.c b/src/ringbuf.c index 09da334..8cb0786 100644 --- a/src/ringbuf.c +++ b/src/ringbuf.c @@ -1,54 +1,64 @@ -/*####COPYRIGHTBEGIN#### - ------------------------------------------- - Copyright (C) 2008 by Steve Karg - - 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. - ------------------------------------------- -####COPYRIGHTEND####*/ - -/* Functional Description: Generic ring buffer library for deeply - embedded system. See the unit tests for usage examples. */ - +/** +* @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 #include #include #include "ringbuf.h" -/**************************************************************************** -* DESCRIPTION: Returns the number of elements in the ring buffer -* RETURN: Number of elements in the ring buffer -* ALGORITHM: none -* NOTES: none -*****************************************************************************/ -unsigned Ringbuf_Count( - RING_BUFFER const *b) +/** +* 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 */ @@ -61,38 +71,104 @@ unsigned Ringbuf_Count( return 0; } -/**************************************************************************** -* DESCRIPTION: Returns the empty/full status of the ring buffer -* RETURN: true if the ring buffer is full, false if it is not. -* ALGORITHM: none -* NOTES: none -*****************************************************************************/ -bool Ringbuf_Full( - RING_BUFFER const *b) +/** +* 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); } -/**************************************************************************** -* DESCRIPTION: Returns the empty/full status of the ring buffer -* RETURN: true if the ring buffer is empty, false if it is not. -* ALGORITHM: none -* NOTES: none -*****************************************************************************/ -bool Ringbuf_Empty( - RING_BUFFER const *b) +/** +* 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); } -/**************************************************************************** -* DESCRIPTION: Looks at the data from the front of the list without removing it -* RETURN: pointer to the data, or NULL if nothing in the list -* ALGORITHM: none -* NOTES: none -*****************************************************************************/ -volatile uint8_t *Ringbuf_Peek( - RING_BUFFER const *b) +/** +* 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 */ @@ -104,14 +180,14 @@ volatile uint8_t *Ringbuf_Peek( return data_element; } -/**************************************************************************** -* DESCRIPTION: Copy the data from the front of the list, and removes it -* RETURN: true if data was copied, false if list is empty -* ALGORITHM: none -* NOTES: none -*****************************************************************************/ -bool Ringbuf_Pop( - RING_BUFFER * b, +/** +* 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 */ @@ -133,16 +209,16 @@ bool Ringbuf_Pop( return status; } -/**************************************************************************** -* DESCRIPTION: Adds an element of data to the end of the ring buffer -* RETURN: true on succesful add, false if not added -* ALGORITHM: none -* NOTES: none -*****************************************************************************/ -bool Ringbuf_Put( - RING_BUFFER * b, /* ring buffer structure */ +/** +* 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) -{ /* one element to add to the ring */ +{ bool status = false; /* return value */ volatile uint8_t *ring_data = NULL; /* used to help point ring data */ unsigned i; /* loop counter */ @@ -156,6 +232,7 @@ bool Ringbuf_Put( ring_data[i] = data_element[i]; } b->head++; + Ringbuf_Depth_Update(b); status = true; } } @@ -163,18 +240,20 @@ bool Ringbuf_Put( return status; } -/**************************************************************************** -* DESCRIPTION: Adds an element of data to the front of the ring buffer -* RETURN: true on succesful add, false if not added -* ALGORITHM: none -* NOTES: moves the tail on add instead of head, so this function -* can't be used if keeping producer and consumer -* as separate processes (i.e. interrupts) -*****************************************************************************/ -bool Ringbuf_Put_Front( - RING_BUFFER * b, /* ring buffer structure */ +/** +* 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) -{ /* one element to add to the front of the ring */ +{ bool status = false; /* return value */ volatile uint8_t *ring_data = NULL; /* used to help point ring data */ unsigned i = 0; /* loop counter */ @@ -189,6 +268,7 @@ bool Ringbuf_Put_Front( for (i = 0; i < b->element_size; i++) { ring_data[i] = data_element[i]; } + Ringbuf_Depth_Update(b); status = true; } } @@ -196,13 +276,13 @@ bool Ringbuf_Put_Front( return status; } -/**************************************************************************** -* DESCRIPTION: Gets a pointer to the next free data element of the buffer +/** +* Gets a pointer to the next free data element of the buffer * without adding it to the ring. -* RETURN: pointer to the next data chunk, or NULL if ring buffer is full. -* ALGORITHM: none -* NOTES: Use Ringbuf_Data_Peek with Ringbuf_Data_Put -*****************************************************************************/ +* +* @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 */ @@ -218,14 +298,15 @@ volatile uint8_t *Ringbuf_Data_Peek(RING_BUFFER * b) return ring_data; } -/**************************************************************************** -* DESCRIPTION: Adds the previously peeked element of data to the end of the -* ring buffer -* RETURN: true if the buffer has space and the data element points to the +/** +* 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. -* ALGORITHM: none -* NOTES: Use Ringbuf_Data_Peek with Ringbuf_Data_Put -*****************************************************************************/ +*/ bool Ringbuf_Data_Put(RING_BUFFER * b, volatile uint8_t *data_element) { bool status = false; @@ -239,6 +320,7 @@ bool Ringbuf_Data_Put(RING_BUFFER * b, volatile uint8_t *data_element) if (ring_data == data_element) { /* same chunk of memory - okay to signal the head */ b->head++; + Ringbuf_Depth_Update(b); status = true; } } @@ -247,28 +329,49 @@ bool Ringbuf_Data_Put(RING_BUFFER * b, volatile uint8_t *data_element) return status; } -/**************************************************************************** -* DESCRIPTION: Configures the ring buffer -* RETURN: none -* ALGORITHM: none -* NOTES: -* element_count must be a power of two -*****************************************************************************/ -void Ringbuf_Init( - RING_BUFFER * b, /* ring buffer structure */ - volatile uint8_t * buffer, /* data block or array of data */ - unsigned element_size, /* size of one element in the data block */ +/** +* 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) -{ /* number of elements in the data block */ - if (b) { +{ + 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; + return status; } #ifdef TEST @@ -277,9 +380,16 @@ void Ringbuf_Init( #include #include "ctest.h" -/* test the ring buffer */ -static void testRingAroundBuffer( - Test * pTest, +/** +* 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, @@ -289,39 +399,47 @@ static void testRingAroundBuffer( unsigned index; unsigned data_index; unsigned count; - unsigned dummy; + 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++) { - dummy = index * count; + value = (index * count)%255; for (data_index = 0; data_index < element_size; data_index++) { - data_element[data_index] = dummy; + 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++) { - dummy = index * 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] == dummy); + ct_test(pTest, test_data[data_index] == value); } } - (void) Ringbuf_Pop(test_buffer, NULL); + status = Ringbuf_Pop(test_buffer, NULL); + ct_test(pTest, status == true); } } ct_test(pTest, Ringbuf_Empty(test_buffer)); } -/* test the ring buffer */ -static void testRingBuf( - Test * pTest, +/** +* 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, @@ -333,8 +451,13 @@ static void testRingBuf( unsigned data_index; bool status; - Ringbuf_Init(&test_buffer, data_store, element_size, element_count); + 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; @@ -342,6 +465,7 @@ static void testRingBuf( 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++) { @@ -350,6 +474,7 @@ static void testRingBuf( 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++) { @@ -359,7 +484,9 @@ static void testRingBuf( 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++) { @@ -368,6 +495,7 @@ static void testRingBuf( 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 */ @@ -382,6 +510,9 @@ static void testRingBuf( (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); @@ -393,33 +524,78 @@ static void testRingBuf( testRingAroundBuffer(pTest, &test_buffer, data_element, element_size, element_count); - return; + return true; } -void testRingBufSize16( - Test * pTest) +/** +* 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) * 16]; + uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)]; - testRingBuf(pTest, data_store, data_element, sizeof(data_element), + status = testRingBuf(pTest, data_store, data_element, + sizeof(data_element), sizeof(data_store) / sizeof(data_element)); + ct_test(pTest, status); } -void testRingBufSize32( - Test * pTest) +/** +* 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) * 32]; + uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(99)]; - testRingBuf(pTest, data_store, data_element, sizeof(data_element), + 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); +} #ifdef TEST_RING_BUFFER -int main( - void) +/** +* Main program entry for Unit Test +* +* @return returns 0 on success, and non-zero on fail. +*/ +int main(void) { Test *pTest; bool rc; @@ -427,9 +603,13 @@ int main( pTest = ct_create("Ring Buffer", NULL); /* individual tests */ - rc = ct_addTestFunction(pTest, testRingBufSize16); + rc = ct_addTestFunction(pTest, testRingBufPowerOfTwo); assert(rc); - rc = ct_addTestFunction(pTest, testRingBufSize32); + rc = ct_addTestFunction(pTest, testRingBufSizeSmall); + assert(rc); + rc = ct_addTestFunction(pTest, testRingBufSizeLarge); + assert(rc); + rc = ct_addTestFunction(pTest, testRingBufSizeInvalid); assert(rc); ct_setStream(pTest, stdout);