2026-08-29 01:50:50 +08:00
|
|
|
#include "c_FastByteRingBuffer.h"
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
2026-08-29 11:39:28 +08:00
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
|
|
|
/* */
|
|
|
|
|
|
2026-08-29 01:50:50 +08:00
|
|
|
|
|
|
|
|
#define RUN_TEST_CASE(test_func) \
|
|
|
|
|
do { \
|
|
|
|
|
printf("[RUNNING] %-40s ... ", #test_func); \
|
|
|
|
|
fflush(stdout); \
|
|
|
|
|
test_func(); \
|
|
|
|
|
printf("[PASSED]\n"); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
void test_ring_buffer_behavior(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
// Capacity initialization must be a power of two
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 4) == C_SUCCESS);
|
|
|
|
|
|
|
|
|
|
uint8_t input_stream[] = {0x11, 0x22, 0x33};
|
|
|
|
|
|
|
|
|
|
// 1. Verify standard incremental writing actions
|
|
|
|
|
assert(c_FastByteRingBuffer_WriteBuffer(&ring, input_stream, 3) == 3);
|
|
|
|
|
assert(c_FastByteRingBuffer_GetSize(&ring) == 3);
|
|
|
|
|
|
|
|
|
|
// 2. Verify overflow rejection clamping protection
|
|
|
|
|
uint8_t flood_stream[] = {0x44, 0x55};
|
|
|
|
|
// Only 1 byte of free space remains out of total capacity 4
|
|
|
|
|
assert(c_FastByteRingBuffer_WriteBuffer(&ring, flood_stream, 2) == 1);
|
|
|
|
|
assert(c_FastByteRingBuffer_IsFull(&ring) == C_TRUE);
|
|
|
|
|
|
|
|
|
|
// Check data integrity via peek operations
|
|
|
|
|
uint8_t output_peek[4] = {0};
|
|
|
|
|
c_FastByteRingBuffer_PeekBuffer(&ring, output_peek, 4);
|
|
|
|
|
assert(output_peek[0] == 0x11);
|
|
|
|
|
assert(output_peek[3] == 0x44); // 0x44 filled the last slot; 0x55 was cleanly rejected
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_overwrite_and_peek_mechanics(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 4) == C_SUCCESS); // Capacity = 4
|
|
|
|
|
|
|
|
|
|
// 1. Validate Single Overwrite
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0x01);
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0x02);
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0x03);
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0x04); // Buffer now full: [0x01, 0x02, 0x03, 0x04]
|
|
|
|
|
assert(c_FastByteRingBuffer_IsFull(&ring) == C_TRUE);
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_WriteByteOverwrite(&ring, 0x05); // 0x01 gets evicted. Head shifts to 0x02
|
|
|
|
|
|
|
|
|
|
uint8_t peek_check = 0;
|
|
|
|
|
assert(c_FastByteRingBuffer_PeekByte(&ring, &peek_check) == C_SUCCESS);
|
|
|
|
|
assert(peek_check == 0x02); // FIFO rules dictate oldest remaining byte is 0x02
|
|
|
|
|
|
|
|
|
|
// 2. Validate Bulk Overwrite Loops
|
|
|
|
|
uint8_t incoming_stream[3] = {0x06, 0x07, 0x08};
|
|
|
|
|
// Ring has 4 bytes capacity. Writing 3 bytes over an already full buffer evicts [0x02, 0x03, 0x04]
|
|
|
|
|
assert(c_FastByteRingBuffer_WriteBufferOverwrite(&ring, incoming_stream, 3) == 3);
|
|
|
|
|
|
|
|
|
|
uint8_t verification_dump[4] = {0};
|
|
|
|
|
c_size_t read_out = c_FastByteRingBuffer_PeekBuffer(&ring, verification_dump, 4);
|
|
|
|
|
assert(read_out == 4);
|
|
|
|
|
assert(verification_dump[0] == 0x05); // Preserved from previous transaction
|
|
|
|
|
assert(verification_dump[1] == 0x06);
|
|
|
|
|
assert(verification_dump[2] == 0x07);
|
|
|
|
|
assert(verification_dump[3] == 0x08);
|
|
|
|
|
|
|
|
|
|
// 3. Confirm Peek leaves data sequence entirely untouched
|
|
|
|
|
assert(c_FastByteRingBuffer_GetSize(&ring) == 4);
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_dma_and_discard_mechanics(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 8) == C_SUCCESS); // Capacity = 8
|
|
|
|
|
|
|
|
|
|
// Force initialization of data that loops around the internal ring memory map
|
|
|
|
|
uint8_t payload[] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, payload, 5);
|
|
|
|
|
|
|
|
|
|
// Discard oldest 2 items: drops 0xA1, 0xA2. Cursors shift.
|
|
|
|
|
assert(c_FastByteRingBuffer_Discard(&ring, 2) == 2);
|
|
|
|
|
assert(c_FastByteRingBuffer_GetSize(&ring) == 3);
|
|
|
|
|
|
|
|
|
|
// Write some more to force a wrap-around layout
|
|
|
|
|
uint8_t wrap_payload[] = {0xB1, 0xB2, 0xB3, 0xB4};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, wrap_payload, 4); // Total size now = 7 bytes
|
|
|
|
|
|
|
|
|
|
// Validate GetReadPtr isolates Block Segment 1 cleanly
|
|
|
|
|
c_size_t read_chunk_len = 0;
|
|
|
|
|
const uint8_t* read_ptr = c_FastByteRingBuffer_GetReadPtr(&ring, &read_chunk_len);
|
|
|
|
|
|
|
|
|
|
assert(read_ptr != NULL);
|
|
|
|
|
// Head was shifted to index 2. 8 - 2 = 6 available linearly up to memory array edge
|
|
|
|
|
assert(read_chunk_len == 6);
|
|
|
|
|
assert(read_ptr[0] == 0xA3); // First remaining item
|
|
|
|
|
|
|
|
|
|
// Clear those processed items via direct execution tracking
|
|
|
|
|
c_FastByteRingBuffer_Discard(&ring, read_chunk_len);
|
|
|
|
|
|
|
|
|
|
// Call secondary pass to capture remaining wrapped bytes
|
|
|
|
|
read_ptr = c_FastByteRingBuffer_GetReadPtr(&ring, &read_chunk_len);
|
|
|
|
|
assert(read_chunk_len == 1);
|
|
|
|
|
assert(read_ptr[0] == 0xB4); // Wrapped character check
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_ring_buffer_index_searching(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 8) == C_SUCCESS); // Capacity = 8
|
|
|
|
|
|
|
|
|
|
// Force a data write footprint that wraps around the buffer margins
|
|
|
|
|
uint8_t standard_fill[] = {0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, standard_fill, 8);
|
|
|
|
|
|
|
|
|
|
// Discard 4 elements to position head cursor at absolute index 4
|
|
|
|
|
c_FastByteRingBuffer_Discard(&ring, 4);
|
|
|
|
|
|
|
|
|
|
// Append sequence to cross edge wrap boundaries cleanly
|
|
|
|
|
uint8_t wrap_fill[] = {0x55, 0x66, 0x77};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, wrap_fill, 3);
|
|
|
|
|
// Dynamic ring content layout from head: [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77]
|
|
|
|
|
|
|
|
|
|
// 1. Single byte search lookup match
|
|
|
|
|
assert(c_FastByteRingBuffer_IndexOfByte(&ring, 0x33) == 2); // Relative offset index 2 from head
|
2026-08-29 11:39:28 +08:00
|
|
|
assert(c_FastByteRingBuffer_IndexOfByte(&ring, 0x99) == C_ERR_NOTFOUND);
|
2026-08-29 01:50:50 +08:00
|
|
|
|
|
|
|
|
// 2. Pattern buffer sequence scan (testing across structural wrap-around edge boundaries)
|
|
|
|
|
uint8_t search_pattern[] = {0x44, 0x55, 0x66};
|
|
|
|
|
c_index_t match_offset = c_FastByteRingBuffer_IndexOfBuffer(&ring, search_pattern, 3);
|
|
|
|
|
|
|
|
|
|
assert(match_offset == 3); // 0x44 sits exactly at relative offset position 3
|
|
|
|
|
|
|
|
|
|
// Application Workflow Integration: Cleanly discard up to token match prefix point
|
|
|
|
|
c_FastByteRingBuffer_Discard(&ring, (c_size_t)match_offset);
|
|
|
|
|
uint8_t current_head_byte = 0;
|
|
|
|
|
c_FastByteRingBuffer_PeekByte(&ring, ¤t_head_byte);
|
|
|
|
|
assert(current_head_byte == 0x44); // The buffer head has been successfully synchronized to the token location
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_reverse_search_and_token_stream(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 8) == C_SUCCESS); // Capacity = 8
|
|
|
|
|
|
|
|
|
|
uint8_t raw_payload[] = {0xAA, 0x11, 0x22, 0xBB, 0x11, 0x22, 0xCC, 0xDD};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, raw_payload, 8);
|
|
|
|
|
|
|
|
|
|
uint8_t pattern[] = {0x11, 0x22};
|
|
|
|
|
|
|
|
|
|
// 1. Verify Reverse Pattern Detection Matches Latest Occurrence
|
|
|
|
|
assert(c_FastByteRingBuffer_IndexOfBuffer(&ring, pattern, 2) == 1); // First pair starts at offset 1
|
|
|
|
|
assert(c_FastByteRingBuffer_LastIndexOfBuffer(&ring, pattern, 2) == 4); // Latest pair starts at offset 4
|
|
|
|
|
|
|
|
|
|
// 2. Clear out buffer to run frame serialization test
|
|
|
|
|
c_FastByteRingBuffer_Discard(&ring, 8);
|
|
|
|
|
|
|
|
|
|
uint8_t stream_data[] = {'P', 'a', 'c', 'k', 'e', 't', '\r', '\n'};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, stream_data, 8);
|
|
|
|
|
|
|
|
|
|
uint8_t frame_terminator[] = {'\r', '\n'};
|
|
|
|
|
uint8_t output_staging[16] = {0};
|
|
|
|
|
|
|
|
|
|
// Fail Case: Pass a staging array that is structurally too cramped to hold the payload safely
|
|
|
|
|
assert(c_FastByteRingBuffer_ReadUntilToken(&ring, frame_terminator, 2, output_staging, 5) == 0);
|
|
|
|
|
assert(c_FastByteRingBuffer_GetSize(&ring) == 8); // Data remains locked safely inside the ring
|
|
|
|
|
|
|
|
|
|
// Success Case: Pass a valid container size to execute frame extraction
|
|
|
|
|
c_size_t read_bytes = c_FastByteRingBuffer_ReadUntilToken(&ring, frame_terminator, 2, output_staging, 16);
|
|
|
|
|
assert(read_bytes == 8);
|
|
|
|
|
assert(memcmp(output_staging, "Packet\r\n", 8) == 0);
|
|
|
|
|
assert(c_FastByteRingBuffer_IsEmpty(&ring) == C_TRUE); // Frame has been cleanly consumed from the queue
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_relative_random_access(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 4) == C_SUCCESS); // Capacity = 4
|
|
|
|
|
|
|
|
|
|
uint8_t seed_data[] = {0x10, 0x20, 0x30};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, seed_data, 3);
|
|
|
|
|
|
|
|
|
|
// Shift the head pointer downstream via a single byte consumption
|
|
|
|
|
uint8_t discard_sink = 0;
|
|
|
|
|
c_FastByteRingBuffer_ReadByte(&ring, &discard_sink); // 0x10 dropped. Head points to 0x20
|
|
|
|
|
|
|
|
|
|
// Append items to cross physical wrapping thresholds cleanly
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0x40);
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0x50); // Buffer contents: [0x20, 0x30, 0x40, 0x50]
|
|
|
|
|
|
|
|
|
|
uint8_t extracted_byte = 0;
|
|
|
|
|
|
|
|
|
|
// 1. Verify standard random read coordinates relative to the head position
|
|
|
|
|
assert(c_FastByteRingBuffer_GetAtRelative(&ring, 0, &extracted_byte) == C_SUCCESS);
|
|
|
|
|
assert(extracted_byte == 0x20); // Relative 0 points directly to the current head
|
|
|
|
|
|
|
|
|
|
assert(c_FastByteRingBuffer_GetAtRelative(&ring, 2, &extracted_byte) == C_SUCCESS);
|
|
|
|
|
assert(extracted_byte == 0x40); // Wrapped index check
|
|
|
|
|
|
|
|
|
|
assert(c_FastByteRingBuffer_GetAtRelative(&ring, 3, &extracted_byte) == C_SUCCESS);
|
|
|
|
|
assert(extracted_byte == 0x50); // Newest unread byte check
|
|
|
|
|
|
|
|
|
|
// 2. Validate bounds-checking flags
|
2026-08-29 11:39:28 +08:00
|
|
|
assert(c_FastByteRingBuffer_GetAtRelative(&ring, 4, &extracted_byte) == C_ERR_OUTOFBOUND);
|
|
|
|
|
assert(c_FastByteRingBuffer_GetAtRelative(&ring, 99, &extracted_byte) == C_ERR_OUTOFBOUND);
|
|
|
|
|
assert(c_FastByteRingBuffer_GetAtRelative(NULL, 0, &extracted_byte) == C_ERR_PARAM);
|
2026-08-29 01:50:50 +08:00
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_conditional_is_validator(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 4) == C_SUCCESS);
|
|
|
|
|
|
|
|
|
|
uint8_t input_stream[] = {0xAA, 0xBB, 0xCC};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, input_stream, 3);
|
|
|
|
|
|
|
|
|
|
// 1. Validate clean true/false matches relative to the head
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, 0, 0xAA) == C_TRUE); // Oldest byte at head matches
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, 1, 0xBB) == C_TRUE); // Next element matches
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, 1, 0x99) == C_FALSE); // Mismatch returns false
|
|
|
|
|
|
|
|
|
|
// Consume 1 byte to advance the head pointer and test wrapping boundaries
|
|
|
|
|
uint8_t sink = 0;
|
|
|
|
|
c_FastByteRingBuffer_ReadByte(&ring, &sink); // Head now points to 0xBB
|
|
|
|
|
c_FastByteRingBuffer_WriteByte(&ring, 0xDD); // Layout: [..., 0xBB, 0xCC, 0xDD]
|
|
|
|
|
|
|
|
|
|
// 2. Re-verify offsets after structural pointer wrap shifts
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, 0, 0xBB) == C_TRUE); // Head index position 0 is now 0xBB
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, 2, 0xDD) == C_TRUE); // Wrapped index element match
|
|
|
|
|
|
|
|
|
|
// 3. Confirm error/bounds conditions return false instead of blowing up memory layout boundaries
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, 3, 0x00) == C_FALSE); // Out of bounds index
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(&ring, -5, 0xBB) == C_FALSE); // Negative index handling protection
|
|
|
|
|
assert(c_FastByteRingBuffer_Is(NULL, 0, 0xBB) == C_FALSE); // NULL safety check
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_ring_buffer_memcmp(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
2026-08-29 11:39:28 +08:00
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 6) == C_ERR_PARAM); // Capacity = 6
|
2026-08-29 01:50:50 +08:00
|
|
|
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 8) == C_SUCCESS); // Capacity = 6
|
|
|
|
|
uint8_t payload[] = {0x00, 0x11, 0x22, 0x33};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, payload, 4);
|
|
|
|
|
|
|
|
|
|
// Consume 2 bytes to step the head pointer forward to absolute index 2
|
|
|
|
|
uint8_t sink = 0;
|
|
|
|
|
c_FastByteRingBuffer_ReadByte(&ring, &sink);
|
|
|
|
|
c_FastByteRingBuffer_ReadByte(&ring, &sink); // Buffer active layout from head: [0x22, 0x33]
|
|
|
|
|
|
|
|
|
|
// Append data to trigger an explicit physical wrap-around edge split layout
|
|
|
|
|
uint8_t wrap_payload[] = {0x44, 0x55, 0x66};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, wrap_payload, 3);
|
|
|
|
|
// Buffer dynamic content path tracking from head: [0x22, 0x33, 0x44, 0x55, 0x66]
|
|
|
|
|
// Physical layout behind indices inside array: [0x55, 0x66, 0x22, 0x33, 0x44, ...]
|
|
|
|
|
|
|
|
|
|
// 1. Validate contiguous segment match comparisons
|
|
|
|
|
uint8_t check_a[] = {0x22, 0x33};
|
|
|
|
|
assert(c_FastByteRingBuffer_Memcmp(&ring, 0, check_a, 2) == 0); // Perfect contiguous match
|
|
|
|
|
|
|
|
|
|
// 2. Validate multi-segment wrap-around comparison mechanics
|
|
|
|
|
uint8_t check_b[] = {0x33, 0x44, 0x55, 0x66};
|
|
|
|
|
assert(c_FastByteRingBuffer_Memcmp(&ring, 1, check_b, 4) == 0); // Perfect split wrap-around match
|
|
|
|
|
|
|
|
|
|
// 3. Mismatch checks
|
|
|
|
|
uint8_t check_mismatch[] = {0x33, 0x44, 0x99, 0x66};
|
|
|
|
|
assert(c_FastByteRingBuffer_Memcmp(&ring, 1, check_mismatch, 4) != 0); // Identifies internal divergence
|
|
|
|
|
|
|
|
|
|
// 4. Bounds and parameter checks
|
2026-08-29 11:39:28 +08:00
|
|
|
assert(c_FastByteRingBuffer_Memcmp(&ring, 0, check_b, 100) == C_ERR_OUTOFBOUND); // Request width overflows content
|
|
|
|
|
assert(c_FastByteRingBuffer_Memcmp(&ring, 99, check_b, 1) == C_ERR_OUTOFBOUND); // Start pointer invalid
|
|
|
|
|
assert(c_FastByteRingBuffer_Memcmp(NULL, 0, check_b, 1) == C_ERR_PARAM);
|
2026-08-29 01:50:50 +08:00
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
static void test_ring_buffer_strtoul(void) {
|
|
|
|
|
c_FastByteRingBuffer_t ring;
|
|
|
|
|
assert(c_FastByteRingBuffer_Init(&ring, 8) == C_SUCCESS); // Capacity = 8
|
|
|
|
|
|
|
|
|
|
// 1. Standard Linear Base-10 Parsing
|
|
|
|
|
uint8_t input_a[] = {'1', '2', '3', '4', ' ', 'A', 'B', 'C'};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, input_a, 8);
|
|
|
|
|
|
|
|
|
|
unsigned long parsed_val = 0;
|
|
|
|
|
c_size_t end_offset = 0;
|
|
|
|
|
|
|
|
|
|
assert(c_FastByteRingBuffer_Strtoul(&ring, 0, 10, &parsed_val, &end_offset) == C_SUCCESS);
|
|
|
|
|
assert(parsed_val == 1234);
|
|
|
|
|
assert(end_offset == 4); // Points exactly to the trailing space character offset
|
|
|
|
|
|
|
|
|
|
// Reset buffer tracking lines
|
|
|
|
|
c_FastByteRingBuffer_Discard(&ring, 8);
|
|
|
|
|
|
|
|
|
|
// 2. Fragmented Wrap Hex Parsing
|
|
|
|
|
// Pre-fill 5 elements to push cursor indices near wrapping layout boundaries
|
|
|
|
|
uint8_t pre_fill[] = {0, 0, 0, 0, 0};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, pre_fill, 5);
|
|
|
|
|
c_FastByteRingBuffer_Discard(&ring, 5); // Head pointer sits at physical index 5
|
|
|
|
|
|
|
|
|
|
// Write Hex parameter payload string ("0x2F") across memory boundaries
|
|
|
|
|
uint8_t input_hex[] = {'0', 'x', '2', 'F'};
|
|
|
|
|
c_FastByteRingBuffer_WriteBuffer(&ring, input_hex, 4);
|
|
|
|
|
|
|
|
|
|
assert(c_FastByteRingBuffer_Strtoul(&ring, 0, 16, &parsed_val, &end_offset) == C_SUCCESS);
|
|
|
|
|
assert(parsed_val == 47); // 0x2F translates to decimal 47
|
|
|
|
|
assert(end_offset == 4);
|
|
|
|
|
|
|
|
|
|
c_FastByteRingBuffer_Destroy(&ring);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
printf("==================================================\n");
|
|
|
|
|
printf(" Starting c_FastByteRingBuffer Unit Testing Suite\n");
|
|
|
|
|
printf("==================================================\n\n");
|
|
|
|
|
|
|
|
|
|
RUN_TEST_CASE(test_ring_buffer_behavior);
|
|
|
|
|
RUN_TEST_CASE(test_overwrite_and_peek_mechanics);
|
|
|
|
|
RUN_TEST_CASE(test_dma_and_discard_mechanics);
|
|
|
|
|
RUN_TEST_CASE(test_ring_buffer_index_searching);
|
|
|
|
|
RUN_TEST_CASE(test_reverse_search_and_token_stream);
|
|
|
|
|
RUN_TEST_CASE(test_relative_random_access);
|
|
|
|
|
RUN_TEST_CASE(test_conditional_is_validator);
|
|
|
|
|
RUN_TEST_CASE(test_ring_buffer_memcmp);
|
|
|
|
|
RUN_TEST_CASE(test_ring_buffer_strtoul);
|
|
|
|
|
|
|
|
|
|
printf("\n==================================================\n");
|
|
|
|
|
printf(" Success! Byte RingBuffer tests passed!\n");
|
|
|
|
|
printf("==================================================\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|