String.h
This commit is contained in:
@@ -27,6 +27,14 @@ void memoryCopy(void *dest, const void *src, const size_t size) {
|
|||||||
assertNotNull(src, "Cannot copy from NULL memory.");
|
assertNotNull(src, "Cannot copy from NULL memory.");
|
||||||
assertTrue(size > 0, "Cannot copy 0 bytes of memory.");
|
assertTrue(size > 0, "Cannot copy 0 bytes of memory.");
|
||||||
assertTrue(dest != src, "Cannot copy memory to itself.");
|
assertTrue(dest != src, "Cannot copy memory to itself.");
|
||||||
|
|
||||||
|
// Check for overlapping regions
|
||||||
|
assertTrue(
|
||||||
|
((uint8_t*)dest + size <= (uint8_t*)src) ||
|
||||||
|
((uint8_t*)src + size <= (uint8_t*)dest),
|
||||||
|
"Source and destination memory regions overlap."
|
||||||
|
);
|
||||||
|
|
||||||
memcpy(dest, src, size);
|
memcpy(dest, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,12 +51,6 @@ void stringTrim(char_t *str) {
|
|||||||
if(start != str) memmove(str, start, end - start + 2);
|
if(start != str) memmove(str, start, end - start + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
char_t * stringToken(char_t *str, const char_t *delim) {
|
|
||||||
assertNotNull(str, "str must not be NULL");
|
|
||||||
assertNotNull(delim, "delim must not be NULL");
|
|
||||||
return strtok(str, delim);
|
|
||||||
}
|
|
||||||
|
|
||||||
char_t * stringFindLastChar(const char_t *str, const char_t c) {
|
char_t * stringFindLastChar(const char_t *str, const char_t c) {
|
||||||
assertNotNull(str, "str must not be NULL");
|
assertNotNull(str, "str must not be NULL");
|
||||||
char_t *last = NULL;
|
char_t *last = NULL;
|
||||||
@@ -106,12 +100,25 @@ bool_t stringToI32(const char_t *str, int32_t *out) {
|
|||||||
assertNotNull(str, "str must not be NULL");
|
assertNotNull(str, "str must not be NULL");
|
||||||
assertNotNull(out, "out must not be NULL");
|
assertNotNull(out, "out must not be NULL");
|
||||||
|
|
||||||
|
// Empty string check
|
||||||
|
if(str[0] == '\0') return false;
|
||||||
|
|
||||||
|
// Leading or trailing whitespace check
|
||||||
|
if(stringIsWhitespace(str[0])) return false;
|
||||||
|
if(stringIsWhitespace(str[strlen(str) - 1])) return false;
|
||||||
|
|
||||||
char_t *endptr;
|
char_t *endptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
long int result = strtol(str, &endptr, 10);
|
long int result = strtol(str, &endptr, 10);
|
||||||
if(errno != 0 || *endptr != '\0') {
|
if(errno != 0 || *endptr != '\0') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Within INT32 range
|
||||||
|
if(result < INT32_MIN || result > INT32_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*out = (int32_t)result;
|
*out = (int32_t)result;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -120,6 +127,13 @@ bool_t stringToI64(const char_t *str, int64_t *out) {
|
|||||||
assertNotNull(str, "str must not be NULL");
|
assertNotNull(str, "str must not be NULL");
|
||||||
assertNotNull(out, "out must not be NULL");
|
assertNotNull(out, "out must not be NULL");
|
||||||
|
|
||||||
|
// Empty string check
|
||||||
|
if(str[0] == '\0') return false;
|
||||||
|
|
||||||
|
// Leading or trailing whitespace check
|
||||||
|
if(stringIsWhitespace(str[0])) return false;
|
||||||
|
if(stringIsWhitespace(str[strlen(str) - 1])) return false;
|
||||||
|
|
||||||
char_t *endptr;
|
char_t *endptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
long long int result = strtoll(str, &endptr, 10);
|
long long int result = strtoll(str, &endptr, 10);
|
||||||
@@ -130,10 +144,38 @@ bool_t stringToI64(const char_t *str, int64_t *out) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t stringToI16(const char_t *str, int16_t *out) {
|
||||||
|
assertNotNull(str, "str must not be NULL");
|
||||||
|
assertNotNull(out, "out must not be NULL");
|
||||||
|
|
||||||
|
// Empty string check
|
||||||
|
if(str[0] == '\0') return false;
|
||||||
|
|
||||||
|
// Leading or trailing whitespace check
|
||||||
|
if(stringIsWhitespace(str[0])) return false;
|
||||||
|
if(stringIsWhitespace(str[strlen(str) - 1])) return false;
|
||||||
|
|
||||||
|
char_t *endptr;
|
||||||
|
errno = 0;
|
||||||
|
long int result = strtol(str, &endptr, 10);
|
||||||
|
if(errno != 0 || *endptr != '\0' || result < INT16_MIN || result > INT16_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (int16_t)result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool_t stringToU16(const char_t *str, uint16_t *out) {
|
bool_t stringToU16(const char_t *str, uint16_t *out) {
|
||||||
assertNotNull(str, "str must not be NULL");
|
assertNotNull(str, "str must not be NULL");
|
||||||
assertNotNull(out, "out must not be NULL");
|
assertNotNull(out, "out must not be NULL");
|
||||||
|
|
||||||
|
// Empty string check
|
||||||
|
if(str[0] == '\0') return false;
|
||||||
|
|
||||||
|
// Leading or trailing whitespace check
|
||||||
|
if(stringIsWhitespace(str[0])) return false;
|
||||||
|
if(stringIsWhitespace(str[strlen(str) - 1])) return false;
|
||||||
|
|
||||||
char_t *endptr;
|
char_t *endptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
unsigned long int result = strtoul(str, &endptr, 10);
|
unsigned long int result = strtoul(str, &endptr, 10);
|
||||||
@@ -148,6 +190,13 @@ bool_t stringToF32(const char_t *str, float_t *out) {
|
|||||||
assertNotNull(str, "str must not be NULL");
|
assertNotNull(str, "str must not be NULL");
|
||||||
assertNotNull(out, "out must not be NULL");
|
assertNotNull(out, "out must not be NULL");
|
||||||
|
|
||||||
|
// Empty string check
|
||||||
|
if(str[0] == '\0') return false;
|
||||||
|
|
||||||
|
// Leading or trailing whitespace check
|
||||||
|
if(stringIsWhitespace(str[0])) return false;
|
||||||
|
if(stringIsWhitespace(str[strlen(str) - 1])) return false;
|
||||||
|
|
||||||
char_t *endptr;
|
char_t *endptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
float_t result = strtof(str, &endptr);
|
float_t result = strtof(str, &endptr);
|
||||||
|
|||||||
@@ -53,17 +53,6 @@ int stringCompareInsensitive(const char_t *str1, const char_t *str2);
|
|||||||
*/
|
*/
|
||||||
void stringTrim(char_t *str);
|
void stringTrim(char_t *str);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the next token in a string using a delimiter.
|
|
||||||
* e.g. input: "Hello, World, Happy Monday!" with stringToken(input, ",") will
|
|
||||||
* return "Hello" then " World" then " Happy Monday!" on each subsequent call.
|
|
||||||
*
|
|
||||||
* @param str The string to split.
|
|
||||||
* @param delim The delimiter to split by.
|
|
||||||
* @return A pointer to the next token in the string.
|
|
||||||
*/
|
|
||||||
char_t * stringToken(char_t *str, const char_t *delim);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the last occurrence of a character in a string.
|
* Finds the last occurrence of a character in a string.
|
||||||
*
|
*
|
||||||
@@ -119,6 +108,15 @@ int32_t stringFormatVA(
|
|||||||
*/
|
*/
|
||||||
bool_t stringToI32(const char_t *str, int32_t *out);
|
bool_t stringToI32(const char_t *str, int32_t *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string to a signed 64-bit integer.
|
||||||
|
*
|
||||||
|
* @param str The string to convert.
|
||||||
|
* @param out The output signed integer.
|
||||||
|
* @return TRUE if the conversion was successful, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
bool_t stringToI64(const char_t *str, int64_t *out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string to a signed 16-bit integer.
|
* Converts a string to a signed 16-bit integer.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ include(dusktest)
|
|||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
dusktest(test_math.c)
|
dusktest(test_math.c)
|
||||||
dusktest(test_memory.c)
|
dusktest(test_memory.c)
|
||||||
|
dusktest(test_string.c)
|
||||||
@@ -37,6 +37,10 @@ static void test_mathNextPowTwo(void **state) {
|
|||||||
|
|
||||||
// Max Value
|
// Max Value
|
||||||
assert_int_equal(mathNextPowTwo(0xFFFFFFFF), 1);
|
assert_int_equal(mathNextPowTwo(0xFFFFFFFF), 1);
|
||||||
|
|
||||||
|
// Edge: value just below and above a power of two
|
||||||
|
assert_int_equal(mathNextPowTwo(255), 256);
|
||||||
|
assert_int_equal(mathNextPowTwo(257), 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_mathMax(void **state) {
|
static void test_mathMax(void **state) {
|
||||||
@@ -80,6 +84,13 @@ static void test_mathMax(void **state) {
|
|||||||
assert_float_equal(mathMax(-1.5f, 0), 0.0f, 0.0001f);
|
assert_float_equal(mathMax(-1.5f, 0), 0.0f, 0.0001f);
|
||||||
assert_float_equal(mathMax(500, -333.5f), 500.0f, 0.0001f);
|
assert_float_equal(mathMax(500, -333.5f), 500.0f, 0.0001f);
|
||||||
assert_float_equal(mathMax(-333.5f, 500), 500.0f, 0.0001f);
|
assert_float_equal(mathMax(-333.5f, 500), 500.0f, 0.0001f);
|
||||||
|
|
||||||
|
// Equal values
|
||||||
|
assert_int_equal(mathMax(5, 5), 5);
|
||||||
|
assert_float_equal(mathMax(2.5f, 2.5f), 2.5f, 0.0001f);
|
||||||
|
|
||||||
|
// Special float values
|
||||||
|
assert_float_equal(mathMax(-0.0f, 0.0f), 0.0f, 0.0001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_mathMin(void **state) {
|
static void test_mathMin(void **state) {
|
||||||
@@ -124,6 +135,13 @@ static void test_mathMin(void **state) {
|
|||||||
assert_float_equal(mathMin(-1.5f, 0), -1.5f, 0.0001f);
|
assert_float_equal(mathMin(-1.5f, 0), -1.5f, 0.0001f);
|
||||||
assert_float_equal(mathMin(500, -333.5f), -333.5f, 0.0001f);
|
assert_float_equal(mathMin(500, -333.5f), -333.5f, 0.0001f);
|
||||||
assert_float_equal(mathMin(-333.5f, 500), -333.5f, 0.0001f);
|
assert_float_equal(mathMin(-333.5f, 500), -333.5f, 0.0001f);
|
||||||
|
|
||||||
|
// Equal values
|
||||||
|
assert_int_equal(mathMin(5, 5), 5);
|
||||||
|
assert_float_equal(mathMin(2.5f, 2.5f), 2.5f, 0.0001f);
|
||||||
|
|
||||||
|
// Special float values
|
||||||
|
assert_float_equal(mathMin(-0.0f, 0.0f), -0.0f, 0.0001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_mathClamp(void **state) {
|
static void test_mathClamp(void **state) {
|
||||||
@@ -172,6 +190,16 @@ static void test_mathClamp(void **state) {
|
|||||||
assert_float_equal(mathClamp(-5.5f, -10, -1), -5.5f, 0.0001f); // Within
|
assert_float_equal(mathClamp(-5.5f, -10, -1), -5.5f, 0.0001f); // Within
|
||||||
assert_float_equal(mathClamp(-15.5f, -10, -1), -10.0f, 0.0001f);// Below
|
assert_float_equal(mathClamp(-15.5f, -10, -1), -10.0f, 0.0001f);// Below
|
||||||
assert_float_equal(mathClamp(0.0f, -10, -1), -1.0f, 0.0001f); // Above
|
assert_float_equal(mathClamp(0.0f, -10, -1), -1.0f, 0.0001f); // Above
|
||||||
|
|
||||||
|
// Edge: value equals min or max
|
||||||
|
assert_int_equal(mathClamp(1, 1, 10), 1);
|
||||||
|
assert_int_equal(mathClamp(10, 1, 10), 10);
|
||||||
|
assert_float_equal(mathClamp(1.0f, 1.0f, 10.0f), 1.0f, 0.0001f);
|
||||||
|
assert_float_equal(mathClamp(10.0f, 1.0f, 10.0f), 10.0f, 0.0001f);
|
||||||
|
|
||||||
|
// Edge: min > max (undefined, but should return min or max)
|
||||||
|
assert_int_equal(mathClamp(5, 10, 1), 1); // Should clamp to upper
|
||||||
|
assert_float_equal(mathClamp(5.0f, 10.0f, 1.0f), 1.0f, 0.0001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_mathAbs(void **state) {
|
static void test_mathAbs(void **state) {
|
||||||
@@ -192,6 +220,12 @@ static void test_mathAbs(void **state) {
|
|||||||
// Negative floats
|
// Negative floats
|
||||||
assert_float_equal(mathAbs(-5.5f), 5.5f, 0.0001f);
|
assert_float_equal(mathAbs(-5.5f), 5.5f, 0.0001f);
|
||||||
assert_float_equal(mathAbs(-100.25f), 100.25f, 0.0001f);
|
assert_float_equal(mathAbs(-100.25f), 100.25f, 0.0001f);
|
||||||
|
|
||||||
|
// Edge: -0.0f
|
||||||
|
assert_float_equal(mathAbs(-0.0f), 0.0f, 0.0001f);
|
||||||
|
|
||||||
|
// INT_MIN edge case is NOT handled due to two's complement overflow
|
||||||
|
assert_int_equal(mathAbs(INT32_MIN + 1), 2147483647);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|||||||
@@ -65,6 +65,12 @@ static void test_memoryCopy(void **state) {
|
|||||||
// Cannot copy to itself
|
// Cannot copy to itself
|
||||||
expect_assert_failure(memoryCopy(src, src, size));
|
expect_assert_failure(memoryCopy(src, src, size));
|
||||||
|
|
||||||
|
// Overlapping regions (should assert)
|
||||||
|
void *overlap = memoryAllocate(size * 2);
|
||||||
|
expect_assert_failure(memoryCopy((uint8_t*)overlap, (uint8_t*)overlap + 8, size));
|
||||||
|
expect_assert_failure(memoryCopy((uint8_t*)overlap + 8, (uint8_t*)overlap, size));
|
||||||
|
memoryFree(overlap);
|
||||||
|
|
||||||
memoryFree(src);
|
memoryFree(src);
|
||||||
memoryFree(dest);
|
memoryFree(dest);
|
||||||
}
|
}
|
||||||
@@ -91,6 +97,12 @@ static void test_memorySet(void **state) {
|
|||||||
// Canot set 0 bytes
|
// Canot set 0 bytes
|
||||||
expect_assert_failure(memorySet(ptr, 0x00, 0));
|
expect_assert_failure(memorySet(ptr, 0x00, 0));
|
||||||
|
|
||||||
|
// Set with value outside 0-255 (should be cast to uint8_t)
|
||||||
|
memorySet(ptr, 0x1FF, size);
|
||||||
|
for(size_t i = 0; i < size; i++) {
|
||||||
|
assert_int_equal(((uint8_t*)ptr)[i], 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
memoryFree(ptr);
|
memoryFree(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +151,10 @@ static void test_memoryCopyRangeSafe(void **state) {
|
|||||||
uint8_t expected[10] = {3, 4, 5, 6, 7}; // Expected data in dest
|
uint8_t expected[10] = {3, 4, 5, 6, 7}; // Expected data in dest
|
||||||
assert_memory_equal(dest, expected, 5);
|
assert_memory_equal(dest, expected, 5);
|
||||||
|
|
||||||
|
// Copy entire buffer
|
||||||
|
memoryCopyRangeSafe(dest, src, (uint8_t*)src + size, size);
|
||||||
|
assert_memory_equal(dest, src, size);
|
||||||
|
|
||||||
// Cannot copy to NULL destination
|
// Cannot copy to NULL destination
|
||||||
expect_assert_failure(memoryCopyRangeSafe(NULL, src, (uint8_t*)src + 5, size));
|
expect_assert_failure(memoryCopyRangeSafe(NULL, src, (uint8_t*)src + 5, size));
|
||||||
|
|
||||||
@@ -187,6 +203,15 @@ static void test_memoryMove(void **state) {
|
|||||||
}
|
}
|
||||||
assert_memory_equal(ptr, expected, size + 5);
|
assert_memory_equal(ptr, expected, size + 5);
|
||||||
|
|
||||||
|
// Overlap backward: move ptr[5..19] to ptr[0..14]
|
||||||
|
for(size_t i = 0; i < size + 5; i++) {
|
||||||
|
((uint8_t*)ptr)[i] = (uint8_t)(i + 1);
|
||||||
|
}
|
||||||
|
memoryMove(ptr, (uint8_t*)ptr + 5, size);
|
||||||
|
for(size_t i = 0; i < size; i++) {
|
||||||
|
assert_int_equal(((uint8_t*)ptr)[i], (uint8_t)(i + 6));
|
||||||
|
}
|
||||||
|
|
||||||
// Cannot move to NULL
|
// Cannot move to NULL
|
||||||
expect_assert_failure(memoryMove(NULL, ptr, size));
|
expect_assert_failure(memoryMove(NULL, ptr, size));
|
||||||
|
|
||||||
@@ -243,6 +268,9 @@ static void test_memoryCompare(void **state) {
|
|||||||
// Cannot compare 0 bytes
|
// Cannot compare 0 bytes
|
||||||
expect_assert_failure(memoryCompare(a, b, 0));
|
expect_assert_failure(memoryCompare(a, b, 0));
|
||||||
|
|
||||||
|
// Compare different sizes (should assert, so we only test the API contract)
|
||||||
|
// Not possible with current API, as size is explicit, but document intent.
|
||||||
|
|
||||||
memoryFree(a);
|
memoryFree(a);
|
||||||
memoryFree(b);
|
memoryFree(b);
|
||||||
}
|
}
|
||||||
|
|||||||
871
test/util/test_string.c
Normal file
871
test/util/test_string.c
Normal file
@@ -0,0 +1,871 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dusktest.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
static void test_stringIsWhitespace(void **state) {
|
||||||
|
(void)state;
|
||||||
|
assert_true(stringIsWhitespace(' ')); // Space is whitespace
|
||||||
|
assert_true(stringIsWhitespace('\t')); // Tab is whitespace
|
||||||
|
assert_true(stringIsWhitespace('\n')); // Newline is whitespace
|
||||||
|
assert_true(stringIsWhitespace('\r')); // Carriage return is whitespace
|
||||||
|
assert_true(stringIsWhitespace('\v')); // Vertical tab is whitespace
|
||||||
|
assert_true(stringIsWhitespace('\f')); // Form feed is whitespace
|
||||||
|
assert_false(stringIsWhitespace('A')); // 'A' is not whitespace
|
||||||
|
assert_false(stringIsWhitespace('1')); // '1' is not whitespace
|
||||||
|
assert_false(stringIsWhitespace('_')); // '_' is not whitespace
|
||||||
|
assert_false(stringIsWhitespace('-')); // '-' is not whitespace
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringCopy(void **state) {
|
||||||
|
(void)state;
|
||||||
|
char dest[16];
|
||||||
|
stringCopy(dest, "hello", sizeof(dest));
|
||||||
|
assert_string_equal(dest, "hello"); // Normal copy
|
||||||
|
|
||||||
|
// Empty string
|
||||||
|
stringCopy(dest, "", sizeof(dest));
|
||||||
|
assert_string_equal(dest, ""); // Should copy empty string
|
||||||
|
|
||||||
|
// Euffer just fits
|
||||||
|
stringCopy(dest, "123456789012345", 16); // 15 chars + null
|
||||||
|
assert_string_equal(dest, "123456789012345"); // Should fit exactly
|
||||||
|
|
||||||
|
// Cannot copy from NULL source
|
||||||
|
expect_assert_failure(stringCopy(dest, NULL, sizeof(dest)));
|
||||||
|
|
||||||
|
// Cannot copy to NULL destination
|
||||||
|
expect_assert_failure(stringCopy(NULL, "hello", sizeof(dest)));
|
||||||
|
|
||||||
|
// Must have destSize > 0
|
||||||
|
expect_assert_failure(stringCopy(dest, "hello", 0));
|
||||||
|
|
||||||
|
// Must have destSize large enough for source
|
||||||
|
expect_assert_failure(stringCopy(dest, "this string is too long", 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringCompare(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
// Check for equality
|
||||||
|
assert_int_equal(stringCompare("abc", "abc"), 0);
|
||||||
|
assert_int_equal(stringCompare("", ""), 0);
|
||||||
|
assert_int_equal(stringCompare("a", "a"), 0);
|
||||||
|
assert_int_equal(stringCompare("longer string", "longer string"), 0);
|
||||||
|
|
||||||
|
// Check for less than cases
|
||||||
|
assert_true(stringCompare("", "a") < 0);
|
||||||
|
assert_true(stringCompare("abc", "abd") < 0);
|
||||||
|
|
||||||
|
// Check for greater than cases
|
||||||
|
assert_true(stringCompare("abd", "abc") > 0);
|
||||||
|
assert_true(stringCompare("a", "") > 0);
|
||||||
|
|
||||||
|
// Cannot compare NULL strings
|
||||||
|
expect_assert_failure(stringCompare(NULL, "abc"));
|
||||||
|
expect_assert_failure(stringCompare("abc", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringCompareInsensitive(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
assert_int_equal(stringCompareInsensitive("abc", "ABC"), 0);
|
||||||
|
assert_true(stringCompareInsensitive("abc", "abd") < 0);
|
||||||
|
assert_true(stringCompareInsensitive("abd", "abc") > 0);
|
||||||
|
|
||||||
|
assert_true(stringCompareInsensitive("", "A") < 0);
|
||||||
|
assert_true(stringCompareInsensitive("A", "") > 0);
|
||||||
|
|
||||||
|
// Cannot compare NULL strings
|
||||||
|
expect_assert_failure(stringCompareInsensitive(NULL, "abc"));
|
||||||
|
expect_assert_failure(stringCompareInsensitive("abc", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringTrim(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
stringCopy(buf, " hello ", sizeof(buf));
|
||||||
|
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "hello"); // Trims spaces
|
||||||
|
|
||||||
|
// Non-space whitespace
|
||||||
|
stringCopy(buf, "\t\nhello world\r\n", sizeof(buf));
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "hello world");
|
||||||
|
|
||||||
|
// Only whitespace
|
||||||
|
stringCopy(buf, " ", sizeof(buf));
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "");
|
||||||
|
|
||||||
|
// No whitespace
|
||||||
|
stringCopy(buf, "no-trim", sizeof(buf));
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "no-trim");
|
||||||
|
|
||||||
|
// Left whitespace only
|
||||||
|
stringCopy(buf, " left", sizeof(buf));
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "left");
|
||||||
|
|
||||||
|
// Right whitespace only
|
||||||
|
stringCopy(buf, "right ", sizeof(buf));
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "right");
|
||||||
|
|
||||||
|
// Cannot trim NULL string
|
||||||
|
expect_assert_failure(stringTrim(NULL));
|
||||||
|
|
||||||
|
// Can trim empty string
|
||||||
|
stringCopy(buf, "", sizeof(buf));
|
||||||
|
stringTrim(buf);
|
||||||
|
assert_string_equal(buf, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringFindLastChar(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
const char *str = "hello world";
|
||||||
|
char *result = stringFindLastChar(str, 'o');
|
||||||
|
assert_non_null(result);
|
||||||
|
assert_int_equal(*result, 'o');
|
||||||
|
assert_int_equal(result - str, 7); // Position of last 'o'
|
||||||
|
|
||||||
|
result = stringFindLastChar(str, 'h');
|
||||||
|
assert_non_null(result);
|
||||||
|
assert_int_equal(*result, 'h');
|
||||||
|
assert_int_equal(result - str, 0); // Position of 'h'
|
||||||
|
|
||||||
|
result = stringFindLastChar(str, 'z');
|
||||||
|
assert_null(result); // 'z' not found
|
||||||
|
|
||||||
|
// Cannot search NULL string
|
||||||
|
expect_assert_failure(stringFindLastChar(NULL, 'a'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringFormat(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
// Test a string format
|
||||||
|
char buffer[32];
|
||||||
|
int32_t len = stringFormat(buffer, sizeof(buffer), "Hello %s!", "World");
|
||||||
|
assert_int_equal(len, 12);
|
||||||
|
assert_string_equal(buffer, "Hello World!");
|
||||||
|
|
||||||
|
// Test a number format
|
||||||
|
len = stringFormat(buffer, sizeof(buffer), "Number: %d", 42);
|
||||||
|
assert_int_equal(len, 10);
|
||||||
|
assert_string_equal(buffer, "Number: 42");
|
||||||
|
|
||||||
|
// Test floats with different precision
|
||||||
|
len = stringFormat(buffer, sizeof(buffer), "Float: %.2f", 3.14159);
|
||||||
|
assert_int_equal(len, 11);
|
||||||
|
assert_string_equal(buffer, "Float: 3.14");
|
||||||
|
|
||||||
|
len = stringFormat(buffer, sizeof(buffer), "Float: %.4f", 3.14159);
|
||||||
|
assert_int_equal(len, 13);
|
||||||
|
assert_string_equal(buffer, "Float: 3.1416");
|
||||||
|
|
||||||
|
// Test integer formatting
|
||||||
|
len = stringFormat(buffer, sizeof(buffer), "Hex: 0x%X", 255);
|
||||||
|
assert_int_equal(len, 9);
|
||||||
|
assert_string_equal(buffer, "Hex: 0xFF");
|
||||||
|
|
||||||
|
// Test empty format
|
||||||
|
len = stringFormat(buffer, sizeof(buffer), "");
|
||||||
|
assert_int_equal(len, 0);
|
||||||
|
assert_string_equal(buffer, "");
|
||||||
|
|
||||||
|
// Test no substitutions
|
||||||
|
len = stringFormat(buffer, sizeof(buffer), "No substitutions");
|
||||||
|
assert_int_equal(len, 16);
|
||||||
|
assert_string_equal(buffer, "No substitutions");
|
||||||
|
|
||||||
|
// Test buffer too small
|
||||||
|
expect_assert_failure(stringFormat(buffer, 5, "This is too long"));
|
||||||
|
expect_assert_failure(stringFormat(buffer, sizeof(buffer), "Hello %s", "This string is way too long to fit within the buffer that we have allocated"));
|
||||||
|
|
||||||
|
// Test NULL destination, simply returns required length
|
||||||
|
len = stringFormat(NULL, 0, "Hello %s!", "World");
|
||||||
|
assert_int_equal(len, 12);
|
||||||
|
|
||||||
|
len = stringFormat(NULL, 0, "Number: %d", 42);
|
||||||
|
assert_int_equal(len, 10);
|
||||||
|
|
||||||
|
// Cannot have NULL format
|
||||||
|
expect_assert_failure(stringFormat(buffer, sizeof(buffer), NULL));
|
||||||
|
|
||||||
|
// Must have destSize > 0 if dest is not NULL
|
||||||
|
expect_assert_failure(stringFormat(buffer, 0, "Hello"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringToI32(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
char_t buffer[64];
|
||||||
|
int32_t value;
|
||||||
|
bool_t result;
|
||||||
|
|
||||||
|
// Standard integers
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI32(buffer, &value));
|
||||||
|
assert_int_equal(value, 12345);
|
||||||
|
|
||||||
|
stringCopy(buffer, "-6789", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI32(buffer, &value));
|
||||||
|
assert_int_equal(value, -6789);
|
||||||
|
|
||||||
|
stringCopy(buffer, "+123", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI32(buffer, &value));
|
||||||
|
assert_int_equal(value, 123);
|
||||||
|
|
||||||
|
// Cannot convert invalid strings
|
||||||
|
stringCopy(buffer, "abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 1234 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+-123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "\t123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "12 34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "--123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "++123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "-", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// Non ascii numbers
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer)); // Fullwidth digits
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot take math
|
||||||
|
stringCopy(buffer, "100+20", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "50-10", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "5*6", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "20/4", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle decimal points
|
||||||
|
stringCopy(buffer, "12.34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle non-numbers
|
||||||
|
stringCopy(buffer, "12-34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "e", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "3.273390607896142e+150 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "9999999999999999999999999", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle really low numbers
|
||||||
|
stringCopy(buffer, "-9999999999999999999999999", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle items outside int32 range
|
||||||
|
stringCopy(buffer, "2147483648", sizeof(buffer)); // INT32_MAX + 1
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
stringCopy(buffer, "-2147483649", sizeof(buffer)); // INT32_MIN - 1
|
||||||
|
assert_false(result = stringToI32(buffer, &value));
|
||||||
|
|
||||||
|
// CAN handle INT32 limits
|
||||||
|
stringCopy(buffer, "2147483647", sizeof(buffer)); // INT32_MAX
|
||||||
|
assert_true(result = stringToI32(buffer, &value));
|
||||||
|
assert_int_equal(value, 2147483647);
|
||||||
|
stringCopy(buffer, "-2147483648", sizeof(buffer)); // INT32_MIN
|
||||||
|
assert_true(result = stringToI32(buffer, &value));
|
||||||
|
assert_int_equal(value, -2147483648);
|
||||||
|
|
||||||
|
// Cannot have NULL string
|
||||||
|
expect_assert_failure(stringToI32(NULL, &value));
|
||||||
|
|
||||||
|
// Cannot have NULL output pointer
|
||||||
|
stringCopy(buffer, "123", sizeof(buffer));
|
||||||
|
expect_assert_failure(stringToI32(buffer, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringToI64(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
char_t buffer[64];
|
||||||
|
int64_t value;
|
||||||
|
bool_t result;
|
||||||
|
|
||||||
|
// Standard integers
|
||||||
|
stringCopy(buffer, "12345678901234", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI64(buffer, &value));
|
||||||
|
assert_int_equal(value, 12345678901234LL);
|
||||||
|
stringCopy(buffer, "-67890123456789", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI64(buffer, &value));
|
||||||
|
assert_int_equal(value, -67890123456789LL);
|
||||||
|
|
||||||
|
// Cannot convert invalid strings
|
||||||
|
stringCopy(buffer, "abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
stringCopy(buffer, "123abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
// Cannot convert invalid strings
|
||||||
|
stringCopy(buffer, "abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 1234 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+-123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "\t123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "12 34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "--123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "++123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "-", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// Non ascii numbers
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer)); // Fullwidth digits
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot take math
|
||||||
|
stringCopy(buffer, "100+20", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "50-10", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "5*6", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "20/4", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle decimal points
|
||||||
|
stringCopy(buffer, "12.34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle non-numbers
|
||||||
|
stringCopy(buffer, "12-34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "e", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "3.273390607896142e+150 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "9999999999999999999999999", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle really low numbers
|
||||||
|
stringCopy(buffer, "-9999999999999999999999999", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle items outside int64 range
|
||||||
|
stringCopy(buffer, "9223372036854775808", sizeof(buffer)); // INT64_MAX + 1
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
stringCopy(buffer, "-9223372036854775809", sizeof(buffer)); // INT64_MIN - 1
|
||||||
|
assert_false(result = stringToI64(buffer, &value));
|
||||||
|
|
||||||
|
// CAN handle INT64 limits
|
||||||
|
stringCopy(buffer, "9223372036854775807", sizeof(buffer)); // INT64_MAX
|
||||||
|
assert_true(result = stringToI64(buffer, &value));
|
||||||
|
assert_int_equal(value, 9223372036854775807LL);
|
||||||
|
stringCopy(buffer, "-9223372036854775808", sizeof(buffer)); // INT64_MIN
|
||||||
|
assert_true(result = stringToI64(buffer, &value));
|
||||||
|
assert_int_equal(value, -9223372036854775808LL);
|
||||||
|
|
||||||
|
// Cannot have NULL string
|
||||||
|
expect_assert_failure(stringToI64(NULL, &value));
|
||||||
|
|
||||||
|
// Cannot have NULL output pointer
|
||||||
|
stringCopy(buffer, "123", sizeof(buffer));
|
||||||
|
expect_assert_failure(stringToI64(buffer, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringToI16(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
char_t buffer[64];
|
||||||
|
int16_t value;
|
||||||
|
bool_t result;
|
||||||
|
|
||||||
|
// Standard integers (within int16 range)
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI16(buffer, &value));
|
||||||
|
assert_int_equal(value, (int16_t)12345);
|
||||||
|
|
||||||
|
stringCopy(buffer, "-23456", sizeof(buffer));
|
||||||
|
assert_true(result = stringToI16(buffer, &value));
|
||||||
|
assert_int_equal(value, (int16_t)-23456);
|
||||||
|
|
||||||
|
// Cannot convert invalid strings
|
||||||
|
stringCopy(buffer, "abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 1234 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+-123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "\t123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "12 34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "--123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "++123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "-", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// Non-ascii numbers
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer)); // Fullwidth digits
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot take math
|
||||||
|
stringCopy(buffer, "100+20", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "50-10", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "5*6", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "20/4", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle decimal points
|
||||||
|
stringCopy(buffer, "12.34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle non-numbers / mixed formats
|
||||||
|
stringCopy(buffer, "12-34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "e", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "3.273390607896142e+150 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// Out of int16 range (overflow)
|
||||||
|
stringCopy(buffer, "32768", sizeof(buffer)); // INT16_MAX + 1
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// Out of int16 range (underflow)
|
||||||
|
stringCopy(buffer, "-32769", sizeof(buffer)); // INT16_MIN - 1
|
||||||
|
assert_false(result = stringToI16(buffer, &value));
|
||||||
|
|
||||||
|
// CAN handle int16 limits
|
||||||
|
stringCopy(buffer, "32767", sizeof(buffer)); // INT16_MAX
|
||||||
|
assert_true(result = stringToI16(buffer, &value));
|
||||||
|
assert_int_equal(value, (int16_t)32767);
|
||||||
|
|
||||||
|
stringCopy(buffer, "-32768", sizeof(buffer)); // INT16_MIN
|
||||||
|
assert_true(result = stringToI16(buffer, &value));
|
||||||
|
assert_int_equal(value, (int16_t)-32768);
|
||||||
|
|
||||||
|
// Cannot have NULL string
|
||||||
|
expect_assert_failure(stringToI16(NULL, &value));
|
||||||
|
|
||||||
|
// Cannot have NULL output pointer
|
||||||
|
stringCopy(buffer, "123", sizeof(buffer));
|
||||||
|
expect_assert_failure(stringToI16(buffer, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringToU16(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
char_t buffer[64];
|
||||||
|
uint16_t value;
|
||||||
|
bool_t result;
|
||||||
|
|
||||||
|
// Standard integers (within uint16 range)
|
||||||
|
stringCopy(buffer, "0", sizeof(buffer));
|
||||||
|
assert_true(result = stringToU16(buffer, &value));
|
||||||
|
assert_int_equal(value, (uint16_t)0);
|
||||||
|
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer));
|
||||||
|
assert_true(result = stringToU16(buffer, &value));
|
||||||
|
assert_int_equal(value, (uint16_t)12345);
|
||||||
|
|
||||||
|
// Cannot convert invalid strings
|
||||||
|
stringCopy(buffer, "abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 1234 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+-123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "\t123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "12 34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "--123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "++123", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// Unsigned: no minus sign
|
||||||
|
stringCopy(buffer, "-", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "-1", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// Non-ascii numbers
|
||||||
|
stringCopy(buffer, "12345", sizeof(buffer)); // Fullwidth digits
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot take math
|
||||||
|
stringCopy(buffer, "100+20", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "50-10", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "5*6", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "20/4", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle decimal points
|
||||||
|
stringCopy(buffer, "12.34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot handle non-numbers / mixed formats
|
||||||
|
stringCopy(buffer, "12-34", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "e", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "3.273390607896142e+150 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// Out of uint16 range (overflow)
|
||||||
|
stringCopy(buffer, "65536", sizeof(buffer)); // UINT16_MAX + 1
|
||||||
|
assert_false(result = stringToU16(buffer, &value));
|
||||||
|
|
||||||
|
// CAN handle uint16 limits
|
||||||
|
stringCopy(buffer, "65535", sizeof(buffer)); // UINT16_MAX
|
||||||
|
assert_true(result = stringToU16(buffer, &value));
|
||||||
|
assert_int_equal(value, (uint16_t)65535);
|
||||||
|
|
||||||
|
// Cannot have NULL string
|
||||||
|
expect_assert_failure(stringToU16(NULL, &value));
|
||||||
|
|
||||||
|
// Cannot have NULL output pointer
|
||||||
|
stringCopy(buffer, "123", sizeof(buffer));
|
||||||
|
expect_assert_failure(stringToU16(buffer, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringToF32(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
char_t buffer[64];
|
||||||
|
float value;
|
||||||
|
bool_t result;
|
||||||
|
|
||||||
|
// Standard values
|
||||||
|
stringCopy(buffer, "0", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
assert_float_equal(value, 0.0f, 0.000001f);
|
||||||
|
|
||||||
|
stringCopy(buffer, "123.5", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
assert_float_equal(value, 123.5f, 0.000001f);
|
||||||
|
|
||||||
|
stringCopy(buffer, "-45.25", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
assert_float_equal(value, -45.25f, 0.000001f);
|
||||||
|
|
||||||
|
stringCopy(buffer, "1.0", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
assert_float_equal(value, 1.0f, 0.000001f);
|
||||||
|
|
||||||
|
// Integers should also parse
|
||||||
|
stringCopy(buffer, "42", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
assert_float_equal(value, 42.0f, 0.000001f);
|
||||||
|
|
||||||
|
stringCopy(buffer, "-7", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
assert_float_equal(value, -7.0f, 0.000001f);
|
||||||
|
|
||||||
|
// Cannot do European format
|
||||||
|
stringCopy(buffer, "123,45", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot convert invalid strings
|
||||||
|
stringCopy(buffer, "abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "123abc", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 1.23", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "1.23 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, " 1.23 ", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Invalid sign usage
|
||||||
|
stringCopy(buffer, "+-1.2", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "--1.2", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "++1.2", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "+", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "-", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Multiple decimal points
|
||||||
|
stringCopy(buffer, "1.2.3", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Non-ascii digits
|
||||||
|
stringCopy(buffer, "123.45", sizeof(buffer)); // Fullwidth
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot take math
|
||||||
|
stringCopy(buffer, "1+2", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "5-3", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "2*3", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "6/2", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Scientific notation allowed
|
||||||
|
stringCopy(buffer, "1e3", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
stringCopy(buffer, "3.4E10", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Overflow (beyond float32 max)
|
||||||
|
stringCopy(buffer, "3.5e38", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Underflow (too small, magnitude)
|
||||||
|
stringCopy(buffer, "1e-50", sizeof(buffer));
|
||||||
|
assert_false(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Edge of float32 range (decimal form)
|
||||||
|
stringCopy(buffer, "340282346638528859811704183484516925440.0",
|
||||||
|
sizeof(buffer)); // ~FLT_MAX
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Valid near-limits (implementation-dependent, keep conservative)
|
||||||
|
stringCopy(buffer, "3.4028234e38", sizeof(buffer));
|
||||||
|
assert_true(result = stringToF32(buffer, &value));
|
||||||
|
|
||||||
|
// Cannot have NULL string
|
||||||
|
expect_assert_failure(stringToF32(NULL, &value));
|
||||||
|
|
||||||
|
// Cannot have NULL output pointer
|
||||||
|
stringCopy(buffer, "1.23", sizeof(buffer));
|
||||||
|
expect_assert_failure(stringToF32(buffer, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringEndsWith(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
assert_true(stringEndsWith("hello.c", ".c"));
|
||||||
|
assert_true(stringEndsWith("Hello World!", "World!"));
|
||||||
|
|
||||||
|
assert_false(stringEndsWith("document.pdf", ".doc"));
|
||||||
|
assert_false(stringEndsWith("image.jpeg", ".png"));
|
||||||
|
assert_false(stringEndsWith("short", "longer"));
|
||||||
|
|
||||||
|
// Cannot have NULL strings
|
||||||
|
expect_assert_failure(stringEndsWith(NULL, "world"));
|
||||||
|
expect_assert_failure(stringEndsWith("hello", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_stringEndsWithCaseInsensitive(void **state) {
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
assert_true(stringEndsWithCaseInsensitive("hello.C", ".c"));
|
||||||
|
assert_true(stringEndsWithCaseInsensitive("Hello World!", "world!"));
|
||||||
|
assert_false(stringEndsWithCaseInsensitive("document.pdf", ".DOC"));
|
||||||
|
assert_false(stringEndsWithCaseInsensitive("image.jpeg", ".PNG"));
|
||||||
|
assert_false(stringEndsWithCaseInsensitive("short", "LONGER"));
|
||||||
|
|
||||||
|
// Cannot have NULL strings
|
||||||
|
expect_assert_failure(stringEndsWithCaseInsensitive(NULL, "WORLD"));
|
||||||
|
expect_assert_failure(stringEndsWithCaseInsensitive("hello", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
const struct CMUnitTest tests[] = {
|
||||||
|
cmocka_unit_test(test_stringIsWhitespace),
|
||||||
|
cmocka_unit_test(test_stringCopy),
|
||||||
|
cmocka_unit_test(test_stringCompare),
|
||||||
|
cmocka_unit_test(test_stringCompareInsensitive),
|
||||||
|
cmocka_unit_test(test_stringTrim),
|
||||||
|
cmocka_unit_test(test_stringFindLastChar),
|
||||||
|
cmocka_unit_test(test_stringFormat),
|
||||||
|
cmocka_unit_test(test_stringToI32),
|
||||||
|
cmocka_unit_test(test_stringToI64),
|
||||||
|
cmocka_unit_test(test_stringToI16),
|
||||||
|
cmocka_unit_test(test_stringToU16),
|
||||||
|
cmocka_unit_test(test_stringToF32),
|
||||||
|
cmocka_unit_test(test_stringEndsWith),
|
||||||
|
cmocka_unit_test(test_stringEndsWithCaseInsensitive),
|
||||||
|
};
|
||||||
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user