Files
dusk/test/util/test_string.c
Dominic Masters 0df7845f2c
Some checks failed
Build Dusk / run-tests (push) Successful in 2m6s
Build Dusk / build-linux (push) Successful in 2m6s
Build Dusk / build-psp (push) Failing after 1m47s
Added memory checks
2026-01-06 11:02:26 -06:00

914 lines
30 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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"
#include "util/memory.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
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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, "");
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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'));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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"));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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, "", 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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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, "", 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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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, "", 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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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, "", 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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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, "", 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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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));
// Expect no leaks
assert_int_equal(memoryGetAllocatedCount(), 0);
}
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);
}