@@ -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 \n hello 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 , " \t 123 " , 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 , " 1 2 3 4 5 " , 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 , " \t 123 " , 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 , " 1 2 3 4 5 " , 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 , " \t 123 " , 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 , " 1 2 3 4 5 " , 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 , " \t 123 " , 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 , " 1 2 3 4 5 " , 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 , " 1 2 3 . 4 5 " , 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 ) ;
}