870 lines
25 KiB
C
870 lines
25 KiB
C
/*==============================================================================
|
|
Copyright (c) 2016-2018, The Linux Foundation.
|
|
Copyright (c) 2018-2022, Laurence Lundblade.
|
|
Copyright (c) 2021, Arm Limited.
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above
|
|
copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided
|
|
with the distribution.
|
|
* Neither the name of The Linux Foundation nor the names of its
|
|
contributors, nor the name "Laurence Lundblade" may be used to
|
|
endorse or promote products derived from this software without
|
|
specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
=============================================================================*/
|
|
|
|
#include "UsefulBuf.h"
|
|
|
|
|
|
/* This calls the main methods to add stuff to a UsefulOutBuf.
|
|
* The result in the UsefulOutBuf is "heffalump unbounce bluster hunny bear"
|
|
*/
|
|
const char *AddStuffToUOB(UsefulOutBuf *pUOB)
|
|
{
|
|
const char *szReturn = NULL;
|
|
|
|
if(!UsefulOutBuf_AtStart(pUOB)) {
|
|
szReturn = "Not at start";
|
|
goto Done;
|
|
}
|
|
|
|
/* Put 7 bytes at beginning of buf */
|
|
UsefulOutBuf_AppendData(pUOB, "bluster", 7);
|
|
|
|
if(UsefulOutBuf_AtStart(pUOB)) {
|
|
szReturn = "At start";
|
|
goto Done;
|
|
}
|
|
|
|
/* add a space to end */
|
|
UsefulOutBuf_AppendByte(pUOB, ' ');
|
|
|
|
/* Add 6 bytes to the end */
|
|
UsefulBufC UBC = {"hunny ", 6};
|
|
UsefulOutBuf_AppendUsefulBuf(pUOB, UBC);
|
|
|
|
/* Insert 9 bytes at the beginning, slide the previous stuff right */
|
|
UsefulOutBuf_InsertData(pUOB, "heffalump", 9, 0);
|
|
UsefulOutBuf_InsertByte(pUOB, ' ', 9);
|
|
|
|
/* Put 9 bytes in at position 10 -- just after "heffalump " */
|
|
UsefulBufC UBC2 = {"unbounce ", 9};
|
|
UsefulOutBuf_InsertUsefulBuf(pUOB, UBC2, 10);
|
|
|
|
/* Add 4 bytes to the end, by accessing the buffer directly and then advancing it */
|
|
UsefulBuf UB = UsefulOutBuf_GetOutPlace(pUOB);
|
|
if (!UsefulBuf_IsNULL(UB)) {
|
|
memcpy(UB.ptr, "bear", UB.len < 4 ? UB.len : 4);
|
|
}
|
|
UsefulOutBuf_Advance(pUOB, 4);
|
|
|
|
Done:
|
|
return szReturn;
|
|
}
|
|
|
|
|
|
/* Basic exercise of a UsefulOutBuf
|
|
*
|
|
* Call all the main public functions.
|
|
*
|
|
* Binary compare the result to the expected.
|
|
*
|
|
* There is nothing adversarial in this test
|
|
*/
|
|
const char * UOBTest_NonAdversarial(void)
|
|
{
|
|
const char *szReturn = NULL;
|
|
|
|
UsefulBuf_MAKE_STACK_UB(outbuf, 50);
|
|
|
|
UsefulOutBuf UOB;
|
|
|
|
UsefulOutBuf_Init(&UOB, outbuf);
|
|
|
|
szReturn = AddStuffToUOB(&UOB);
|
|
if(szReturn) {
|
|
goto Done;
|
|
}
|
|
|
|
const UsefulBufC Expected = UsefulBuf_FROM_SZ_LITERAL("heffalump unbounce bluster hunny bear");
|
|
|
|
UsefulBufC U = UsefulOutBuf_OutUBuf(&UOB);
|
|
if(UsefulBuf_IsNULLC(U) ||
|
|
UsefulBuf_Compare(Expected, U) ||
|
|
UsefulOutBuf_GetError(&UOB)) {
|
|
szReturn = "OutUBuf";
|
|
goto Done;
|
|
}
|
|
|
|
UsefulBuf_MAKE_STACK_UB(buf, 50);
|
|
UsefulBufC Out = UsefulOutBuf_CopyOut(&UOB, buf);
|
|
if(UsefulBuf_IsNULLC(Out) || UsefulBuf_Compare(Expected, Out)) {
|
|
szReturn = "CopyOut";
|
|
goto Done;
|
|
}
|
|
|
|
/* Now test the size calculation mode */
|
|
UsefulOutBuf_Init(&UOB, SizeCalculateUsefulBuf);
|
|
|
|
szReturn = AddStuffToUOB(&UOB);
|
|
if(szReturn) {
|
|
goto Done;
|
|
}
|
|
|
|
U = UsefulOutBuf_OutUBuf(&UOB);
|
|
if(U.len != Expected.len || U.ptr != NULL) {
|
|
szReturn = "size calculation failed";
|
|
}
|
|
|
|
Done:
|
|
return szReturn;
|
|
}
|
|
|
|
|
|
/*
|
|
Append test utility.
|
|
pUOB is the buffer to append too
|
|
num is the amount to append
|
|
expected is the expected return code, 0 or 1
|
|
|
|
returns 0 if test passed
|
|
|
|
*/
|
|
static int AppendTest(UsefulOutBuf *pUOB, size_t num, int expected)
|
|
{
|
|
//reset
|
|
UsefulOutBuf_Reset(pUOB);
|
|
|
|
// check status first
|
|
if(UsefulOutBuf_GetError(pUOB))
|
|
return 1;
|
|
|
|
// append the bytes
|
|
UsefulOutBuf_AppendData(pUOB, (const uint8_t *)"bluster", num);
|
|
|
|
// check error status after
|
|
if(UsefulOutBuf_GetError(pUOB) != expected)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
Same as append, but takes a position param too
|
|
*/
|
|
static int InsertTest(UsefulOutBuf *pUOB, size_t num, size_t pos, int expected)
|
|
{
|
|
// reset
|
|
UsefulOutBuf_Reset(pUOB);
|
|
|
|
// check
|
|
if(UsefulOutBuf_GetError(pUOB))
|
|
return 1;
|
|
|
|
UsefulOutBuf_InsertData(pUOB, (const uint8_t *)"bluster", num, pos);
|
|
|
|
if(UsefulOutBuf_GetError(pUOB) != expected)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
Boundary conditions to test
|
|
- around 0
|
|
- around the buffer size
|
|
- around MAX size_t
|
|
|
|
|
|
Test these for the buffer size and the cursor, the insert amount, the
|
|
append amount and the insert position
|
|
|
|
*/
|
|
|
|
const char *UOBTest_BoundaryConditionsTest(void)
|
|
{
|
|
UsefulBuf_MAKE_STACK_UB(outbuf, 2);
|
|
|
|
UsefulOutBuf UOB;
|
|
|
|
UsefulOutBuf_Init(&UOB, outbuf);
|
|
|
|
// append 0 byte to a 2 byte buffer --> success
|
|
if(AppendTest(&UOB, 0, 0))
|
|
return "Append 0 bytes failed";
|
|
|
|
// append 1 byte to a 2 byte buffer --> success
|
|
if(AppendTest(&UOB, 1, 0))
|
|
return "Append of 1 byte failed";
|
|
|
|
// append 2 byte to a 2 byte buffer --> success
|
|
if(AppendTest(&UOB, 2, 0))
|
|
return "Append to fill buffer failed";
|
|
|
|
// append 3 bytes to a 2 byte buffer --> failure
|
|
if(AppendTest(&UOB, 3, 1))
|
|
return "Overflow of buffer not caught";
|
|
|
|
// append max size_t to a 2 byte buffer --> failure
|
|
if(AppendTest(&UOB, SIZE_MAX, 1))
|
|
return "Append of SIZE_MAX error not caught";
|
|
|
|
if(InsertTest(&UOB, 1, 0, 0))
|
|
return "Insert 1 byte at start failed";
|
|
|
|
if(InsertTest(&UOB, 2, 0, 0))
|
|
return "Insert 2 bytes at start failed";
|
|
|
|
if(InsertTest(&UOB, 3, 0, 1))
|
|
return "Insert overflow not caught";
|
|
|
|
if(InsertTest(&UOB, 1, 1, 1))
|
|
return "Bad insertion point not caught";
|
|
|
|
|
|
UsefulBuf_MAKE_STACK_UB(outBuf2,10);
|
|
|
|
UsefulOutBuf_Init(&UOB, outBuf2);
|
|
|
|
UsefulOutBuf_Reset(&UOB);
|
|
// put data in the buffer
|
|
UsefulOutBuf_AppendString(&UOB, "abc123");
|
|
|
|
UsefulOutBuf_InsertString(&UOB, "xyz*&^", 0);
|
|
|
|
if(!UsefulOutBuf_GetError(&UOB)) {
|
|
return "insert with data should have failed";
|
|
}
|
|
|
|
|
|
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5});
|
|
UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -6);
|
|
if(UsefulOutBuf_GetError(&UOB)) {
|
|
return "insert in huge should have succeeded";
|
|
}
|
|
|
|
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5});
|
|
UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -5);
|
|
if(UsefulOutBuf_GetError(&UOB)) {
|
|
return "insert in huge should have succeeded";
|
|
}
|
|
|
|
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5});
|
|
UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX - 4);
|
|
if(!UsefulOutBuf_GetError(&UOB)) {
|
|
return "lengths near max size";
|
|
}
|
|
|
|
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, 100});
|
|
if(!UsefulOutBuf_IsBufferNULL(&UOB)) {
|
|
return "NULL check failed";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Test function to get size and magic number check
|
|
|
|
const char *TestBasicSanity(void)
|
|
{
|
|
UsefulBuf_MAKE_STACK_UB(outbuf,10);
|
|
|
|
UsefulOutBuf UOB;
|
|
|
|
// First -- make sure that the room left function returns the right amount
|
|
UsefulOutBuf_Init(&UOB, outbuf);
|
|
|
|
if(UsefulOutBuf_RoomLeft(&UOB) != 10)
|
|
return "room left failed";
|
|
|
|
if(!UsefulOutBuf_WillItFit(&UOB, 9)) {
|
|
return "it did not fit";
|
|
}
|
|
|
|
if(UsefulOutBuf_WillItFit(&UOB, 11)) {
|
|
return "it should have not fit";
|
|
}
|
|
|
|
|
|
// Next -- make sure that the magic number checking is working right
|
|
UOB.magic = 8888; // make magic bogus
|
|
|
|
UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7);
|
|
|
|
if(!UsefulOutBuf_GetError(&UOB)) {
|
|
return "magic corruption check failed";
|
|
}
|
|
|
|
|
|
|
|
// Next make sure that the valid data length check is working right
|
|
UsefulOutBuf_Init(&UOB, outbuf);
|
|
|
|
UOB.data_len = UOB.UB.len+1; // make size bogus
|
|
|
|
UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7);
|
|
if(!UsefulOutBuf_GetError(&UOB))
|
|
return "valid data check failed";
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
const char *UBMacroConversionsTest(void)
|
|
{
|
|
char *szFoo = "foo";
|
|
|
|
UsefulBufC Foo = UsefulBuf_FromSZ(szFoo);
|
|
if(Foo.len != 3 || strncmp(Foo.ptr, szFoo, 3))
|
|
return "SZToUsefulBufC failed";
|
|
|
|
UsefulBufC Too = UsefulBuf_FROM_SZ_LITERAL("Toooo");
|
|
if(Too.len != 5 || strncmp(Too.ptr, "Toooo", 5))
|
|
return "UsefulBuf_FROM_SZ_LITERAL failed";
|
|
|
|
uint8_t pB[] = {0x42, 0x6f, 0x6f};
|
|
UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
|
|
if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3))
|
|
return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed";
|
|
|
|
char *String = "string"; // Intentionally not const
|
|
UsefulBuf B = (UsefulBuf){(void *)String, strlen(String)};
|
|
UsefulBufC BC = UsefulBuf_Const(B);
|
|
if(BC.len != strlen(String) || BC.ptr != String)
|
|
return "UsefulBufConst failed";
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
const char *UBUtilTests(void)
|
|
{
|
|
UsefulBuf UB = NULLUsefulBuf;
|
|
|
|
if(!UsefulBuf_IsNULL(UB)){
|
|
return "IsNull failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsEmpty(UB)){
|
|
return "IsEmpty failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsNULLOrEmpty(UB)) {
|
|
return "IsNULLOrEmpty failed";
|
|
}
|
|
|
|
const UsefulBufC UBC = UsefulBuf_Const(UB);
|
|
|
|
if(!UsefulBuf_IsNULLC(UBC)){
|
|
return "IsNull const failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsEmptyC(UBC)){
|
|
return "IsEmptyC failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsNULLOrEmptyC(UBC)){
|
|
return "IsNULLOrEmptyC failed";
|
|
}
|
|
|
|
const UsefulBuf UB2 = UsefulBuf_Unconst(UBC);
|
|
if(!UsefulBuf_IsEmpty(UB2)) {
|
|
return "Back to UB is Empty failed";
|
|
}
|
|
|
|
UB.ptr = "x"; // just some valid pointer
|
|
|
|
if(UsefulBuf_IsNULL(UB)){
|
|
return "IsNull failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsEmptyC(UBC)){
|
|
return "IsEmpty failed";
|
|
}
|
|
|
|
// test the Unconst.
|
|
if(UsefulBuf_Unconst(UBC).ptr != NULL) {
|
|
return "Unconst failed";
|
|
}
|
|
|
|
// Set 100 bytes of '+'; validated a few tests later
|
|
UsefulBuf_MAKE_STACK_UB(Temp, 100);
|
|
const UsefulBufC TempC = UsefulBuf_Set(Temp, '+');
|
|
|
|
// Try to copy into a buf that is too small and see failure
|
|
UsefulBuf_MAKE_STACK_UB(Temp2, 99);
|
|
if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp2, TempC))) {
|
|
return "Copy should have failed";
|
|
}
|
|
|
|
if(UsefulBuf_IsNULLC(UsefulBuf_CopyPtr(Temp2, "xx", 2))) {
|
|
return "CopyPtr failed";
|
|
}
|
|
|
|
UsefulBufC xxyy = UsefulBuf_CopyOffset(Temp2, 2, UsefulBuf_FROM_SZ_LITERAL("yy"));
|
|
if(UsefulBuf_IsNULLC(xxyy)) {
|
|
return "CopyOffset Failed";
|
|
}
|
|
|
|
if(UsefulBuf_Compare(UsefulBuf_Head(xxyy, 3), UsefulBuf_FROM_SZ_LITERAL("xxy"))) {
|
|
return "head failed";
|
|
}
|
|
|
|
if(UsefulBuf_Compare(UsefulBuf_Tail(xxyy, 1), UsefulBuf_FROM_SZ_LITERAL("xyy"))) {
|
|
return "tail failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsNULLC(UsefulBuf_Head(xxyy, 5))) {
|
|
return "head should have failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(xxyy, 5))) {
|
|
return "tail should have failed";
|
|
}
|
|
|
|
if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(NULLUsefulBufC, 0))) {
|
|
return "tail of NULLUsefulBufC is not NULLUsefulBufC";
|
|
}
|
|
|
|
const UsefulBufC TailResult = UsefulBuf_Tail((UsefulBufC){NULL, 100}, 99);
|
|
if(TailResult.ptr != NULL || TailResult.len != 1) {
|
|
return "tail of NULL and length incorrect";
|
|
}
|
|
|
|
if(!UsefulBuf_IsNULLC(UsefulBuf_CopyOffset(Temp2, 100, UsefulBuf_FROM_SZ_LITERAL("yy")))) {
|
|
return "Copy Offset should have failed";
|
|
}
|
|
|
|
// Try to copy into a NULL/empty buf and see failure
|
|
const UsefulBuf UBNull = NULLUsefulBuf;
|
|
if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(UBNull, TempC))) {
|
|
return "Copy to NULL should have failed";
|
|
}
|
|
|
|
|
|
// Try to set a NULL/empty buf; nothing should happen
|
|
UsefulBuf_Set(UBNull, '+'); // This will crash on failure
|
|
|
|
// Copy successfully to a buffer
|
|
UsefulBuf_MAKE_STACK_UB(Temp3, 101);
|
|
if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp3, TempC))) {
|
|
return "Copy should not have failed";
|
|
}
|
|
|
|
static const uint8_t pExpected[] = {
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
};
|
|
UsefulBufC Expected = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpected);
|
|
// This validates comparison for equality and the UsefulBuf_Set
|
|
if(UsefulBuf_Compare(Expected, TempC)) {
|
|
return "Set / Copy / Compare failed";
|
|
}
|
|
|
|
// Compare two empties and expect success
|
|
if(UsefulBuf_Compare(NULLUsefulBufC, NULLUsefulBufC)){
|
|
return "Compare Empties failed";
|
|
}
|
|
|
|
// Compare with empty and expect the first to be larger
|
|
if(UsefulBuf_Compare(Expected, NULLUsefulBufC) <= 0){
|
|
return "Compare with empty failed";
|
|
}
|
|
|
|
|
|
static const uint8_t pExpectedBigger[] = {
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', ',',
|
|
};
|
|
const UsefulBufC ExpectedBigger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedBigger);
|
|
|
|
// Expect -1 when the first arg is smaller
|
|
if(UsefulBuf_Compare(Expected, ExpectedBigger) >= 0){
|
|
return "Compare with bigger";
|
|
}
|
|
|
|
|
|
static const uint8_t pExpectedSmaller[] = {
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '*',
|
|
};
|
|
const UsefulBufC ExpectedSmaller = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedSmaller);
|
|
// Expect +1 when the first arg is larger
|
|
if(UsefulBuf_Compare(Expected, ExpectedSmaller) <= 0){
|
|
return "Compare with smaller";
|
|
}
|
|
|
|
|
|
static const uint8_t pExpectedLonger[] = {
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+'
|
|
};
|
|
const UsefulBufC ExpectedLonger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedLonger);
|
|
|
|
// Expect -1 when the first arg is smaller
|
|
if(UsefulBuf_Compare(Expected, ExpectedLonger) >= 0){
|
|
return "Compare with longer";
|
|
}
|
|
|
|
|
|
static const uint8_t pExpectedShorter[] = {
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
'+', '+', '+', '+', '+', '+', '+', '+', '+',
|
|
};
|
|
const UsefulBufC ExpectedShorter = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedShorter);
|
|
// Expect +1 with the first arg is larger
|
|
if(UsefulBuf_Compare(Expected, ExpectedShorter) <= 0){
|
|
return "Compare with shorter";
|
|
}
|
|
|
|
|
|
if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp, NULLUsefulBufC))) {
|
|
return "Copy null/empty failed";
|
|
}
|
|
|
|
if(UsefulBuf_IsValue(ExpectedShorter, '+') != SIZE_MAX) {
|
|
return "IsValue failed to match all";
|
|
}
|
|
|
|
if(UsefulBuf_IsValue(ExpectedShorter, '-') != 0) {
|
|
return "IsValue should have failed right away";
|
|
}
|
|
|
|
if(UsefulBuf_IsValue(NULLUsefulBufC, 0x00) != 0) {
|
|
return "IsValue failed on NULLUsefulBufC";
|
|
}
|
|
|
|
if(UsefulBuf_IsValue((UsefulBufC){(uint8_t[]){0x00}, 1}, 0x00) != SIZE_MAX) {
|
|
return "IsValue failed finding 0 in one byte of 0";
|
|
}
|
|
|
|
if(UsefulBuf_IsValue((UsefulBufC){(uint8_t[]){0x00}, 1}, 0x01) != 0) {
|
|
return "IsValue failed not finding 1 in one byte of 0";
|
|
}
|
|
|
|
if(UsefulBuf_IsValue(ExpectedSmaller, '+') != ExpectedSmaller.len -1) {
|
|
return "IsValue failed to find final *";
|
|
}
|
|
|
|
// Look for +++++... in +++++... and find it at the beginning
|
|
if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedShorter)){
|
|
return "Failed to find";
|
|
}
|
|
|
|
// look for ++* in ....++* and find it at the end
|
|
static const uint8_t pToFind[] = {'+', '+', '*'};
|
|
const UsefulBufC ToBeFound = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pToFind);
|
|
|
|
if(97 != UsefulBuf_FindBytes(ExpectedSmaller, ToBeFound)){
|
|
return "Failed to find 2";
|
|
}
|
|
|
|
// look for ++* in ....++, and find it near the end
|
|
if(SIZE_MAX != UsefulBuf_FindBytes(ExpectedBigger, ToBeFound)){
|
|
return "Failed to not find";
|
|
}
|
|
|
|
// Look for the whole buffer in itself and succeed.
|
|
if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedLonger)){
|
|
return "Failed to find 3";
|
|
}
|
|
|
|
|
|
const uint8_t pB[] = {0x01, 0x02, 0x03};
|
|
UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
|
|
// Try to map a pointer before
|
|
if(UsefulBuf_PointerToOffset(Boo, pB-1) != SIZE_MAX) {
|
|
return "Didn't error on pointer before";
|
|
}
|
|
|
|
// Try to map a pointer after
|
|
if(UsefulBuf_PointerToOffset(Boo, pB+sizeof(pB)) != SIZE_MAX) {
|
|
return "Didn't error on pointer after";
|
|
}
|
|
|
|
// Try to map a pointer inside
|
|
if(UsefulBuf_PointerToOffset(Boo, pB+1) != 1) {
|
|
return "Incorrect pointer offset";
|
|
}
|
|
|
|
// Try to map a pointer at the start
|
|
if(UsefulBuf_PointerToOffset(Boo, pB) != 0) {
|
|
return "Incorrect pointer offset for start";
|
|
}
|
|
|
|
// Try to map a pointer at the end
|
|
if(UsefulBuf_PointerToOffset(Boo, pB + sizeof(pB)-1) != 2) {
|
|
return "Incorrect pointer offset for end";
|
|
}
|
|
|
|
// Try to map a pointer on a NULL UB
|
|
if(UsefulBuf_PointerToOffset(NULLUsefulBufC, pB ) != SIZE_MAX) {
|
|
return "Incorrect pointer offset for start";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
const char * UIBTest_IntegerFormat(void)
|
|
{
|
|
UsefulOutBuf_MakeOnStack(UOB, 100);
|
|
|
|
const uint32_t u32 = 0x0A0B0C0D; // from https://en.wikipedia.org/wiki/Endianness
|
|
const uint64_t u64 = 1984738472938472;
|
|
const uint16_t u16 = 40000;
|
|
const uint8_t u8 = 9;
|
|
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
|
|
const float f = (float)314.15;
|
|
const double d = 2.1e10;
|
|
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
|
|
|
|
|
|
UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition
|
|
UsefulOutBuf_AppendUint64(&UOB, u64); // Also tests UsefulOutBuf_InsertUint32
|
|
UsefulOutBuf_AppendUint16(&UOB, u16); // Also tests UsefulOutBuf_InsertUint16
|
|
UsefulOutBuf_AppendByte(&UOB, u8);
|
|
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
|
|
UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat
|
|
UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble
|
|
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
|
|
|
|
const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
|
|
if(UsefulBuf_IsNULLC(O))
|
|
return "Couldn't output integers";
|
|
|
|
// from https://en.wikipedia.org/wiki/Endianness
|
|
const uint8_t pExpectedNetworkOrder[4] = {0x0A, 0x0B, 0x0C, 0x0D};
|
|
if(memcmp(O.ptr, pExpectedNetworkOrder, 4)) {
|
|
return "not in network order";
|
|
}
|
|
|
|
UsefulInputBuf UIB;
|
|
|
|
UsefulInputBuf_Init(&UIB, O);
|
|
|
|
if(UsefulInputBuf_Tell(&UIB) != 0) {
|
|
return "UsefulInputBuf_Tell failed";
|
|
}
|
|
|
|
if(UsefulInputBuf_GetUint32(&UIB) != u32) {
|
|
return "u32 out then in failed";
|
|
}
|
|
if(UsefulInputBuf_GetUint64(&UIB) != u64) {
|
|
return "u64 out then in failed";
|
|
}
|
|
if(UsefulInputBuf_GetUint16(&UIB) != u16) {
|
|
return "u16 out then in failed";
|
|
}
|
|
if(UsefulInputBuf_GetByte(&UIB) != u8) {
|
|
return "u8 out then in failed";
|
|
}
|
|
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
|
|
if(UsefulInputBuf_GetFloat(&UIB) != f) {
|
|
return "float out then in failed";
|
|
}
|
|
if(UsefulInputBuf_GetDouble(&UIB) != d) {
|
|
return "double out then in failed";
|
|
}
|
|
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
|
|
|
|
// Reset and go again for a few more tests
|
|
UsefulInputBuf_Init(&UIB, O);
|
|
|
|
const UsefulBufC Four = UsefulInputBuf_GetUsefulBuf(&UIB, 4);
|
|
if(UsefulBuf_IsNULLC(Four)) {
|
|
return "Four is NULL";
|
|
}
|
|
if(UsefulBuf_Compare(Four, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedNetworkOrder))) {
|
|
return "Four compare failed";
|
|
}
|
|
|
|
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
|
|
if(UsefulInputBuf_BytesUnconsumed(&UIB) != 23){
|
|
return "Wrong number of unconsumed bytes";
|
|
}
|
|
|
|
if(!UsefulInputBuf_BytesAvailable(&UIB, 23)){
|
|
return "Wrong number of bytes available I";
|
|
}
|
|
|
|
if(UsefulInputBuf_BytesAvailable(&UIB, 24)){
|
|
return "Wrong number of bytes available II";
|
|
}
|
|
#else /* USEFULBUF_DISABLE_ALL_FLOAT */
|
|
if(UsefulInputBuf_BytesUnconsumed(&UIB) != 11){
|
|
return "Wrong number of unconsumed bytes";
|
|
}
|
|
if(!UsefulInputBuf_BytesAvailable(&UIB, 11)){
|
|
return "Wrong number of bytes available I";
|
|
}
|
|
|
|
if(UsefulInputBuf_BytesAvailable(&UIB, 12)){
|
|
return "Wrong number of bytes available II";
|
|
}
|
|
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
|
|
|
|
UsefulInputBuf_Seek(&UIB, 0);
|
|
|
|
if(UsefulInputBuf_GetError(&UIB)) {
|
|
return "unexpected error after seek";
|
|
}
|
|
|
|
const uint8_t *pGetBytes = (const uint8_t *)UsefulInputBuf_GetBytes(&UIB, 4);
|
|
if(pGetBytes == NULL) {
|
|
return "GetBytes returns NULL";
|
|
}
|
|
|
|
if(memcmp(pGetBytes, pExpectedNetworkOrder, 4)) {
|
|
return "Got wrong bytes";
|
|
}
|
|
|
|
UsefulInputBuf_Seek(&UIB, 28);
|
|
|
|
if(!UsefulInputBuf_GetError(&UIB)) {
|
|
return "expected error after seek";
|
|
}
|
|
|
|
if(UsefulInputBuf_PointerToOffset(&UIB, O.ptr) != 0) {
|
|
return "PointerToOffset not working";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
|
|
const char *UBUTest_CopyUtil(void)
|
|
{
|
|
if(UsefulBufUtil_CopyFloatToUint32(65536.0F) != 0x47800000) {
|
|
return "CopyFloatToUint32 failed";
|
|
}
|
|
|
|
if(UsefulBufUtil_CopyDoubleToUint64(4e-40F) != 0X37C16C2800000000ULL) {
|
|
return "CopyDoubleToUint64 failed";
|
|
}
|
|
|
|
if(UsefulBufUtil_CopyUint64ToDouble(0X37C16C2800000000ULL) != 4e-40F) {
|
|
return "CopyUint64ToDouble failed";
|
|
}
|
|
|
|
if(UsefulBufUtil_CopyUint32ToFloat(0x47800000) != 65536.0F) {
|
|
return "CopyUint32ToFloat failed";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
|
|
|
|
|
|
const char *UBAdvanceTest(void)
|
|
{
|
|
#define ADVANCE_TEST_SIZE 10
|
|
UsefulOutBuf_MakeOnStack(UOB, ADVANCE_TEST_SIZE);
|
|
|
|
UsefulBuf Place = UsefulOutBuf_GetOutPlace(&UOB);
|
|
if(Place.len != 10) {
|
|
return "GetOutPlace wrong size";
|
|
}
|
|
|
|
memset(Place.ptr, 'x', Place.len/2);
|
|
|
|
UsefulOutBuf_Advance(&UOB, Place.len/2);
|
|
|
|
UsefulOutBuf_AppendByte(&UOB, 'y');
|
|
|
|
Place = UsefulOutBuf_GetOutPlace(&UOB);
|
|
if(Place.len != ADVANCE_TEST_SIZE/2 -1 ) {
|
|
return "GetOutPlace wrong size 2";
|
|
}
|
|
|
|
memset(Place.ptr, 'z', Place.len);
|
|
|
|
UsefulOutBuf_Advance(&UOB, Place.len);
|
|
|
|
UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
|
|
|
|
UsefulBuf_Compare(O, UsefulBuf_FROM_SZ_LITERAL("xxxxxyzzzz"));
|
|
|
|
Place = UsefulOutBuf_GetOutPlace(&UOB);
|
|
if(Place.len != 0 || Place.ptr != NULL) {
|
|
return "GetOutPlace not null";
|
|
}
|
|
|
|
if(UsefulOutBuf_GetError(&UOB)) {
|
|
return "GetOutPlace error set";
|
|
}
|
|
|
|
UsefulOutBuf_Advance(&UOB, 1);
|
|
if(!UsefulOutBuf_GetError(&UOB)) {
|
|
return "Advance off end didn't set error";
|
|
}
|
|
|
|
return NULL;
|
|
}
|