#include "test_str8.h" #include "mem_allocator.h" #include "mem_arena_allocator.h" #include "misc_utils.h" #include "str8.h" #include "tester.h" #include #define ARRLEN(ARR) (sizeof(ARR) / sizeof(ARR[0])) TestFuncResult test_str8_lit(void) { bool result; Str8 s1 = wapp_str8_lit("Hello world"); result = s1.capacity == 22 && s1.capacity != s1.size; Str8 s2 = wapp_str8_lit("Different strokes for different folks"); result = result && s2.capacity == 74 && s2.capacity != s2.size; Str8 s3 = wapp_str8_lit("Discretion is the better part of valour"); result = result && s3.capacity == 78 && s3.capacity != s3.size; Str8 s4 = wapp_str8_lit("Distance lends enchantment to the view"); result = result && s4.capacity == 76 && s4.capacity != s4.size; Str8 s5 = wapp_str8_lit("Do as I say, not as I do"); result = result && s5.capacity == 48 && s5.capacity != s5.size; Str8 s6 = wapp_str8_lit("Do as you would be done by"); result = result && s6.capacity == 52 && s6.capacity != s6.size; Str8 s7 = wapp_str8_lit("Do unto others as you would have them do to you"); result = result && s7.capacity == 94 && s7.capacity != s7.size; return wapp_tester_result(result); } TestFuncResult test_str8_lit_ro(void) { bool result; Str8RO s1 = wapp_str8_lit_ro("Hello world"); result = s1.capacity == 11 && s1.capacity == s1.size; Str8RO s2 = wapp_str8_lit_ro("Different strokes for different folks"); result = result && s2.capacity == 37 && s2.capacity == s2.size; Str8RO s3 = wapp_str8_lit_ro("Discretion is the better part of valour"); result = result && s3.capacity == 39 && s3.capacity == s3.size; Str8RO s4 = wapp_str8_lit_ro("Distance lends enchantment to the view"); result = result && s4.capacity == 38 && s4.capacity == s4.size; Str8RO s5 = wapp_str8_lit_ro("Do as I say, not as I do"); result = result && s5.capacity == 24 && s5.capacity == s5.size; Str8RO s6 = wapp_str8_lit_ro("Do as you would be done by"); result = result && s6.capacity == 26 && s6.capacity == s6.size; Str8RO s7 = wapp_str8_lit_ro("Do unto others as you would have them do to you"); result = result && s7.capacity == 47 && s7.capacity == s7.size; return wapp_tester_result(result); } TestFuncResult test_str8_buf(void) { bool result; Str8 s1 = wapp_str8_buf(1024); result = s1.capacity == 1024 && s1.size == 0; Str8 s2 = wapp_str8_buf(2048); result = result && s2.capacity == 2048 && s2.size == 0; Str8 s3 = wapp_str8_buf(4096); result = result && s3.capacity == 4096 && s3.size == 0; Str8 s4 = wapp_str8_buf(8192); result = result && s4.capacity == 8192 && s4.size == 0; return wapp_tester_result(result); } TestFuncResult test_str8_alloc_buf(void) { bool result; Allocator allocator = wapp_mem_arena_allocator_init(KB(100)); if (wapp_mem_allocator_invalid(&allocator)) { return wapp_tester_result(false); } u64 capacity = 4096; Str8 *s = wapp_str8_alloc_buf(&allocator, capacity); if (!s) { result = false; goto TEST_ALLOC_BUF_CLEANUP; } result = s->capacity == capacity; const char *cstr = "My name is Abdelrahman"; wapp_str8_copy_cstr_capped(s, cstr); result = result && s->capacity == capacity && s->size == strlen(cstr) && memcmp(s->buf, cstr, s->size) == 0; TEST_ALLOC_BUF_CLEANUP: wapp_mem_arena_allocator_destroy(&allocator); return wapp_tester_result(result); } TestFuncResult test_str8_alloc_cstr(void) { bool result; Allocator allocator = wapp_mem_arena_allocator_init(KB(100)); if (wapp_mem_allocator_invalid(&allocator)) { return wapp_tester_result(false); } char *str = "Abdelrahman"; u64 length = strlen(str); Str8 *s = wapp_str8_alloc_cstr(&allocator, str); if (!s) { return wapp_tester_result(false); } result = s->size == length && memcmp(s->buf, str, length) == 0; wapp_mem_arena_allocator_destroy(&allocator); return wapp_tester_result(result); } TestFuncResult test_str8_alloc_str8(void) { bool result; Allocator allocator = wapp_mem_arena_allocator_init(KB(100)); if (wapp_mem_allocator_invalid(&allocator)) { return wapp_tester_result(false); } Str8 str = wapp_str8_lit("Abdelrahman"); Str8 *s = wapp_str8_alloc_str8(&allocator, &str); if (!s) { return wapp_tester_result(false); } result = wapp_str8_equal(s, &str); wapp_mem_arena_allocator_destroy(&allocator); return wapp_tester_result(result); } TestFuncResult test_str8_alloc_substr(void) { bool result; Allocator allocator = wapp_mem_arena_allocator_init(KB(100)); if (wapp_mem_allocator_invalid(&allocator)) { return wapp_tester_result(false); } Str8 str = wapp_str8_lit("Abdelrahman"); Str8 *s = wapp_str8_alloc_substr(&allocator, &str, 3, 8); if (!s) { return wapp_tester_result(false); } result = s->size == 5 && memcmp(s->buf, "elrah", s->size) == 0; wapp_mem_arena_allocator_destroy(&allocator); return wapp_tester_result(result); } TestFuncResult test_str8_get_index_within_bounds(void) { bool result; Str8RO s1 = wapp_str8_lit_ro("Hello world"); result = wapp_str8_get(&s1, 4) == 'o'; Str8RO s2 = wapp_str8_lit_ro("Different strokes for different folks"); result = result && wapp_str8_get(&s2, 0) == 'D'; Str8RO s3 = wapp_str8_lit_ro("Discretion is the better part of valour"); result = result && wapp_str8_get(&s3, 13) == ' '; Str8RO s4 = wapp_str8_lit_ro("Distance lends enchantment to the view"); result = result && wapp_str8_get(&s4, 20) == 'n'; Str8RO s5 = wapp_str8_lit_ro("Do as I say, not as I do"); result = result && wapp_str8_get(&s5, 11) == ','; Str8RO s6 = wapp_str8_lit_ro("Do as you would be done by"); result = result && wapp_str8_get(&s6, 25) == 'y'; Str8RO s7 = wapp_str8_lit_ro("Do unto others as you would have them do to you"); result = result && wapp_str8_get(&s7, 16) == 's'; return wapp_tester_result(result); } TestFuncResult test_str8_get_index_out_of_bounds(void) { Str8 s1 = wapp_str8_lit("Hello world"); bool result = wapp_str8_get(&s1, 20) == '\0'; return wapp_tester_result(result); } TestFuncResult test_str8_set(void) { bool result; Str8 s1 = wapp_str8_lit("Hello world"); wapp_str8_set(&s1, 4, 'f'); result = wapp_str8_get(&s1, 4) == 'f'; Str8 s2 = wapp_str8_lit("Different strokes for different folks"); wapp_str8_set(&s2, 0, 'A'); result = result && wapp_str8_get(&s2, 0) == 'A'; Str8 s3 = wapp_str8_lit("Discretion is the better part of valour"); wapp_str8_set(&s3, 13, 'u'); result = result && wapp_str8_get(&s3, 13) == 'u'; Str8 s4 = wapp_str8_lit("Distance lends enchantment to the view"); wapp_str8_set(&s4, 20, 'R'); result = result && wapp_str8_get(&s4, 20) == 'R'; Str8 s5 = wapp_str8_lit("Do as I say, not as I do"); wapp_str8_set(&s5, 11, '.'); result = result && wapp_str8_get(&s5, 11) == '.'; Str8 s6 = wapp_str8_lit("Do as you would be done by"); wapp_str8_set(&s6, 25, 'w'); result = result && wapp_str8_get(&s6, 25) == 'w'; Str8 s7 = wapp_str8_lit("Do unto others as you would have them do to you"); wapp_str8_set(&s7, 16, 'i'); result = result && wapp_str8_get(&s7, 16) == 'i'; return wapp_tester_result(result); } TestFuncResult test_str8_equal(void) { bool result; Str8RO s1 = wapp_str8_lit_ro("hello"); Str8RO s2 = wapp_str8_lit_ro("hell"); Str8RO s3 = wapp_str8_lit_ro("hello"); Str8RO s4 = wapp_str8_lit_ro("goodbye"); result = wapp_str8_equal(&s1, &s2) == false; result = result && wapp_str8_equal(&s1, &s3) == true; result = result && wapp_str8_equal(&s1, &s4) == false; return wapp_tester_result(result); } TestFuncResult test_str8_slice(void) { bool result; Str8 s = wapp_str8_lit("Different strokes for different folks"); Str8RO sub1 = wapp_str8_slice(&s, 3, 9); result = sub1.size == 6 && sub1.capacity == 6; Str8RO sub2 = wapp_str8_slice(&s, 18, 21); result = result && sub2.size == 3 && sub2.capacity == 3; Str8RO sub3 = wapp_str8_slice(&s, 5, 1); result = result && sub3.size == 0 && sub3.capacity == 0; Str8RO sub4 = wapp_str8_slice(&s, 70, 80); result = result && sub4.size == 0 && sub4.capacity == 0; return wapp_tester_result(result); } TestFuncResult test_str8_alloc_concat(void) { bool result; Allocator arena = wapp_mem_arena_allocator_init(KB(100)); Str8 str = wapp_str8_lit("Hello world"); Str8 suffix1 = wapp_str8_lit(" from me."); Str8 suffix2 = wapp_str8_lit(" This is my code."); Str8 concat1 = wapp_str8_lit("Hello world from me."); Str8 concat2 = wapp_str8_lit("Hello world from me. This is my code."); Str8 *output; output = wapp_str8_alloc_concat(&arena, &str, &suffix1); result = output->size == concat1.size && wapp_str8_equal(output, &concat1); output = wapp_str8_alloc_concat(&arena, output, &suffix2); result = result && output->size == concat2.size && wapp_str8_equal(output, &concat2); wapp_mem_arena_allocator_destroy(&arena); return wapp_tester_result(result); } TestFuncResult test_str8_concat_capped(void) { bool result; Str8 str = wapp_str8_lit("Hello world"); Str8 suffix1 = wapp_str8_lit(" from me."); Str8 suffix2 = wapp_str8_lit(" This is my code."); Str8 concat1 = wapp_str8_lit("Hello world from me."); Str8 concat2 = wapp_str8_lit("Hello world from me. T"); wapp_str8_concat_capped(&str, &suffix1); result = str.size == concat1.size && wapp_str8_equal(&str, &concat1); wapp_str8_concat_capped(&str, &suffix2); result = result && str.size == concat2.size && wapp_str8_equal(&str, &concat2); return wapp_tester_result(result); } TestFuncResult test_str8_copy_cstr_capped(void) { bool result; Str8 buf = wapp_str8_buf(32); const char *src1 = "Hello world"; const char *src2 = "Hello world from the Wizard Apprentice standard library"; Str8RO src1_cp = wapp_str8_lit_ro("Hello world"); Str8RO src2_cp = wapp_str8_lit_ro("Hello world from the Wizard Appr"); wapp_str8_copy_cstr_capped(&buf, src1); result = buf.size == src1_cp.size && wapp_str8_equal(&buf, &src1_cp); wapp_str8_copy_cstr_capped(&buf, src2); result = result && buf.size == src2_cp.size && buf.size == buf.capacity && wapp_str8_equal(&buf, &src2_cp); return wapp_tester_result(result); } TestFuncResult test_str8_copy_str8_capped(void) { bool result; Str8 buf = wapp_str8_buf(32); Str8RO src1 = wapp_str8_lit_ro("Hello world"); Str8RO src2 = wapp_str8_lit_ro("Hello world from the Wizard Apprentice standard library"); Str8RO src2_cp = wapp_str8_lit_ro("Hello world from the Wizard Appr"); wapp_str8_copy_str8_capped(&buf, &src1); result = buf.size == src1.size && wapp_str8_equal(&buf, &src1); wapp_str8_copy_str8_capped(&buf, &src2); result = result && buf.size < src2.size && buf.size == buf.capacity && wapp_str8_equal(&buf, &src2_cp); return wapp_tester_result(result); } TestFuncResult test_str8_format(void) { bool result; Str8 buf = wapp_str8_buf(128); Str8 expected = wapp_str8_lit("My name is Abdelrahman and I am 35 years old"); wapp_str8_format(&buf, "My name is %s and I am %u years old", "Abdelrahman", 35); result = wapp_str8_equal(&buf, &expected); return wapp_tester_result(result); } TestFuncResult test_str8_find(void) { bool result; Str8RO s = wapp_str8_lit("Do as I say, not as I do"); result = wapp_str8_find(&s, wapp_str8_lit_ro("d")) != -1; result = result && (wapp_str8_find(&s, wapp_str8_lit_ro("not")) != -1); result = result && (wapp_str8_find(&s, wapp_str8_lit_ro("as I say")) != -1); result = result && (wapp_str8_find(&s, wapp_str8_lit_ro("f")) == -1); result = result && (wapp_str8_find(&s, wapp_str8_lit_ro("hello")) == -1); result = result && (wapp_str8_find(&s, wapp_str8_lit_ro("not sa I")) == -1); result = result && (wapp_str8_find(&s, wapp_str8_lit_ro("Do unto others as you would have them do to you")) == -1); return wapp_tester_result(result); } TestFuncResult test_str8_rfind(void) { bool result; Str8RO s = wapp_str8_lit("Do as I say, not as I do"); result = wapp_str8_rfind(&s, wapp_str8_lit_ro("d")) != -1; result = result && (wapp_str8_rfind(&s, wapp_str8_lit_ro("not")) != -1); result = result && (wapp_str8_rfind(&s, wapp_str8_lit_ro("as I say")) != -1); result = result && (wapp_str8_rfind(&s, wapp_str8_lit_ro("f")) == -1); result = result && (wapp_str8_rfind(&s, wapp_str8_lit_ro("hello")) == -1); result = result && (wapp_str8_rfind(&s, wapp_str8_lit_ro("not sa I")) == -1); result = result && (wapp_str8_rfind(&s, wapp_str8_lit_ro("Do unto others as you would have them do to you")) == -1); return wapp_tester_result(result); } TestFuncResult test_str8_split(void) { bool result; Allocator arena = wapp_mem_arena_allocator_init(KB(100)); Str8 str = wapp_str8_lit("hello world from me"); Str8 delim1 = wapp_str8_lit(" "); Str8 delim2 = wapp_str8_lit("from"); Str8List *list1 = wapp_str8_split(&arena, &str, &delim1); Str8List *list2 = wapp_str8_split(&arena, &str, &delim2); Str8RO splits1[] = { wapp_str8_slice(&str, 0, 5), wapp_str8_slice(&str, 6, 11), wapp_str8_slice(&str, 12, 16), wapp_str8_slice(&str, 17, 19), }; Str8RO splits2[] = { wapp_str8_slice(&str, 0, 12), wapp_str8_slice(&str, 16, 19), }; u64 index1 = 0; u64 count1 = ARRLEN(splits1); bool running1 = true; u64 index2 = 0; u64 count2 = ARRLEN(splits2); bool running2 = true; result = list1->node_count == count1 && list1->total_size == str.size - 3; result = result && list2->node_count == count2 && list2->total_size == str.size - 4; // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of // MSVC Spectre mitigation warnings while (running1) { Str8Node *node = wapp_str8_list_get(list1, index1); result = result && wapp_str8_equal(node->string, &(splits1[index1])); ++index1; running1 = index1 < count1; } // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of // MSVC Spectre mitigation warnings while (running2) { Str8Node *node = wapp_str8_list_get(list2, index2); result = result && wapp_str8_equal(node->string, &(splits2[index2])); ++index2; running2 = index2 < count2; } wapp_mem_arena_allocator_destroy(&arena); return wapp_tester_result(result); } TestFuncResult test_str8_split_with_max(void) { bool result; Allocator arena = wapp_mem_arena_allocator_init(KB(100)); Str8 str = wapp_str8_lit("hello world from me"); Str8 delim = wapp_str8_lit(" "); Str8List *list = wapp_str8_split_with_max(&arena, &str, &delim, 2); Str8RO splits[] = { wapp_str8_slice(&str, 0, 5), wapp_str8_slice(&str, 6, 11), wapp_str8_slice(&str, 12, 19), }; u64 index = 0; u64 count = ARRLEN(splits); bool running = true; result = list->node_count == count && list->total_size == str.size - 2; // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of // MSVC Spectre mitigation warnings while (running) { Str8Node *node = wapp_str8_list_get(list, index); result = result && wapp_str8_equal(node->string, &(splits[index])); ++index; running = index < count; } wapp_mem_arena_allocator_destroy(&arena); return wapp_tester_result(result); } TestFuncResult test_str8_rsplit(void) { bool result; Allocator arena = wapp_mem_arena_allocator_init(KB(100)); Str8 str = wapp_str8_lit("hello world from me"); Str8 delim1 = wapp_str8_lit(" "); Str8 delim2 = wapp_str8_lit("from"); Str8List *list1 = wapp_str8_rsplit(&arena, &str, &delim1); Str8List *list2 = wapp_str8_rsplit(&arena, &str, &delim2); Str8RO splits1[] = { wapp_str8_slice(&str, 0, 5), wapp_str8_slice(&str, 6, 11), wapp_str8_slice(&str, 12, 16), wapp_str8_slice(&str, 17, 19), }; Str8RO splits2[] = { wapp_str8_slice(&str, 0, 12), wapp_str8_slice(&str, 16, 19), }; u64 index1 = 0; u64 count1 = ARRLEN(splits1); bool running1 = true; u64 index2 = 0; u64 count2 = ARRLEN(splits2); bool running2 = true; result = list1->node_count == count1 && list1->total_size == str.size - 3; result = result && list2->node_count == count2 && list2->total_size == str.size - 4; // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of // MSVC Spectre mitigation warnings while (running1) { Str8Node *node = wapp_str8_list_get(list1, index1); result = result && wapp_str8_equal(node->string, &(splits1[index1])); ++index1; running1 = index1 < count1; } // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of // MSVC Spectre mitigation warnings while (running2) { Str8Node *node = wapp_str8_list_get(list2, index2); result = result && wapp_str8_equal(node->string, &(splits2[index2])); ++index2; running2 = index2 < count2; } wapp_mem_arena_allocator_destroy(&arena); return wapp_tester_result(result); } TestFuncResult test_str8_rsplit_with_max(void) { bool result; Allocator arena = wapp_mem_arena_allocator_init(KB(100)); Str8 str = wapp_str8_lit("hello world from me"); Str8 delim = wapp_str8_lit(" "); Str8List *list = wapp_str8_rsplit_with_max(&arena, &str, &delim, 2); Str8RO splits[] = { wapp_str8_slice(&str, 0, 11), wapp_str8_slice(&str, 12, 16), wapp_str8_slice(&str, 17, 19), }; u64 index = 0; u64 count = ARRLEN(splits); bool running = true; result = list->node_count == count && list->total_size == str.size - 2; // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of // MSVC Spectre mitigation warnings while (running) { Str8Node *node = wapp_str8_list_get(list, index); result = result && wapp_str8_equal(node->string, &(splits[index])); ++index; running = index < count; } wapp_mem_arena_allocator_destroy(&arena); return wapp_tester_result(result); } TestFuncResult test_str8_join(void) { bool result; Allocator arena = wapp_mem_arena_allocator_init(KB(100)); Str8 str = wapp_str8_lit("hello world from me"); Str8 delim1 = wapp_str8_lit(" "); Str8 delim2 = wapp_str8_lit("from"); Str8List *list1 = wapp_str8_rsplit(&arena, &str, &delim1); Str8List *list2 = wapp_str8_rsplit(&arena, &str, &delim2); Str8 *join1 = wapp_str8_join(&arena, list1, &delim1); Str8 *join2 = wapp_str8_join(&arena, list2, &delim2); result = join1->size == str.size && wapp_str8_equal(join1, &str); result = result && join2->size == str.size && wapp_str8_equal(join2, &str); wapp_mem_arena_allocator_destroy(&arena); return wapp_tester_result(result); }