#include #include cbool check(const char *str, usize expect, usize *output) { // TODO maybe have other logger (void)(expect); log_set_level(&__default_logger_root, 0); scc_pos_t pos = scc_pos_create(); scc_mem_probe_stream_t mem_stream; scc_probe_stream_t *stream = scc_mem_probe_stream_init(&mem_stream, str, scc_strlen(str), false); return scc_lex_parse_number(stream, &pos, output); } #define CHECK_VALID(str, expect) \ do { \ usize _output; \ cbool ret = check(str, expect, &_output); \ TEST_CHECK(ret == true); \ TEST_CHECK(_output == expect); \ TEST_MSG("Produced: %llu", _output); \ } while (0) #define CHECK_INVALID(str) \ do { \ usize _output; \ cbool ret = check(str, 0, &_output); \ TEST_CHECK(ret == false); \ } while (0) void test_simple_hex(void) { TEST_CASE("lowercase hex"); CHECK_VALID("0xff", 255); CHECK_VALID("0x0", 0); CHECK_VALID("0xa", 10); CHECK_VALID("0xf", 15); CHECK_VALID("0x1a", 26); TEST_CASE("uppercase hex"); CHECK_VALID("0xFF", 255); CHECK_VALID("0xA0", 160); CHECK_VALID("0xCAFEBABE", 3405691582); TEST_CASE("mixed case hex"); CHECK_VALID("0xFf", 255); CHECK_VALID("0xCaFeBaBe", 3405691582); TEST_CASE("larger hex values"); CHECK_VALID("0xff00", 65280); CHECK_VALID("0xFFFF", 65535); TEST_CASE("invalid hex"); CHECK_INVALID("0xG"); // Invalid hex digit CHECK_INVALID("0xyz"); // Invalid prefix CHECK_INVALID("0x"); // Incomplete hex } void test_simple_oct(void) { TEST_CASE("basic octal"); CHECK_VALID("00", 0); CHECK_VALID("01", 1); CHECK_VALID("07", 7); TEST_CASE("multi-digit octal"); CHECK_VALID("010", 8); CHECK_VALID("017", 15); CHECK_VALID("077", 63); TEST_CASE("larger octal values"); CHECK_VALID("0177", 127); CHECK_VALID("0377", 255); CHECK_VALID("0777", 511); TEST_CASE("invalid octal"); CHECK_INVALID("08"); // Invalid octal digit CHECK_INVALID("09"); // Invalid octal digit } void test_simple_dec(void) { TEST_CASE("single digits"); CHECK_VALID("0", 0); CHECK_VALID("1", 1); CHECK_VALID("9", 9); TEST_CASE("multi-digit decimal"); CHECK_VALID("10", 10); CHECK_VALID("42", 42); CHECK_VALID("123", 123); TEST_CASE("larger decimal values"); CHECK_VALID("999", 999); CHECK_VALID("1234", 1234); CHECK_VALID("65535", 65535); } void test_simple_bin(void) { TEST_CASE("basic binary"); CHECK_VALID("0b0", 0); CHECK_VALID("0b1", 1); TEST_CASE("multi-digit binary"); CHECK_VALID("0b10", 2); CHECK_VALID("0b11", 3); CHECK_VALID("0b100", 4); CHECK_VALID("0b1010", 10); TEST_CASE("larger binary values"); CHECK_VALID("0b1111", 15); CHECK_VALID("0b11111111", 255); CHECK_VALID("0b10101010", 170); TEST_CASE("invalid binary"); CHECK_INVALID("0b2"); // Invalid binary digit CHECK_INVALID("0b3"); // Invalid binary digit CHECK_INVALID("0b"); // Incomplete binary } void test_edge_cases(void) { TEST_CASE("empty string"); CHECK_INVALID(""); // Empty string TEST_CASE("non-numeric strings"); CHECK_INVALID("abc"); // Non-numeric CHECK_INVALID("xyz"); // Non-numeric TEST_CASE("mixed invalid formats"); CHECK_INVALID("0x1G"); // Mixed valid/invalid hex CHECK_INVALID("0b12"); // Mixed valid/invalid binary } TEST_LIST = { {"test_simple_hex", test_simple_hex}, {"test_simple_oct", test_simple_oct}, {"test_simple_dec", test_simple_dec}, {"test_simple_bin", test_simple_bin}, {"test_edge_cases", test_edge_cases}, {NULL, NULL}, };