#include "runner.h" #include "../colla.h" #include // String (str_t) Tests UNIT_TEST(str_init_basic) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s = str_init(&arena, "hello"); ASSERT(s.len == 5); ASSERT(s.buf != NULL); ASSERT(memcmp(s.buf, "hello", 5) == 0); arena_cleanup(&arena); } UNIT_TEST(str_init_len) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s = str_init_len(&arena, "hello world", 5); ASSERT(s.len == 5); ASSERT(s.buf != NULL); ASSERT(memcmp(s.buf, "hello", 5) == 0); arena_cleanup(&arena); } UNIT_TEST(str_fmt) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s = str_fmt(&arena, "Number: %d, String: %s", 42, "test"); ASSERT(s.buf != NULL); ASSERT(memcmp(s.buf, "Number: 42, String: test", s.len) == 0); arena_cleanup(&arena); } UNIT_TEST(str_equals) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s1 = str_init(&arena, "hello"); str_t s2 = str_init(&arena, "hello"); str_t s3 = str_init(&arena, "world"); ASSERT(str_equals(s1, s2) == true); ASSERT(str_equals(s1, s3) == false); arena_cleanup(&arena); } UNIT_TEST(str_compare) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s1 = str_init(&arena, "abc"); str_t s2 = str_init(&arena, "abc"); str_t s3 = str_init(&arena, "abd"); str_t s4 = str_init(&arena, "abb"); ASSERT(str_compare(s1, s2) == 0); ASSERT(str_compare(s1, s3) < 0); ASSERT(str_compare(s1, s4) > 0); arena_cleanup(&arena); } UNIT_TEST(str_dup) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s1 = str_init(&arena, "test"); str_t s2 = str_dup(&arena, s1); ASSERT(s1.len == s2.len); ASSERT(s1.buf != s2.buf); // Different memory locations ASSERT(memcmp(s1.buf, s2.buf, s1.len) == 0); arena_cleanup(&arena); } UNIT_TEST(str_cat) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s1 = str_init(&arena, "hello "); str_t s2 = str_init(&arena, "world"); str_t s3 = str_cat(&arena, s1, s2); ASSERT(s3.len == s1.len + s2.len); ASSERT(memcmp(s3.buf, "hello world", s3.len) == 0); arena_cleanup(&arena); } UNIT_TEST(str_is_empty) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s1 = str_init(&arena, "test"); str_t s2 = STR_EMPTY; ASSERT(str_is_empty(s1) == false); ASSERT(str_is_empty(s2) == true); arena_cleanup(&arena); } UNIT_TEST(str_lower_upper) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s1 = str_init(&arena, "TeSt"); str_lower(&s1); ASSERT(memcmp(s1.buf, "test", 4) == 0); str_t s2 = str_init(&arena, "TeSt"); str_upper(&s2); ASSERT(memcmp(s2.buf, "TEST", 4) == 0); arena_cleanup(&arena); } UNIT_TEST(str_replace) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s = str_init(&arena, "hello"); str_replace(&s, 'l', 'x'); ASSERT(memcmp(s.buf, "hexxo", 5) == 0); arena_cleanup(&arena); } UNIT_TEST(str_sub) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s = str_init(&arena, "hello world"); strview_t sv = str_sub(s, 6, 11); ASSERT(sv.len == 5); ASSERT(memcmp(sv.buf, "world", 5) == 0); arena_cleanup(&arena); } // String View (strview_t) Tests UNIT_TEST(strv_init) { strview_t sv = strv_init("hello"); ASSERT(sv.len == 5); ASSERT(sv.buf != NULL); ASSERT(memcmp(sv.buf, "hello", 5) == 0); } UNIT_TEST(strv_init_len) { strview_t sv = strv_init_len("hello world", 5); ASSERT(sv.len == 5); ASSERT(sv.buf != NULL); ASSERT(memcmp(sv.buf, "hello", 5) == 0); } UNIT_TEST(strv_init_str) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); str_t s = str_init(&arena, "hello"); strview_t sv = strv_init_str(s); ASSERT(sv.len == s.len); ASSERT(sv.buf == s.buf); arena_cleanup(&arena); } UNIT_TEST(strv_is_empty) { strview_t sv1 = strv_init("test"); strview_t sv2 = STRV_EMPTY; ASSERT(strv_is_empty(sv1) == false); ASSERT(strv_is_empty(sv2) == true); } UNIT_TEST(strv_equals) { strview_t sv1 = strv_init("hello"); strview_t sv2 = strv_init("hello"); strview_t sv3 = strv_init("world"); ASSERT(strv_equals(sv1, sv2) == true); ASSERT(strv_equals(sv1, sv3) == false); } UNIT_TEST(strv_compare) { strview_t sv1 = strv_init("abc"); strview_t sv2 = strv_init("abc"); strview_t sv3 = strv_init("abd"); strview_t sv4 = strv_init("abb"); ASSERT(strv_compare(sv1, sv2) == 0); ASSERT(strv_compare(sv1, sv3) < 0); ASSERT(strv_compare(sv1, sv4) > 0); } UNIT_TEST(strv_front_back) { strview_t sv = strv_init("hello"); ASSERT(strv_front(sv) == 'h'); ASSERT(strv_back(sv) == 'o'); } UNIT_TEST(strv_remove_prefix_suffix) { strview_t sv = strv_init("hello"); strview_t prefix_removed = strv_remove_prefix(sv, 2); ASSERT(prefix_removed.len == 3); ASSERT(memcmp(prefix_removed.buf, "llo", 3) == 0); strview_t suffix_removed = strv_remove_suffix(sv, 2); ASSERT(suffix_removed.len == 3); ASSERT(memcmp(suffix_removed.buf, "hel", 3) == 0); } UNIT_TEST(strv_trim) { strview_t sv1 = strv_init(" hello "); strview_t sv2 = strv_init(" hello"); strview_t sv3 = strv_init("hello "); strview_t trimmed1 = strv_trim(sv1); strview_t trimmed2 = strv_trim_left(sv2); strview_t trimmed3 = strv_trim_right(sv3); ASSERT(trimmed1.len == 5); ASSERT(memcmp(trimmed1.buf, "hello", 5) == 0); ASSERT(trimmed2.len == 5); ASSERT(memcmp(trimmed2.buf, "hello", 5) == 0); ASSERT(trimmed3.len == 5); ASSERT(memcmp(trimmed3.buf, "hello", 5) == 0); } UNIT_TEST(strv_sub) { strview_t sv = strv_init("hello world"); strview_t sub = strv_sub(sv, 6, 11); ASSERT(sub.len == 5); ASSERT(memcmp(sub.buf, "world", 5) == 0); } UNIT_TEST(strv_starts_ends_with) { strview_t sv = strv_init("hello"); ASSERT(strv_starts_with(sv, 'h') == true); ASSERT(strv_starts_with(sv, 'e') == false); ASSERT(strv_ends_with(sv, 'o') == true); ASSERT(strv_ends_with(sv, 'l') == false); strview_t prefix = strv_init("hel"); strview_t suffix = strv_init("llo"); ASSERT(strv_starts_with_view(sv, prefix) == true); ASSERT(strv_ends_with_view(sv, suffix) == true); } UNIT_TEST(strv_contains) { strview_t sv = strv_init("hello world"); ASSERT(strv_contains(sv, 'e') == true); ASSERT(strv_contains(sv, 'z') == false); strview_t sub = strv_init("world"); ASSERT(strv_contains_view(sv, sub) == true); strview_t chars = strv_init("xyz"); ASSERT(strv_contains_either(sv, chars) == false); strview_t chars2 = strv_init("xyo"); ASSERT(strv_contains_either(sv, chars2) == true); } UNIT_TEST(strv_find) { strview_t sv = strv_init("hello world"); ASSERT(strv_find(sv, 'o', 0) == 4); ASSERT(strv_find(sv, 'o', 5) == 7); ASSERT(strv_find(sv, 'z', 0) == STR_NONE); strview_t sub = strv_init("world"); ASSERT(strv_find_view(sv, sub, 0) == 6); strview_t chars = strv_init("xwo"); ASSERT(strv_find_either(sv, chars, 0) == 4); // 'w' at position 6 } UNIT_TEST(strv_rfind) { strview_t sv = strv_init("hello world"); ASSERT(strv_rfind(sv, 'o', 0) == 7); ASSERT(strv_rfind(sv, 'o', 5) == 4); ASSERT(strv_rfind(sv, 'z', 0) == STR_NONE); strview_t sub = strv_init("world"); ASSERT(strv_rfind_view(sv, sub, 0) == 6); } // Character Functions Tests UNIT_TEST(char_functions) { ASSERT(char_is_space(' ') == true); ASSERT(char_is_space('\t') == true); ASSERT(char_is_space('a') == false); ASSERT(char_is_alpha('a') == true); ASSERT(char_is_alpha('Z') == true); ASSERT(char_is_alpha('1') == false); ASSERT(char_is_num('0') == true); ASSERT(char_is_num('9') == true); ASSERT(char_is_num('a') == false); ASSERT(char_lower('A') == 'a'); ASSERT(char_lower('a') == 'a'); ASSERT(char_lower('1') == '1'); } // Input Stream Tests UNIT_TEST(instream_basic) { strview_t sv = strv_init("hello world"); instream_t is = istr_init(sv); ASSERT(istr_get(&is) == 'h'); ASSERT(istr_get(&is) == 'e'); ASSERT(istr_peek(&is) == 'l'); ASSERT(istr_peek_next(&is) == 'l'); ASSERT(istr_get(&is) == 'l'); ASSERT(istr_prev(&is) == 'l'); ASSERT(istr_prev_prev(&is) == 'e'); istr_skip(&is, 2); ASSERT(istr_peek(&is) == ' '); istr_skip_whitespace(&is); ASSERT(istr_peek(&is) == 'w'); istr_rewind(&is); ASSERT(istr_peek(&is) == 'h'); ASSERT(istr_tell(&is) == 0); ASSERT(istr_remaining(&is) == 11); ASSERT(istr_is_finished(&is) == false); } UNIT_TEST(instream_ignore) { strview_t sv = strv_init("hello,world"); instream_t is = istr_init(sv); istr_ignore(&is, ','); ASSERT(istr_peek(&is) == ','); istr_ignore_and_skip(&is, ','); ASSERT(istr_peek(&is) == 'w'); } UNIT_TEST(instream_get_values) { strview_t sv = strv_init("true 42 3.14 hello"); instream_t is = istr_init(sv); bool b; ASSERT(istr_get_bool(&is, &b) == true); ASSERT(b == true); istr_skip_whitespace(&is); u32 u; ASSERT(istr_get_u32(&is, &u) == true); ASSERT(u == 42); istr_skip_whitespace(&is); double d; ASSERT(istr_get_num(&is, &d) == true); ASSERT(d > 3.13 && d < 3.15); istr_skip_whitespace(&is); strview_t word = istr_get_view(&is, ' '); ASSERT(word.len == 5); ASSERT(memcmp(word.buf, "hello", 5) == 0); } // Output Stream Tests UNIT_TEST(outstream_basic) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); outstream_t os = ostr_init(&arena); ostr_putc(&os, 'h'); ostr_putc(&os, 'i'); ASSERT(ostr_tell(&os) == 2); ASSERT(ostr_back(&os) == 'i'); ostr_print(&os, " %d", 42); strview_t result = ostr_as_view(&os); ASSERT(result.len == 5); ASSERT(memcmp(result.buf, "hi 42", 5) == 0); ostr_pop(&os, 3); result = ostr_as_view(&os); ASSERT(result.len == 2); ASSERT(memcmp(result.buf, "hi", 2) == 0); ostr_clear(&os); ASSERT(ostr_tell(&os) == 0); arena_cleanup(&arena); } UNIT_TEST(outstream_append) { arena_t arena = arena_make(ARENA_MALLOC, KB(4)); outstream_t os = ostr_init(&arena); ostr_append_bool(&os, true); ostr_putc(&os, ' '); ostr_append_uint(&os, 42); ostr_putc(&os, ' '); ostr_append_int(&os, -10); ostr_putc(&os, ' '); ostr_append_num(&os, 3.14); str_t result = ostr_to_str(&os); ASSERT(result.len > 0); arena_cleanup(&arena); } // Binary Input Stream Tests UNIT_TEST(binary_stream) { u8 data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; buffer_t buffer = {data, sizeof(data)}; ibstream_t bs = ibstr_init(buffer); ASSERT(ibstr_remaining(&bs) == 8); ASSERT(ibstr_tell(&bs) == 0); ASSERT(ibstr_is_finished(&bs) == false); u8 val8; ASSERT(ibstr_get_u8(&bs, &val8) == true); ASSERT(val8 == 0x01); u16 val16; ASSERT(ibstr_get_u16(&bs, &val16) == true); ASSERT(val16 == 0x0302); // Assuming little-endian ibstr_skip(&bs, 1); u32 val32; ASSERT(ibstr_get_u32(&bs, &val32) == true); ASSERT(val32 == 0x08070605); // Assuming little-endian ASSERT(ibstr_is_finished(&bs) == true); }