tests/test_string.c

changeset 1052
e997862a57d8
parent 1003
455afb252878
--- a/tests/test_string.c	Mon Dec 23 00:33:27 2024 +0100
+++ b/tests/test_string.c	Mon Dec 23 00:34:05 2024 +0100
@@ -31,6 +31,9 @@
 
 #include "cx/string.h"
 
+#include <limits.h>
+#include <errno.h>
+
 #define ASSERT_ZERO_TERMINATED(str) CX_TEST_ASSERTM((str).ptr[(str).length] == '\0', \
     #str " is not zero terminated")
 
@@ -970,6 +973,159 @@
     cx_strfree(&str);
 }
 
+#define test_strtoint_impl(suffix, num, base, var, min, max) \
+    do { \
+        errno = 0; \
+        int r = cx_strto##var(cx_str( #num), &var, base); \
+        if ((min) <= (num##suffix) && (num##suffix) <= (max)) { \
+            CX_TEST_ASSERTM(0 == r, "failed for "#num); \
+            CX_TEST_ASSERT(0 == errno); \
+            CX_TEST_ASSERT((num##suffix) == (0##suffix)+(var)); \
+        } else { \
+            CX_TEST_ASSERTM(0 != r, "out-of-range not detected for "#num " in variant "#var); \
+            CX_TEST_ASSERT(ERANGE == errno); \
+        } \
+    } while (0)
+
+#define test_strtoint_rollout_signed_impl(num, base) \
+    test_strtoint_impl(LL, num, base, s, SHRT_MIN, SHRT_MAX); \
+    test_strtoint_impl(LL, num, base, i, INT_MIN, INT_MAX); \
+    test_strtoint_impl(LL, num, base, l, LONG_MIN, LONG_MAX); \
+    test_strtoint_impl(LL, num, base, ll, LLONG_MIN, LLONG_MAX); \
+    test_strtoint_impl(LL, num, base, i8, INT8_MIN, INT8_MAX); \
+    test_strtoint_impl(LL, num, base, i16, INT16_MIN, INT16_MAX); \
+    test_strtoint_impl(LL, num, base, i32, INT32_MIN, INT32_MAX); \
+    test_strtoint_impl(LL, num, base, i64, INT64_MIN, INT64_MAX); \
+    test_strtoint_impl(LL, num, base, z, -SSIZE_MAX-1, SSIZE_MAX)
+
+#define test_strtoint_rollout_signed(num, base) \
+    test_strtoint_rollout_signed_impl(num, base); \
+    test_strtoint_rollout_signed_impl(-num, base)
+
+#define test_strtoint_rollout(num, base) \
+    test_strtoint_impl(ULL, num, base, us, 0, USHRT_MAX); \
+    test_strtoint_impl(ULL, num, base, u, 0, UINT_MAX); \
+    test_strtoint_impl(ULL, num, base, ul, 0, ULONG_MAX); \
+    test_strtoint_impl(ULL, num, base, ull, 0, ULLONG_MAX); \
+    test_strtoint_impl(ULL, num, base, u8, 0, UINT8_MAX); \
+    test_strtoint_impl(ULL, num, base, u16, 0, UINT16_MAX); \
+    test_strtoint_impl(ULL, num, base, u32, 0, UINT32_MAX); \
+    test_strtoint_impl(ULL, num, base, u64, 0, UINT64_MAX); \
+    test_strtoint_impl(ULL, num, base, uz, 0, SIZE_MAX)
+
+CX_TEST(test_string_to_signed_integer) {
+    short s;
+    int i;
+    long l;
+    long long ll;
+    int8_t i8;
+    int16_t i16;
+    int32_t i32;
+    int64_t i64;
+    ssize_t z;
+    CX_TEST_DO {
+        // do some brute force tests with all ranges
+        test_strtoint_rollout_signed(47, 10);
+        test_strtoint_rollout_signed(210, 10);
+        test_strtoint_rollout_signed(5678, 10);
+        test_strtoint_rollout_signed(40678, 10);
+        test_strtoint_rollout_signed(1350266537, 10);
+        test_strtoint_rollout_signed(3350266537, 10);
+        test_strtoint_rollout_signed(473350266537, 10);
+        test_strtoint_rollout_signed(057, 8);
+        test_strtoint_rollout_signed(0322, 8);
+        test_strtoint_rollout_signed(013056, 8);
+        test_strtoint_rollout_signed(0117346, 8);
+        test_strtoint_rollout_signed(012036667251, 8);
+        test_strtoint_rollout_signed(030754201251, 8);
+        test_strtoint_rollout_signed(06706567757251, 8);
+        test_strtoint_rollout_signed(0767716340165362204025, 8);
+        test_strtoint_rollout_signed(0x65, 16);
+        test_strtoint_rollout_signed(0xf5, 16);
+        test_strtoint_rollout_signed(0xABC5, 16);
+        test_strtoint_rollout_signed(0xFBC5, 16);
+        test_strtoint_rollout_signed(0x6df9CE03, 16);
+        test_strtoint_rollout_signed(0xFdf9CE03, 16);
+        test_strtoint_rollout_signed(0x6df9CE03AbC90815, 16);
+        // TODO: roll out base 2 tests, but that needs C23
+
+        // do some special case tests
+
+        // can fit only in unsigned long long
+        errno = 0;
+        CX_TEST_ASSERT(0 != cx_strtoll(cx_str("0x8df9CE03AbC90815"), &ll, 16));
+        CX_TEST_ASSERT(errno == ERANGE);
+
+        // TODO: implement more special cases
+    }
+}
+
+CX_TEST(test_string_to_unsigned_integer) {
+    unsigned short us;
+    unsigned int u;
+    unsigned long ul;
+    unsigned long long ull;
+    uint8_t u8;
+    uint16_t u16;
+    uint32_t u32;
+    uint64_t u64;
+    size_t uz;
+    CX_TEST_DO {
+        // do some brute force tests with all ranges
+        test_strtoint_rollout(47, 10);
+        test_strtoint_rollout(210, 10);
+        test_strtoint_rollout(5678, 10);
+        test_strtoint_rollout(40678, 10);
+        test_strtoint_rollout(1350266537, 10);
+        test_strtoint_rollout(3350266537, 10);
+        test_strtoint_rollout(473350266537, 10);
+        test_strtoint_rollout(057, 8);
+        test_strtoint_rollout(0322, 8);
+        test_strtoint_rollout(013056, 8);
+        test_strtoint_rollout(0117346, 8);
+        test_strtoint_rollout(012036667251, 8);
+        test_strtoint_rollout(030754201251, 8);
+        test_strtoint_rollout(06706567757251, 8);
+        test_strtoint_rollout(01767716340165362204025, 8);
+        test_strtoint_rollout(0x65, 16);
+        test_strtoint_rollout(0xf5, 16);
+        test_strtoint_rollout(0xABC5, 16);
+        test_strtoint_rollout(0xFBC5, 16);
+        test_strtoint_rollout(0x6df9CE03, 16);
+        test_strtoint_rollout(0xFdf9CE03, 16);
+        test_strtoint_rollout(0x6df9CE03AbC90815, 16);
+        test_strtoint_rollout(0xfdf9CE03AbC90815, 16);
+        // TODO: roll out base 2 tests, but that needs C23
+
+        // do some special case tests
+
+        // TODO: implement tests
+    }
+}
+
+CX_TEST(test_string_to_float) {
+    float f;
+    CX_TEST_DO {
+        CX_TEST_ASSERT(0 == cx_strtof(cx_str("11.3"), &f));
+        CX_TEST_ASSERT(11.3f == f);
+    }
+}
+
+CX_TEST(test_string_to_double) {
+    double d;
+    CX_TEST_DO {
+        CX_TEST_ASSERT(0 == cx_strtod(cx_str("11.3"), &d));
+        CX_TEST_ASSERT(11.3 == d);
+    }
+}
+
+CX_TEST(test_string_to_float_german) {
+    float f;
+    CX_TEST_DO {
+        // TODO: implement
+        (void)f;
+    }
+}
 
 CxTestSuite *cx_test_suite_string(void) {
     CxTestSuite *suite = cx_test_suite_new("string");
@@ -1006,3 +1162,15 @@
 
     return suite;
 }
+
+CxTestSuite *cx_test_suite_string_to_number(void) {
+    CxTestSuite *suite = cx_test_suite_new("string to number");
+
+    cx_test_register(suite, test_string_to_signed_integer);
+    cx_test_register(suite, test_string_to_unsigned_integer);
+    cx_test_register(suite, test_string_to_float);
+    cx_test_register(suite, test_string_to_double);
+    cx_test_register(suite, test_string_to_float_german);
+
+    return suite;
+}

mercurial