/** * 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); }