From 6d22734aaf91bdfd717f8e1969830e2b875c4e14 Mon Sep 17 00:00:00 2001 From: doyle Date: Sun, 12 Mar 2023 11:07:23 +1100 Subject: [PATCH] dqn: Use defer loops for testing framework --- Project/dqn.rdbg | Bin 636 -> 667 bytes dqn.h | 4 +- dqn_tester.h | 120 +-- dqn_unit_tests.cpp | 1985 +++++++++++++++++++------------------------- 4 files changed, 916 insertions(+), 1193 deletions(-) diff --git a/Project/dqn.rdbg b/Project/dqn.rdbg index 889ed615d2ce178d77df1398959f1b75d306ba8a..4ed6eac7b9c9e2e267be1747d02c6de1cacebbaa 100644 GIT binary patch delta 74 zcmeyvGMkk($i>NBZz8L_MM_~_d}&^0Nqk9aaY?aWYDFpo6fgp5F(7ufit)(LO^tER RPf3jdDhFY`jE%PTOaKVA6qf)1 delta 43 pcmbQu`iF%z$i>NBb0Vv}q)TC5d`N0>NwHpPMJfXl*cfBa1ONn&3J(AP diff --git a/dqn.h b/dqn.h index ac1581f..6f648e0 100644 --- a/dqn.h +++ b/dqn.h @@ -2066,7 +2066,7 @@ DQN_API Dqn_M4 Dqn_M4_SubF(Dqn_M4 lhs, Dqn_f32 rhs); DQN_API Dqn_M4 Dqn_M4_MulF(Dqn_M4 lhs, Dqn_f32 rhs); DQN_API Dqn_M4 Dqn_M4_DivF(Dqn_M4 lhs, Dqn_f32 rhs); -#if defined(DQN_WITH_FIXED_STRING) +#if !defined(DQN_NO_FSTRING8) DQN_API Dqn_FString8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat); #endif @@ -6205,7 +6205,7 @@ DQN_API Dqn_M4 Dqn_M4_DivF(Dqn_M4 lhs, Dqn_f32 rhs) return result; } -#if defined(DQN_WITH_FIXED_STRING) +#if !defined(DQN_NO_FSTRING8) DQN_API Dqn_FString8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat) { Dqn_FString8<256> result = {}; diff --git a/dqn_tester.h b/dqn_tester.h index 9d79f27..a569ed9 100644 --- a/dqn_tester.h +++ b/dqn_tester.h @@ -60,18 +60,22 @@ #endif #define DQN_TESTER_COLOR_RESET "\x1b[0m" +#define DQN_TESTER_TOKEN_COMBINE2(x, y) x ## y_ +#define DQN_TESTER_TOKEN_COMBINE(x, y) DQN_TESTER_TOKEN_COMBINE2(x, y) -#define DQN_TESTER_BEGIN_GROUP(fmt, ...) fprintf(stdout, fmt "\n", ##__VA_ARGS__) -#define DQN_TESTER_END_GROUP(test) \ - do { \ - bool all_clear = (test)->num_tests_ok_in_group == (test)->num_tests_in_group; \ - fprintf(stdout, \ - "%s\n %02d/%02d tests passed -- %s\n\n" DQN_TESTER_COLOR_RESET, \ - all_clear ? DQN_TESTER_GOOD_COLOR : DQN_TESTER_BAD_COLOR, \ - (test)->num_tests_ok_in_group, \ - (test)->num_tests_in_group, \ - all_clear ? "OK" : "FAILED"); \ - } while (0) +/// Creates _ .e. group_123_ +#define DQN_TESTER_UNIQUE_NAME(prefix) \ + DQN_TESTER_TOKEN_COMBINE(DQN_TESTER_TOKEN_COMBINE(prefix, __LINE__), _) + +#define DQN_TESTER_GROUP(group, fmt, ...) \ + for (Dqn_Tester *test_group_ = (group = Dqn_Tester_BeginGroup(fmt, ## __VA_ARGS__), &group); \ + !test_group_->finished; \ + Dqn_Tester_EndGroup(test_group_)) + +#define DQN_TESTER_TEST(fmt, ...) \ + for (int DQN_TESTER_UNIQUE_NAME(dummy_) = (Dqn_Tester_Begin(test_group_, fmt, ## __VA_ARGS__), 0); \ + (void)DQN_TESTER_UNIQUE_NAME(dummy_), test_group_->state == Dqn_TesterTestState_TestBegun; \ + Dqn_Tester_End(test_group_)) #define DQN_TESTER_ASSERTF(test, expr, fmt, ...) \ DQN_TESTER_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__) @@ -92,7 +96,7 @@ if ((test)->log_count++ == 0) { \ fprintf(stdout, "\n"); \ } \ - (test)->state = Dqn_TesterState_TestFailed; \ + (test)->state = Dqn_TesterTestState_TestFailed; \ fprintf(stderr, \ "%*sAssertion Triggered\n" \ "%*sFile: %s:%d\n" \ @@ -118,7 +122,7 @@ if ((test)->log_count++ == 0) { \ fprintf(stdout, "\n"); \ } \ - (test)->state = Dqn_TesterState_TestFailed; \ + (test)->state = Dqn_TesterTestState_TestFailed; \ fprintf(stderr, \ "%*sFile: %s:%d\n" \ "%*sExpression: [" #expr "]\n", \ @@ -133,43 +137,71 @@ // NOTE: Header // ----------------------------------------------------------------------------- -enum Dqn_TesterState { - Dqn_TesterState_Nil, - Dqn_TesterState_TestBegun, - Dqn_TesterState_TestFailed, -}; +typedef enum Dqn_TesterTestState { + Dqn_TesterTestState_Nil, + Dqn_TesterTestState_TestBegun, + Dqn_TesterTestState_TestFailed, +} Dqn_TesterTestState; typedef struct Dqn_Tester { - int num_tests_in_group; - int num_tests_ok_in_group; - int log_count; - Dqn_TesterState state; + int num_tests_in_group; + int num_tests_ok_in_group; + int log_count; + Dqn_TesterTestState state; + bool finished; } Dqn_Tester; +Dqn_Tester Dqn_Tester_BeginGroupV(char const *fmt, va_list args); +Dqn_Tester Dqn_Tester_BeginGroup(char const *fmt, ...); +void Dqn_Tester_EndGroup(Dqn_Tester *test); + void Dqn_Tester_BeginV(Dqn_Tester *test, char const *fmt, va_list args); void Dqn_Tester_Begin(Dqn_Tester *test, char const *fmt, ...); void Dqn_Tester_End(Dqn_Tester *test); -#if defined(__cplusplus) -struct Dqn_TesterBeginScopedTest { - Dqn_TesterBeginScopedTest(Dqn_Tester *test, char const *fmt, ...); - ~Dqn_TesterBeginScopedTest(); - Dqn_Tester *test; -}; -#endif // __cplusplus -#endif // DQN_TESTER_H - // NOTE: Implementation // ----------------------------------------------------------------------------- #if defined(DQN_TESTER_IMPLEMENTATION) +Dqn_Tester Dqn_Tester_BeginGroupV(char const *fmt, va_list args) +{ + fprintf(stdout, fmt, args); + fputc('\n', stdout); + Dqn_Tester result = {}; + return result; +} + +Dqn_Tester Dqn_Tester_BeginGroup(char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Tester result = Dqn_Tester_BeginGroupV(fmt, args); + va_end(args); + return result; +} + +void Dqn_Tester_EndGroup(Dqn_Tester *test) +{ + if (test->finished) + return; + + test->finished = true; + bool all_clear = test->num_tests_ok_in_group == test->num_tests_in_group; + fprintf(stdout, + "%s\n %02d/%02d tests passed -- %s\n\n" DQN_TESTER_COLOR_RESET, + all_clear ? DQN_TESTER_GOOD_COLOR : DQN_TESTER_BAD_COLOR, + test->num_tests_ok_in_group, + test->num_tests_in_group, + all_clear ? "OK" : "FAILED"); +} + void Dqn_Tester_BeginV(Dqn_Tester *test, char const *fmt, va_list args) { - assert(test->state == Dqn_TesterState_Nil && + assert(test->state == Dqn_TesterTestState_Nil && "Nesting a unit test within another unit test is not allowed, ensure" "the first test has finished by calling Dqn_Tester_End"); test->num_tests_in_group++; - test->state = Dqn_TesterState_TestBegun; + test->state = Dqn_TesterTestState_TestBegun; test->log_count = 0; int size_required = 0; @@ -196,7 +228,7 @@ void Dqn_Tester_Begin(Dqn_Tester *test, char const *fmt, ...) void Dqn_Tester_End(Dqn_Tester *test) { - assert(test->state != Dqn_TesterState_Nil && "Test was marked as ended but a test was never commenced using Dqn_Tester_Begin"); + assert(test->state != Dqn_TesterTestState_Nil && "Test was marked as ended but a test was never commenced using Dqn_Tester_Begin"); if (test->log_count != 0) { // NOTE: We try and print the result on the same line as the test name, // but if there were logs printed throughout the test then we must print @@ -206,7 +238,7 @@ void Dqn_Tester_End(Dqn_Tester *test) putc(DQN_TESTER_RESULT_PAD_CHAR, stdout); } - if (test->state == Dqn_TesterState_TestFailed) { + if (test->state == Dqn_TesterTestState_TestFailed) { fprintf(stdout, DQN_TESTER_BAD_COLOR " FAILED"); } else { fprintf(stdout, DQN_TESTER_GOOD_COLOR " OK"); @@ -218,21 +250,7 @@ void Dqn_Tester_End(Dqn_Tester *test) putc('\n', stdout); } - test->state = Dqn_TesterState_Nil; + test->state = Dqn_TesterTestState_Nil; } - -#if defined(__cplusplus) -Dqn_TesterBeginScopedTest::Dqn_TesterBeginScopedTest(Dqn_Tester *test, char const *fmt, ...) -: test(test) -{ - va_list args; - va_start(args, fmt); - Dqn_Tester_BeginV(test, fmt, args); - va_end(args); -} - -Dqn_TesterBeginScopedTest::~Dqn_TesterBeginScopedTest() { - Dqn_Tester_End(test); -} -#endif // __cplusplus #endif // DQN_TESTER_IMPLEMENTATION +#endif // DQN_TESTER_H diff --git a/dqn_unit_tests.cpp b/dqn_unit_tests.cpp index 0370c44..69a1aa8 100644 --- a/dqn_unit_tests.cpp +++ b/dqn_unit_tests.cpp @@ -8,14 +8,6 @@ #if defined(DQN_TEST_WITH_MAIN) #define DQN_IMPLEMENTATION - #define DQN_WITH_DSMAP // Dqn_DSMap - #define DQN_WITH_FIXED_ARRAY // Dqn_FArray - #define DQN_WITH_FIXED_STRING // Dqn_FString8 - #define DQN_WITH_HEX // Dqn_Hex and friends ... - #define DQN_WITH_JSON_BUILDER // Dqn_JSONBuilder - #define DQN_WITH_MAP // Dqn_Map - #define DQN_WITH_MATH // Dqn_V2/3/4/Mat4 and friends ... - #define DQN_WITH_WIN_NET // #include "dqn.h" #define DQN_KECCAK_IMPLEMENTATION @@ -30,542 +22,443 @@ Dqn_Tester Dqn_Test_File() { Dqn_Tester test = {}; - DQN_TESTER_BEGIN_GROUP("Dqn_Fs"); + DQN_TESTER_GROUP(test, "Dqn_Fs") { - Dqn_Arena arena = {}; - Dqn_Allocator allocator = Dqn_Arena_Allocator(&arena); - Dqn_Tester_Begin(&test, "Make directory recursive \"abcd/efgh\""); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_MakeDir(DQN_STRING8("abcd/efgh")), "Failed to make directory"); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_DirExists(DQN_STRING8("abcd")), "Directory was not made"); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_DirExists(DQN_STRING8("abcd/efgh")), "Subdirectory was not made"); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_Exists(DQN_STRING8("abcd")) == false, "This function should only return true for files"); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_Exists(DQN_STRING8("abcd/efgh")) == false, "This function should only return true for files"); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_Delete(DQN_STRING8("abcd/efgh")), "Failed to delete directory"); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_Delete(DQN_STRING8("abcd")), "Failed to cleanup directory"); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Make directory recursive \"abcd/efgh\"") { + DQN_TESTER_ASSERTF(&test, Dqn_Fs_MakeDir(DQN_STRING8("abcd/efgh")), "Failed to make directory"); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_DirExists(DQN_STRING8("abcd")), "Directory was not made"); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_DirExists(DQN_STRING8("abcd/efgh")), "Subdirectory was not made"); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_Exists(DQN_STRING8("abcd")) == false, "This function should only return true for files"); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_Exists(DQN_STRING8("abcd/efgh")) == false, "This function should only return true for files"); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_Delete(DQN_STRING8("abcd/efgh")), "Failed to delete directory"); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_Delete(DQN_STRING8("abcd")), "Failed to cleanup directory"); + } + + DQN_TESTER_TEST("Write file, read it, copy it, move it and delete it") { + // NOTE: Write step + Dqn_String8 const SRC_FILE = DQN_STRING8("dqn_test_file"); + Dqn_b32 write_result = Dqn_Fs_WriteCString8(SRC_FILE.data, SRC_FILE.size, "test", 4); + DQN_TESTER_ASSERT(&test, write_result); + DQN_TESTER_ASSERT(&test, Dqn_Fs_Exists(SRC_FILE)); + + // NOTE: Read step + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 read_file = Dqn_Fs_ReadString8(SRC_FILE, scratch.allocator); + DQN_TESTER_ASSERTF(&test, Dqn_String8_IsValid(read_file), "Failed to load file"); + DQN_TESTER_ASSERTF(&test, read_file.size == 4, "File read wrong amount of bytes"); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(read_file, DQN_STRING8("test")), "read(%zu): %.*s", read_file.size, DQN_STRING_FMT(read_file)); + + // NOTE: Copy step + Dqn_String8 const COPY_FILE = DQN_STRING8("dqn_test_file_copy"); + Dqn_b32 copy_result = Dqn_Fs_Copy(SRC_FILE, COPY_FILE, true /*overwrite*/); + DQN_TESTER_ASSERT(&test, copy_result); + DQN_TESTER_ASSERT(&test, Dqn_Fs_Exists(COPY_FILE)); + + // NOTE: Move step + Dqn_String8 const MOVE_FILE = DQN_STRING8("dqn_test_file_move"); + Dqn_b32 move_result = Dqn_Fs_Move(COPY_FILE, MOVE_FILE, true /*overwrite*/); + DQN_TESTER_ASSERT(&test, move_result); + DQN_TESTER_ASSERT(&test, Dqn_Fs_Exists(MOVE_FILE)); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_Exists(COPY_FILE) == false, "Moving a file should remove the original"); + + // NOTE: Delete step + Dqn_b32 delete_src_file = Dqn_Fs_Delete(SRC_FILE); + Dqn_b32 delete_moved_file = Dqn_Fs_Delete(MOVE_FILE); + DQN_TESTER_ASSERT(&test, delete_src_file); + DQN_TESTER_ASSERT(&test, delete_moved_file); + + // NOTE: Deleting non-existent file fails + Dqn_b32 delete_non_existent_src_file = Dqn_Fs_Delete(SRC_FILE); + Dqn_b32 delete_non_existent_moved_file = Dqn_Fs_Delete(MOVE_FILE); + DQN_TESTER_ASSERT(&test, delete_non_existent_moved_file == false); + DQN_TESTER_ASSERT(&test, delete_non_existent_src_file == false); + } } - - { - // NOTE: Write step - Dqn_String8 const SRC_FILE = DQN_STRING8("dqn_test_file"); - Dqn_Tester_Begin(&test, "Write file, read it, copy it, move it and delete it"); - Dqn_b32 write_result = Dqn_Fs_WriteCString8(SRC_FILE.data, SRC_FILE.size, "test", 4); - DQN_TESTER_ASSERT(&test, write_result); - DQN_TESTER_ASSERT(&test, Dqn_Fs_Exists(SRC_FILE)); - - // NOTE: Read step - Dqn_Arena arena = {}; - Dqn_String8 read_file = Dqn_Fs_ReadString8(SRC_FILE, Dqn_Arena_Allocator(&arena)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_IsValid(read_file), "Failed to load file"); - DQN_TESTER_ASSERTF(&test, read_file.size == 4, "File read wrong amount of bytes"); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(read_file, DQN_STRING8("test")), "read(%zu): %.*s", read_file.size, DQN_STRING_FMT(read_file)); - - // NOTE: Copy step - Dqn_String8 const COPY_FILE = DQN_STRING8("dqn_test_file_copy"); - Dqn_b32 copy_result = Dqn_Fs_Copy(SRC_FILE, COPY_FILE, true /*overwrite*/); - DQN_TESTER_ASSERT(&test, copy_result); - DQN_TESTER_ASSERT(&test, Dqn_Fs_Exists(COPY_FILE)); - - // NOTE: Move step - Dqn_String8 const MOVE_FILE = DQN_STRING8("dqn_test_file_move"); - Dqn_b32 move_result = Dqn_Fs_Move(COPY_FILE, MOVE_FILE, true /*overwrite*/); - DQN_TESTER_ASSERT(&test, move_result); - DQN_TESTER_ASSERT(&test, Dqn_Fs_Exists(MOVE_FILE)); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_Exists(COPY_FILE) == false, "Moving a file should remove the original"); - - // NOTE: Delete step - Dqn_b32 delete_src_file = Dqn_Fs_Delete(SRC_FILE); - Dqn_b32 delete_moved_file = Dqn_Fs_Delete(MOVE_FILE); - DQN_TESTER_ASSERT(&test, delete_src_file); - DQN_TESTER_ASSERT(&test, delete_moved_file); - - // NOTE: Deleting non-existent file fails - Dqn_b32 delete_non_existent_src_file = Dqn_Fs_Delete(SRC_FILE); - Dqn_b32 delete_non_existent_moved_file = Dqn_Fs_Delete(MOVE_FILE); - DQN_TESTER_ASSERT(&test, delete_non_existent_moved_file == false); - DQN_TESTER_ASSERT(&test, delete_non_existent_src_file == false); - - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - DQN_TESTER_END_GROUP(&test); return test; } Dqn_Tester Dqn_Test_FixedArray() { Dqn_Tester test = {}; -#if defined(DQN_WITH_FIXED_ARRAY) - DQN_TESTER_BEGIN_GROUP("Dqn_FArray"); - // NOTE: Dqn_FArray_Init - { - Dqn_Tester_Begin(&test, "Initialise from raw array"); - int raw_array[] = {1, 2}; - auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 1); - DQN_TESTER_ASSERT(&test, array.data[1] == 2); - Dqn_Tester_End(&test); - } + DQN_TESTER_GROUP(test, "Dqn_FArray") { + DQN_TESTER_TEST("Initialise from raw array") { + int raw_array[] = {1, 2}; + auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); + DQN_TESTER_ASSERT(&test, array.size == 2); + DQN_TESTER_ASSERT(&test, array.data[0] == 1); + DQN_TESTER_ASSERT(&test, array.data[1] == 2); + } - // NOTE: Dqn_FArray_EraseStable - { - Dqn_Tester_Begin(&test, "Erase stable 1 element from array"); - int raw_array[] = {1, 2, 3}; - auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); - Dqn_FArray_EraseStable(&array, 1); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 1); - DQN_TESTER_ASSERT(&test, array.data[1] == 3); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Erase stable 1 element from array") { + int raw_array[] = {1, 2, 3}; + auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); + Dqn_FArray_EraseStable(&array, 1); + DQN_TESTER_ASSERT(&test, array.size == 2); + DQN_TESTER_ASSERT(&test, array.data[0] == 1); + DQN_TESTER_ASSERT(&test, array.data[1] == 3); + } - // NOTE: Dqn_FArray_EraseUnstable - { - Dqn_Tester_Begin(&test, "Erase unstable 1 element from array"); - int raw_array[] = {1, 2, 3}; - auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); - DQN_TESTER_ASSERT(&test, Dqn_FArray_EraseUnstable(&array, 0)); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 3); - DQN_TESTER_ASSERT(&test, array.data[1] == 2); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Erase unstable 1 element from array") { + int raw_array[] = {1, 2, 3}; + auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); + DQN_TESTER_ASSERT(&test, Dqn_FArray_EraseUnstable(&array, 0)); + DQN_TESTER_ASSERT(&test, array.size == 2); + DQN_TESTER_ASSERT(&test, array.data[0] == 3); + DQN_TESTER_ASSERT(&test, array.data[1] == 2); + } - // NOTE: Dqn_FArray_Add - { - Dqn_Tester_Begin(&test, "Add 1 element to array"); - int const ITEM = 2; - int raw_array[] = {1}; - auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); - Dqn_FArray_Add(&array, ITEM); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 1); - DQN_TESTER_ASSERT(&test, array.data[1] == ITEM); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Add 1 element to array") { + int const ITEM = 2; + int raw_array[] = {1}; + auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); + Dqn_FArray_Add(&array, ITEM); + DQN_TESTER_ASSERT(&test, array.size == 2); + DQN_TESTER_ASSERT(&test, array.data[0] == 1); + DQN_TESTER_ASSERT(&test, array.data[1] == ITEM); + } - // NOTE: Dqn_FArray_Clear - { - Dqn_Tester_Begin(&test, "Clear array"); - int raw_array[] = {1}; - auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); - Dqn_FArray_Clear(&array, Dqn_ZeroMem_No); - DQN_TESTER_ASSERT(&test, array.size == 0); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Clear array") { + int raw_array[] = {1}; + auto array = Dqn_FArray_Init(raw_array, (int)Dqn_CArray_Count(raw_array)); + Dqn_FArray_Clear(&array, Dqn_ZeroMem_No); + DQN_TESTER_ASSERT(&test, array.size == 0); + } } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_FIXED_ARRAY return test; } Dqn_Tester Dqn_Test_FString8() { Dqn_Tester test = {}; -#if defined(DQN_WITH_FIXED_STRING) - DQN_TESTER_BEGIN_GROUP("Dqn_FString8"); + DQN_TESTER_GROUP(test, "Dqn_FString8") { + DQN_TESTER_TEST("Append too much fails") { + Dqn_FString8<4> str = {}; + DQN_TESTER_ASSERTF(&test, Dqn_FString8_AppendCString8(&str, "abcd") == false, "We need space for the null-terminator"); + } - // NOTE: Dqn_FString8_Append - { - Dqn_Tester_Begin(&test, "Append too much fails"); - Dqn_FString8<4> str = {}; - DQN_TESTER_ASSERTF(&test, Dqn_FString8_AppendCString8(&str, "abcd") == false, "We need space for the null-terminator"); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Append format string too much fails") { + Dqn_FString8<4> str = {}; + DQN_TESTER_ASSERTF(&test, Dqn_FString8_AppendF(&str, "abcd") == false, "We need space for the null-terminator"); + } } - - // NOTE: Dqn_FString8_AppendFmt - { - Dqn_Tester_Begin(&test, "Append format string too much fails"); - Dqn_FString8<4> str = {}; - DQN_TESTER_ASSERTF(&test, Dqn_FString8_AppendF(&str, "abcd") == false, "We need space for the null-terminator"); - Dqn_Tester_End(&test); - } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_FIXED_STRING return test; } Dqn_Tester Dqn_Test_Hex() { Dqn_Tester test = {}; -#if defined(DQN_WITH_HEX) - DQN_TESTER_BEGIN_GROUP("Dqn_Hex"); - { - Dqn_Tester_Begin(&test, "Convert 0x123"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0x123")); - DQN_TESTER_ASSERTF(&test, result == 0x123, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_GROUP(test, "Dqn_Hex") { + DQN_TESTER_TEST("Convert 0x123") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0x123")); + DQN_TESTER_ASSERTF(&test, result == 0x123, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert 0xFFFF"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0xFFFF")); - DQN_TESTER_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert 0xFFFF") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0xFFFF")); + DQN_TESTER_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert FFFF"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("FFFF")); - DQN_TESTER_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert FFFF") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("FFFF")); + DQN_TESTER_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert abCD"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("abCD")); - DQN_TESTER_ASSERTF(&test, result == 0xabCD, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert abCD") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("abCD")); + DQN_TESTER_ASSERTF(&test, result == 0xabCD, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert 0xabCD"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0xabCD")); - DQN_TESTER_ASSERTF(&test, result == 0xabCD, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert 0xabCD") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0xabCD")); + DQN_TESTER_ASSERTF(&test, result == 0xabCD, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert 0x"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0x")); - DQN_TESTER_ASSERTF(&test, result == 0x0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert 0x") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0x")); + DQN_TESTER_ASSERTF(&test, result == 0x0, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert 0X"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0X")); - DQN_TESTER_ASSERTF(&test, result == 0x0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert 0X") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("0X")); + DQN_TESTER_ASSERTF(&test, result == 0x0, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert 3"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("3")); - DQN_TESTER_ASSERTF(&test, result == 3, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert 3") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("3")); + DQN_TESTER_ASSERTF(&test, result == 3, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert f"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("f")); - DQN_TESTER_ASSERTF(&test, result == 0xf, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert f") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("f")); + DQN_TESTER_ASSERTF(&test, result == 0xf, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert g"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("g")); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Convert g") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("g")); + DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "Convert -0x3"); - uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("-0x3")); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Convert -0x3") { + uint64_t result = Dqn_Hex_String8ToU64(DQN_STRING8("-0x3")); + DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + } } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_HEX return test; } Dqn_Tester Dqn_Test_M4() { Dqn_Tester test = {}; -#if defined(DQN_WITH_MATH) - DQN_TESTER_BEGIN_GROUP("Dqn_M4"); - { - Dqn_Tester_Begin(&test, "Simple translate and scale matrix"); - Dqn_M4 translate = Dqn_M4_TranslateF(1, 2, 3); - Dqn_M4 scale = Dqn_M4_ScaleF(2, 2, 2); - Dqn_M4 result = Dqn_M4_Mul(translate, scale); + DQN_TESTER_GROUP(test, "Dqn_M4") { + DQN_TESTER_TEST("Simple translate and scale matrix") { + Dqn_M4 translate = Dqn_M4_TranslateF(1, 2, 3); + Dqn_M4 scale = Dqn_M4_ScaleF(2, 2, 2); + Dqn_M4 result = Dqn_M4_Mul(translate, scale); - const Dqn_M4 EXPECT = {{ - {2, 0, 0, 0}, - {0, 2, 0, 0}, - {0, 0, 2, 0}, - {1, 2, 3, 1}, - }}; + const Dqn_M4 EXPECT = {{ + {2, 0, 0, 0}, + {0, 2, 0, 0}, + {0, 0, 2, 0}, + {1, 2, 3, 1}, + }}; - DQN_TESTER_ASSERTF(&test, - memcmp(result.columns, EXPECT.columns, sizeof(EXPECT)) == 0, - "\nresult =\n%s\nexpected =\n%s", - Dqn_M4_ColumnMajorString(result).data, - Dqn_M4_ColumnMajorString(EXPECT).data); - Dqn_Tester_End(&test); + DQN_TESTER_ASSERTF(&test, + memcmp(result.columns, EXPECT.columns, sizeof(EXPECT)) == 0, + "\nresult =\n%s\nexpected =\n%s", + Dqn_M4_ColumnMajorString(result).data, + Dqn_M4_ColumnMajorString(EXPECT).data); + } } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_MATH return test; } Dqn_Tester Dqn_Test_DSMap() { Dqn_Tester test = {}; -#if defined(DQN_WITH_DSMAP) - DQN_TESTER_BEGIN_GROUP("Dqn_DSMap"); - { - Dqn_Tester_Begin(&test, "Add r-value item to map"); - Dqn_DSMap map = Dqn_DSMap_Init(128); - Dqn_DSMapItem *entry = Dqn_DSMap_Add(&map, 3 /*hash*/, 5 /*value*/); - DQN_TESTER_ASSERTF(&test, map.size == 128, "size: %I64d", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); - DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); + DQN_TESTER_GROUP(test, "Dqn_DSMap") { + DQN_TESTER_TEST("Add r-value item to map") { + Dqn_DSMap map = Dqn_DSMap_Init(128); + Dqn_DSMapItem *entry = Dqn_DSMap_Add(&map, 3 /*hash*/, 5 /*value*/); + DQN_TESTER_ASSERTF(&test, map.size == 128, "size: %I64d", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); + DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } + + DQN_TESTER_TEST("Add l-value item to map") { + Dqn_DSMap map = Dqn_DSMap_Init(128); + int value = 5; + Dqn_DSMapItem *entry = Dqn_DSMap_Add(&map, 3 /*hash*/, value); + DQN_TESTER_ASSERTF(&test, map.size == 128, "size: %I64d", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); + DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } + + DQN_TESTER_TEST("Get item from map") { + Dqn_DSMap map = Dqn_DSMap_Init(128); + Dqn_DSMapItem *entry = Dqn_DSMap_Add(&map, 3 /*hash*/, 5 /*value*/); + Dqn_DSMapItem *get_entry = Dqn_DSMap_Get(&map, 3 /*hash*/); + DQN_TESTER_ASSERTF(&test, get_entry == entry, "get_entry: %p, entry: %p", get_entry, entry); + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } + + DQN_TESTER_TEST("Get non-existent item from map") { + Dqn_DSMap map = Dqn_DSMap_Init(128); + Dqn_DSMapItem *entry = Dqn_DSMap_Get(&map, 3 /*hash*/); + DQN_TESTER_ASSERT(&test, entry == nullptr); + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } + + DQN_TESTER_TEST("Erase item from map") { + Dqn_DSMap map = Dqn_DSMap_Init(128); + Dqn_DSMap_Add(&map, 3 /*hash*/, 5 /*value*/); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %I64d", map.count); + Dqn_DSMap_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_No); + DQN_TESTER_ASSERTF(&test, map.count == 0, "count: %I64d", map.count); + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } + + DQN_TESTER_TEST("Erase non-existent item from map") { + Dqn_DSMap map = Dqn_DSMap_Init(128); + Dqn_DSMap_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_No); + DQN_TESTER_ASSERTF(&test, map.count == 0, "count: %I64d", map.count); + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } + + DQN_TESTER_TEST("Test resize on maximum load") { + const Dqn_isize INIT_SIZE = 4; + Dqn_DSMap map = Dqn_DSMap_Init(INIT_SIZE); + Dqn_DSMap_Add(&map, 0 /*hash*/, 5 /*value*/); + Dqn_DSMap_Add(&map, 1 /*hash*/, 5 /*value*/); + DQN_TESTER_ASSERTF(&test, map.count == 2, "count: %I64d", map.count); + + // This *should* cause a resize because 3/4 slots filled is 75% load + Dqn_DSMap_Add(&map, 6 /*hash*/, 5 /*value*/); + DQN_TESTER_ASSERTF(&test, map.count == 3, "count: %I64d", map.count); + DQN_TESTER_ASSERTF(&test, map.size == INIT_SIZE * 2, "size: %I64d", map.size); + + // Check that the elements are rehashed where we expected them to be + DQN_TESTER_ASSERT(&test, map.slots[0].occupied == DQN_CAST(uint8_t)true); + DQN_TESTER_ASSERT(&test, map.slots[1].occupied == DQN_CAST(uint8_t)true); + DQN_TESTER_ASSERT(&test, map.slots[2].occupied == DQN_CAST(uint8_t)false); + DQN_TESTER_ASSERT(&test, map.slots[3].occupied == DQN_CAST(uint8_t)false); + DQN_TESTER_ASSERT(&test, map.slots[4].occupied == DQN_CAST(uint8_t)false); + DQN_TESTER_ASSERT(&test, map.slots[5].occupied == DQN_CAST(uint8_t)false); + DQN_TESTER_ASSERT(&test, map.slots[6].occupied == DQN_CAST(uint8_t)true); + DQN_TESTER_ASSERT(&test, map.slots[7].occupied == DQN_CAST(uint8_t)false); + + DQN_TESTER_ASSERTF(&test, map.slots[0].value == 5, "value: %d", map.slots[0].value); + DQN_TESTER_ASSERTF(&test, map.slots[1].value == 5, "value: %d", map.slots[1].value); + DQN_TESTER_ASSERTF(&test, map.slots[6].value == 5, "value: %d", map.slots[6].value); + + Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); + } } - - { - Dqn_Tester_Begin(&test, "Add l-value item to map"); - Dqn_DSMap map = Dqn_DSMap_Init(128); - int value = 5; - Dqn_DSMapItem *entry = Dqn_DSMap_Add(&map, 3 /*hash*/, value); - DQN_TESTER_ASSERTF(&test, map.size == 128, "size: %I64d", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); - DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Get item from map"); - Dqn_DSMap map = Dqn_DSMap_Init(128); - Dqn_DSMapItem *entry = Dqn_DSMap_Add(&map, 3 /*hash*/, 5 /*value*/); - Dqn_DSMapItem *get_entry = Dqn_DSMap_Get(&map, 3 /*hash*/); - DQN_TESTER_ASSERTF(&test, get_entry == entry, "get_entry: %p, entry: %p", get_entry, entry); - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Get non-existent item from map"); - Dqn_DSMap map = Dqn_DSMap_Init(128); - Dqn_DSMapItem *entry = Dqn_DSMap_Get(&map, 3 /*hash*/); - DQN_TESTER_ASSERT(&test, entry == nullptr); - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Erase item from map"); - Dqn_DSMap map = Dqn_DSMap_Init(128); - Dqn_DSMap_Add(&map, 3 /*hash*/, 5 /*value*/); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %I64d", map.count); - Dqn_DSMap_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_No); - DQN_TESTER_ASSERTF(&test, map.count == 0, "count: %I64d", map.count); - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Erase non-existent item from map"); - Dqn_DSMap map = Dqn_DSMap_Init(128); - Dqn_DSMap_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_No); - DQN_TESTER_ASSERTF(&test, map.count == 0, "count: %I64d", map.count); - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Test resize on maximum load"); - const Dqn_isize INIT_SIZE = 4; - Dqn_DSMap map = Dqn_DSMap_Init(INIT_SIZE); - Dqn_DSMap_Add(&map, 0 /*hash*/, 5 /*value*/); - Dqn_DSMap_Add(&map, 1 /*hash*/, 5 /*value*/); - DQN_TESTER_ASSERTF(&test, map.count == 2, "count: %I64d", map.count); - - // This *should* cause a resize because 3/4 slots filled is 75% load - Dqn_DSMap_Add(&map, 6 /*hash*/, 5 /*value*/); - DQN_TESTER_ASSERTF(&test, map.count == 3, "count: %I64d", map.count); - DQN_TESTER_ASSERTF(&test, map.size == INIT_SIZE * 2, "size: %I64d", map.size); - - // Check that the elements are rehashed where we expected them to be - DQN_TESTER_ASSERT(&test, map.slots[0].occupied == DQN_CAST(uint8_t)true); - DQN_TESTER_ASSERT(&test, map.slots[1].occupied == DQN_CAST(uint8_t)true); - DQN_TESTER_ASSERT(&test, map.slots[2].occupied == DQN_CAST(uint8_t)false); - DQN_TESTER_ASSERT(&test, map.slots[3].occupied == DQN_CAST(uint8_t)false); - DQN_TESTER_ASSERT(&test, map.slots[4].occupied == DQN_CAST(uint8_t)false); - DQN_TESTER_ASSERT(&test, map.slots[5].occupied == DQN_CAST(uint8_t)false); - DQN_TESTER_ASSERT(&test, map.slots[6].occupied == DQN_CAST(uint8_t)true); - DQN_TESTER_ASSERT(&test, map.slots[7].occupied == DQN_CAST(uint8_t)false); - - DQN_TESTER_ASSERTF(&test, map.slots[0].value == 5, "value: %d", map.slots[0].value); - DQN_TESTER_ASSERTF(&test, map.slots[1].value == 5, "value: %d", map.slots[1].value); - DQN_TESTER_ASSERTF(&test, map.slots[6].value == 5, "value: %d", map.slots[6].value); - - Dqn_DSMap_Free(&map, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_DSMAP return test; } Dqn_Tester Dqn_Test_Map() { Dqn_Tester test = {}; -#if defined(DQN_WITH_MAP) - DQN_TESTER_BEGIN_GROUP("Dqn_Map"); - Dqn_Arena arena = {}; - { - Dqn_Tester_Begin(&test, "Add r-value item to map"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_MapEntry *entry = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5 /*value*/, Dqn_MapCollideRule::Overwrite); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %I64d", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); - DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); - DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); - DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); + DQN_TESTER_GROUP(test, "Dqn_Map") { + DQN_TESTER_TEST("Add r-value item to map") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_MapEntry *entry = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5 /*value*/, Dqn_MapCollideRule::Overwrite); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %I64d", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); + DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); + DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); + DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); + } + + DQN_TESTER_TEST("Add l-value item to map") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + int value = 5; + Dqn_MapEntry *entry = Dqn_Map_Add(&map, 3 /*hash*/, value, Dqn_MapCollideRule::Overwrite); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %I64d", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); + DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); + DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); + DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); + } + + DQN_TESTER_TEST("Add r-value item and overwrite on collision") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_MapEntry *entry_a = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); + Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Overwrite); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); + DQN_TESTER_ASSERTF(&test, entry_a == entry_b, "Expected entry to be overwritten"); + DQN_TESTER_ASSERTF(&test, entry_b->hash == 4, "hash: %zu", entry_b->hash); + DQN_TESTER_ASSERTF(&test, entry_b->value == 6, "value: %d", entry_b->value); + DQN_TESTER_ASSERTF(&test, entry_b->next == nullptr, "next: %p", entry_b->next); + } + + DQN_TESTER_TEST("Add r-value item and fail on collision") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); + Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Fail); + DQN_TESTER_ASSERTF(&test, entry_b == nullptr, "Expected entry to be overwritten"); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); + } + + DQN_TESTER_TEST("Add r-value item and chain on collision") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_MapEntry *entry_a = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); + Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 1, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); + DQN_TESTER_ASSERTF(&test, entry_a != entry_b, "Expected colliding entry to be chained"); + DQN_TESTER_ASSERTF(&test, entry_a->next == entry_b, "Expected chained entry to be next to our first map entry"); + DQN_TESTER_ASSERTF(&test, entry_b->hash == 4, "hash: %zu", entry_b->hash); + DQN_TESTER_ASSERTF(&test, entry_b->value == 6, "value: %d", entry_b->value); + DQN_TESTER_ASSERTF(&test, entry_b->next == nullptr, "next: %p", entry_b->next); + } + + DQN_TESTER_TEST("Add r-value item and get them back out again") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_MapEntry *entry_a = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); + Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); + + Dqn_MapEntry *entry_a_copy = Dqn_Map_Get(&map, 3 /*hash*/); + Dqn_MapEntry *entry_b_copy = Dqn_Map_Get(&map, 4 /*hash*/); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 1, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); + DQN_TESTER_ASSERT(&test, entry_a_copy == entry_a); + DQN_TESTER_ASSERT(&test, entry_b_copy == entry_b); + } + + DQN_TESTER_TEST("Add r-value item and erase it") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); + Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); + Dqn_Map_Get(&map, 3 /*hash*/); + + Dqn_Map_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_No); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list != nullptr, "free_list: %p", map.free_list); + + DQN_TESTER_ASSERTF(&test, map.free_list->hash == 3, "Entry should not be zeroed out on erase"); + DQN_TESTER_ASSERTF(&test, map.free_list->value == 5, "Entry should not be zeroed out on erase"); + DQN_TESTER_ASSERTF(&test, map.free_list->next == nullptr, "This should be the first and only entry in the free list"); + + Dqn_MapEntry *entry = Dqn_Map_Get(&map, 4 /*hash*/); + DQN_TESTER_ASSERTF(&test, entry->hash == 4, "hash: %zu", entry->hash); + DQN_TESTER_ASSERTF(&test, entry->value == 6, "value: %d", entry->value); + DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); + } + + DQN_TESTER_TEST("Add r-value item and erase it, zeroing the memory out") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Map map = Dqn_Map_InitWithArena(scratch.arena, 1); + Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); + Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); + Dqn_Map_Get(&map, 3 /*hash*/); + + Dqn_Map_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_Yes); + DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); + DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); + DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); + DQN_TESTER_ASSERTF(&test, map.free_list != nullptr, "free_list: %p", map.free_list); + + DQN_TESTER_ASSERTF(&test, map.free_list->hash == 0, "Entry should be zeroed out on erase"); + DQN_TESTER_ASSERTF(&test, map.free_list->value == 0, "Entry should be zeroed out on erase"); + DQN_TESTER_ASSERTF(&test, map.free_list->next == nullptr, "This should be the first and only entry in the free list"); + + Dqn_MapEntry *entry = Dqn_Map_Get(&map, 4 /*hash*/); + DQN_TESTER_ASSERTF(&test, entry->hash == 4, "hash: %zu", entry->hash); + DQN_TESTER_ASSERTF(&test, entry->value == 6, "value: %d", entry->value); + DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); + } + + // TODO(dqn): Test free list is chained correctly + // TODO(dqn): Test deleting 'b' from the list in the situation [map] - [a]->[b], we currently only test deleting a } - - { - Dqn_Tester_Begin(&test, "Add l-value item to map"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - int value = 5; - Dqn_MapEntry *entry = Dqn_Map_Add(&map, 3 /*hash*/, value, Dqn_MapCollideRule::Overwrite); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %I64d", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); - DQN_TESTER_ASSERTF(&test, entry->hash == 3, "hash: %zu", entry->hash); - DQN_TESTER_ASSERTF(&test, entry->value == 5, "value: %d", entry->value); - DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Add r-value item and overwrite on collision"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_MapEntry *entry_a = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); - Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Overwrite); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); - DQN_TESTER_ASSERTF(&test, entry_a == entry_b, "Expected entry to be overwritten"); - DQN_TESTER_ASSERTF(&test, entry_b->hash == 4, "hash: %zu", entry_b->hash); - DQN_TESTER_ASSERTF(&test, entry_b->value == 6, "value: %d", entry_b->value); - DQN_TESTER_ASSERTF(&test, entry_b->next == nullptr, "next: %p", entry_b->next); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Add r-value item and fail on collision"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); - Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Fail); - DQN_TESTER_ASSERTF(&test, entry_b == nullptr, "Expected entry to be overwritten"); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Add r-value item and chain on collision"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_MapEntry *entry_a = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); - Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 1, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); - DQN_TESTER_ASSERTF(&test, entry_a != entry_b, "Expected colliding entry to be chained"); - DQN_TESTER_ASSERTF(&test, entry_a->next == entry_b, "Expected chained entry to be next to our first map entry"); - DQN_TESTER_ASSERTF(&test, entry_b->hash == 4, "hash: %zu", entry_b->hash); - DQN_TESTER_ASSERTF(&test, entry_b->value == 6, "value: %d", entry_b->value); - DQN_TESTER_ASSERTF(&test, entry_b->next == nullptr, "next: %p", entry_b->next); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Add r-value item and get them back out again"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_MapEntry *entry_a = Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); - Dqn_MapEntry *entry_b = Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); - - Dqn_MapEntry *entry_a_copy = Dqn_Map_Get(&map, 3 /*hash*/); - Dqn_MapEntry *entry_b_copy = Dqn_Map_Get(&map, 4 /*hash*/); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 1, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list == nullptr, "free_list: %p", map.free_list); - DQN_TESTER_ASSERT(&test, entry_a_copy == entry_a); - DQN_TESTER_ASSERT(&test, entry_b_copy == entry_b); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Add r-value item and erase it"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); - Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); - Dqn_Map_Get(&map, 3 /*hash*/); - - Dqn_Map_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_No); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list != nullptr, "free_list: %p", map.free_list); - - DQN_TESTER_ASSERTF(&test, map.free_list->hash == 3, "Entry should not be zeroed out on erase"); - DQN_TESTER_ASSERTF(&test, map.free_list->value == 5, "Entry should not be zeroed out on erase"); - DQN_TESTER_ASSERTF(&test, map.free_list->next == nullptr, "This should be the first and only entry in the free list"); - - Dqn_MapEntry *entry = Dqn_Map_Get(&map, 4 /*hash*/); - DQN_TESTER_ASSERTF(&test, entry->hash == 4, "hash: %zu", entry->hash); - DQN_TESTER_ASSERTF(&test, entry->value == 6, "value: %d", entry->value); - DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); - - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "Add r-value item and erase it, zeroing the memory out"); - Dqn_Map map = Dqn_Map_InitWithArena(&arena, 1); - Dqn_Map_AddCopy(&map, 3 /*hash*/, 5, Dqn_MapCollideRule::Overwrite); - Dqn_Map_AddCopy(&map, 4 /*hash*/, 6, Dqn_MapCollideRule::Chain); - Dqn_Map_Get(&map, 3 /*hash*/); - - Dqn_Map_Erase(&map, 3 /*hash*/, Dqn_ZeroMem_Yes); - DQN_TESTER_ASSERTF(&test, map.size == 1, "size: %zu", map.size); - DQN_TESTER_ASSERTF(&test, map.count == 1, "count: %zu", map.count); - DQN_TESTER_ASSERTF(&test, map.chain_count == 0, "chain_count: %zu", map.chain_count); - DQN_TESTER_ASSERTF(&test, map.free_list != nullptr, "free_list: %p", map.free_list); - - DQN_TESTER_ASSERTF(&test, map.free_list->hash == 0, "Entry should be zeroed out on erase"); - DQN_TESTER_ASSERTF(&test, map.free_list->value == 0, "Entry should be zeroed out on erase"); - DQN_TESTER_ASSERTF(&test, map.free_list->next == nullptr, "This should be the first and only entry in the free list"); - - Dqn_MapEntry *entry = Dqn_Map_Get(&map, 4 /*hash*/); - DQN_TESTER_ASSERTF(&test, entry->hash == 4, "hash: %zu", entry->hash); - DQN_TESTER_ASSERTF(&test, entry->value == 6, "value: %d", entry->value); - DQN_TESTER_ASSERTF(&test, entry->next == nullptr, "next: %p", entry->next); - - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - // TODO(dqn): Test free list is chained correctly - // TODO(dqn): Test deleting 'b' from the list in the situation [map] - [a]->[b], we currently only test deleting a - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_MAP return test; } @@ -576,87 +469,66 @@ Dqn_Tester Dqn_Test_Intrinsics() // atomics/intrinsics are implemented using macros we ensure the macro was // written properly with these tests. - DQN_TESTER_BEGIN_GROUP("Dqn_Atomic_"); - { - Dqn_Tester_Begin(&test, "Dqn_Atomic_AddU32"); - uint32_t val = 0; - Dqn_Atomic_AddU32(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 1, "val: %u", val); - Dqn_Tester_End(&test); - } + DQN_TESTER_GROUP(test, "Dqn_Atomic") { + DQN_TESTER_TEST("Dqn_Atomic_AddU32") { + uint32_t val = 0; + Dqn_Atomic_AddU32(&val, 1); + DQN_TESTER_ASSERTF(&test, val == 1, "val: %u", val); + } - { - Dqn_Tester_Begin(&test, "Dqn_Atomic_AddU64"); - uint64_t val = 0; - Dqn_Atomic_AddU64(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 1, "val: %zu", val); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Dqn_Atomic_AddU64") { + uint64_t val = 0; + Dqn_Atomic_AddU64(&val, 1); + DQN_TESTER_ASSERTF(&test, val == 1, "val: %zu", val); + } - { - Dqn_Tester_Begin(&test, "Dqn_Atomic_SubU32"); - uint32_t val = 1; - Dqn_Atomic_SubU32(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 0, "val: %u", val); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Dqn_Atomic_SubU32") { + uint32_t val = 1; + Dqn_Atomic_SubU32(&val, 1); + DQN_TESTER_ASSERTF(&test, val == 0, "val: %u", val); + } - { - Dqn_Tester_Begin(&test, "Dqn_Atomic_SubU64"); - uint64_t val = 1; - Dqn_Atomic_SubU64(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 0, "val: %zu", val); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Dqn_Atomic_SubU64") { + uint64_t val = 1; + Dqn_Atomic_SubU64(&val, 1); + DQN_TESTER_ASSERTF(&test, val == 0, "val: %zu", val); + } - { - Dqn_Tester_Begin(&test, "Dqn_Atomic_SetValue32"); - long a = 0; - long b = 111; - Dqn_Atomic_SetValue32(&a, b); - DQN_TESTER_ASSERTF(&test, a == b, "a: %lu, b: %lu", a, b); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Dqn_Atomic_SetValue32") { + long a = 0; + long b = 111; + Dqn_Atomic_SetValue32(&a, b); + DQN_TESTER_ASSERTF(&test, a == b, "a: %lu, b: %lu", a, b); + } - { - Dqn_Tester_Begin(&test, "Dqn_Atomic_SetValue64"); - int64_t a = 0; - int64_t b = 111; - Dqn_Atomic_SetValue64(DQN_CAST(uint64_t *)&a, b); - DQN_TESTER_ASSERTF(&test, a == b, "a: %I64i, b: %I64i", a, b); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Dqn_Atomic_SetValue64") { + int64_t a = 0; + int64_t b = 111; + Dqn_Atomic_SetValue64(DQN_CAST(uint64_t *)&a, b); + DQN_TESTER_ASSERTF(&test, a == b, "a: %I64i, b: %I64i", a, b); + } - { Dqn_Tester_Begin(&test, "Dqn_CPUClockCycle"); Dqn_CPUClockCycle(); Dqn_Tester_End(&test); - } - { Dqn_Tester_Begin(&test, "Dqn_CompilerReadBarrierAndCPUReadFence"); Dqn_CompilerReadBarrierAndCPUReadFence; Dqn_Tester_End(&test); - } - { Dqn_Tester_Begin(&test, "Dqn_CompilerWriteBarrierAndCPUWriteFence"); Dqn_CompilerWriteBarrierAndCPUWriteFence; Dqn_Tester_End(&test); } - DQN_TESTER_END_GROUP(&test); + return test; } Dqn_Tester Dqn_Test_Rect() { Dqn_Tester test = {}; -#if defined(DQN_WITH_MATH) - DQN_TESTER_BEGIN_GROUP("Dqn_Rect"); - // NOTE: Dqn_Rect_Intersection - { - { - Dqn_Tester_Begin(&test, "No intersection"); + DQN_TESTER_GROUP(test, "Dqn_Rect") { + DQN_TESTER_TEST("No intersection") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2(0, 0), Dqn_V2(100, 100)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2(200, 0), Dqn_V2(200, 200)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -668,11 +540,9 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "A's min intersects B"); + DQN_TESTER_TEST("A's min intersects B") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2(50, 50), Dqn_V2(100, 100)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2( 0, 0), Dqn_V2(100, 100)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -684,11 +554,9 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "B's min intersects A"); + DQN_TESTER_TEST("B's min intersects A") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2( 0, 0), Dqn_V2(100, 100)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2(50, 50), Dqn_V2(100, 100)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -700,11 +568,9 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "A's max intersects B"); + DQN_TESTER_TEST("A's max intersects B") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2(-50, -50), Dqn_V2(100, 100)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2( 0, 0), Dqn_V2(100, 100)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -716,11 +582,9 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "B's max intersects A"); + DQN_TESTER_TEST("B's max intersects A") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2( 0, 0), Dqn_V2(100, 100)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2(-50, -50), Dqn_V2(100, 100)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -732,12 +596,10 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "B contains A"); + DQN_TESTER_TEST("B contains A") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2(25, 25), Dqn_V2( 25, 25)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2( 0, 0), Dqn_V2(100, 100)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -749,11 +611,9 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "A contains B"); + DQN_TESTER_TEST("A contains B") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2( 0, 0), Dqn_V2(100, 100)); Dqn_Rect b = Dqn_Rect_InitFromPosAndSize(Dqn_V2(25, 25), Dqn_V2( 25, 25)); Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -765,11 +625,9 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } - { - Dqn_Tester_Begin(&test, "A equals B"); + DQN_TESTER_TEST("A equals B") { Dqn_Rect a = Dqn_Rect_InitFromPosAndSize(Dqn_V2(0, 0), Dqn_V2(100, 100)); Dqn_Rect b = a; Dqn_Rect ab = Dqn_Rect_Intersection(a, b); @@ -781,670 +639,522 @@ Dqn_Tester Dqn_Test_Rect() ab.min.y, ab.max.x, ab.max.y); - Dqn_Tester_End(&test); } } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_WITH_MATH return test; } Dqn_Tester Dqn_Test_PerfCounter() { Dqn_Tester test = {}; - DQN_TESTER_BEGIN_GROUP("Dqn_OS_PerfCounter"); - { - Dqn_Tester_Begin(&test, "Dqn_OS_PerfCounterNow"); - uint64_t result = Dqn_OS_PerfCounterNow(); - DQN_TESTER_ASSERT(&test, result != 0); - Dqn_Tester_End(&test); - } + DQN_TESTER_GROUP(test, "Dqn_OS_PerfCounter") { + DQN_TESTER_TEST("Dqn_OS_PerfCounterNow") { + uint64_t result = Dqn_OS_PerfCounterNow(); + DQN_TESTER_ASSERT(&test, result != 0); + } - { - Dqn_Tester_Begin(&test, "Consecutive ticks are ordered"); - uint64_t a = Dqn_OS_PerfCounterNow(); - uint64_t b = Dqn_OS_PerfCounterNow(); - DQN_TESTER_ASSERTF(&test, b >= a, "a: %zu, b: %zu", a, b); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Consecutive ticks are ordered") { + uint64_t a = Dqn_OS_PerfCounterNow(); + uint64_t b = Dqn_OS_PerfCounterNow(); + DQN_TESTER_ASSERTF(&test, b >= a, "a: %zu, b: %zu", a, b); + } - { - Dqn_Tester_Begin(&test, "Ticks to time are a correct order of magnitude"); - uint64_t a = Dqn_OS_PerfCounterNow(); - uint64_t b = Dqn_OS_PerfCounterNow(); - - Dqn_f64 s = Dqn_OS_PerfCounterS(a, b); - Dqn_f64 ms = Dqn_OS_PerfCounterMs(a, b); - Dqn_f64 micro_s = Dqn_OS_PerfCounterMicroS(a, b); - Dqn_f64 ns = Dqn_OS_PerfCounterNs(a, b); - DQN_TESTER_ASSERTF(&test, s <= ms, "s: %f, ms: %f", s, ms); - DQN_TESTER_ASSERTF(&test, ms <= micro_s, "ms: %f, micro_s: %f", ms, micro_s); - DQN_TESTER_ASSERTF(&test, micro_s <= ns, "micro_s: %f, ns: %f", micro_s, ns); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Ticks to time are a correct order of magnitude") { + uint64_t a = Dqn_OS_PerfCounterNow(); + uint64_t b = Dqn_OS_PerfCounterNow(); + Dqn_f64 s = Dqn_OS_PerfCounterS(a, b); + Dqn_f64 ms = Dqn_OS_PerfCounterMs(a, b); + Dqn_f64 micro_s = Dqn_OS_PerfCounterMicroS(a, b); + Dqn_f64 ns = Dqn_OS_PerfCounterNs(a, b); + DQN_TESTER_ASSERTF(&test, s <= ms, "s: %f, ms: %f", s, ms); + DQN_TESTER_ASSERTF(&test, ms <= micro_s, "ms: %f, micro_s: %f", ms, micro_s); + DQN_TESTER_ASSERTF(&test, micro_s <= ns, "micro_s: %f, ns: %f", micro_s, ns); + } } - DQN_TESTER_END_GROUP(&test); return test; } Dqn_Tester Dqn_Test_OS() { Dqn_Tester test = {}; - DQN_TESTER_BEGIN_GROUP("Dqn_OS_"); - { - Dqn_Tester_Begin(&test, "Generate secure RNG bytes with nullptr"); - Dqn_b32 result = Dqn_OS_SecureRNGBytes(nullptr, 1); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_GROUP(test, "Dqn_OS_") { + DQN_TESTER_TEST("Generate secure RNG bytes with nullptr") { + Dqn_b32 result = Dqn_OS_SecureRNGBytes(nullptr, 1); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Generate secure RNG 32 bytes"); - char const ZERO[32] = {}; - char buf[32] = {}; - Dqn_b32 result = Dqn_OS_SecureRNGBytes(buf, Dqn_CArray_CountI(buf)); - DQN_TESTER_ASSERT(&test, result); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(buf, ZERO, Dqn_CArray_Count(buf)) != 0); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Generate secure RNG 32 bytes") { + char const ZERO[32] = {}; + char buf[32] = {}; + Dqn_b32 result = Dqn_OS_SecureRNGBytes(buf, Dqn_CArray_CountI(buf)); + DQN_TESTER_ASSERT(&test, result); + DQN_TESTER_ASSERT(&test, DQN_MEMCMP(buf, ZERO, Dqn_CArray_Count(buf)) != 0); + } - { - Dqn_Tester_Begin(&test, "Generate secure RNG 0 bytes"); - char buf[32] = {}; - buf[0] = 'Z'; - Dqn_b32 result = Dqn_OS_SecureRNGBytes(buf, 0); - DQN_TESTER_ASSERT(&test, result); - DQN_TESTER_ASSERT(&test, buf[0] == 'Z'); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Generate secure RNG 0 bytes") { + char buf[32] = {}; + buf[0] = 'Z'; + Dqn_b32 result = Dqn_OS_SecureRNGBytes(buf, 0); + DQN_TESTER_ASSERT(&test, result); + DQN_TESTER_ASSERT(&test, buf[0] == 'Z'); + } - { - Dqn_Tester_Begin(&test, "Query executable directory"); - Dqn_Arena arena = {}; - Dqn_String8 result = Dqn_OS_EXEDir(Dqn_Arena_Allocator(&arena)); - DQN_TESTER_ASSERT(&test, Dqn_String8_IsValid(result)); - DQN_TESTER_ASSERTF(&test, Dqn_Fs_DirExists(result), "result(%zu): %.*s", result.size, DQN_STRING_FMT(result)); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Query executable directory") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 result = Dqn_OS_EXEDir(scratch.allocator); + DQN_TESTER_ASSERT(&test, Dqn_String8_IsValid(result)); + DQN_TESTER_ASSERTF(&test, Dqn_Fs_DirExists(result), "result(%zu): %.*s", result.size, DQN_STRING_FMT(result)); + } } - DQN_TESTER_END_GROUP(&test); return test; } Dqn_Tester Dqn_Test_CString8() { Dqn_Tester test = {}; - DQN_TESTER_BEGIN_GROUP("Dqn_CString8"); + DQN_TESTER_GROUP(test, "Dqn_CString8") { + // NOTE: Dqn_CString8_ToI64 + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("To I64: Convert nullptr") { + int64_t result = Dqn_CString8_ToI64(nullptr); + DQN_TESTER_ASSERT(&test, result == 0); + } - // NOTE: Dqn_CString8_ToI64 - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "To I64: Convert nullptr"); - int64_t result = Dqn_CString8_ToI64(nullptr); - DQN_TESTER_ASSERT(&test, result == 0); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert empty string") { + int64_t result = Dqn_CString8_ToI64(""); + DQN_TESTER_ASSERT(&test, result == 0); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert empty string"); - int64_t result = Dqn_CString8_ToI64(""); - DQN_TESTER_ASSERT(&test, result == 0); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"1\"") { + int64_t result = Dqn_CString8_ToI64("1"); + DQN_TESTER_ASSERT(&test, result == 1); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"1\""); - int64_t result = Dqn_CString8_ToI64("1"); - DQN_TESTER_ASSERT(&test, result == 1); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"-0\"") { + int64_t result = Dqn_CString8_ToI64("-0"); + DQN_TESTER_ASSERT(&test, result == 0); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"-0\""); - int64_t result = Dqn_CString8_ToI64("-0"); - DQN_TESTER_ASSERT(&test, result == 0); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"-1\"") { + int64_t result = Dqn_CString8_ToI64("-1"); + DQN_TESTER_ASSERT(&test, result == -1); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"-1\""); - int64_t result = Dqn_CString8_ToI64("-1"); - DQN_TESTER_ASSERT(&test, result == -1); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"1.2\"") { + int64_t result = Dqn_CString8_ToI64("1.2"); + DQN_TESTER_ASSERT(&test, result == 1); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"1.2\""); - int64_t result = Dqn_CString8_ToI64("1.2"); - DQN_TESTER_ASSERT(&test, result == 1); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"1,234\"") { + int64_t result = Dqn_CString8_ToI64("1,234"); + DQN_TESTER_ASSERT(&test, result == 1234); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"1,234\""); - int64_t result = Dqn_CString8_ToI64("1,234"); - DQN_TESTER_ASSERT(&test, result == 1234); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"1,2\"") { + int64_t result = Dqn_CString8_ToI64("1,2"); + DQN_TESTER_ASSERT(&test, result == 12); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"1,2\""); - int64_t result = Dqn_CString8_ToI64("1,2"); - DQN_TESTER_ASSERT(&test, result == 12); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To I64: Convert \"12a3\"") { + int64_t result = Dqn_CString8_ToI64("12a3"); + DQN_TESTER_ASSERT(&test, result == 12); + } - { - Dqn_Tester_Begin(&test, "To I64: Convert \"12a3\""); - int64_t result = Dqn_CString8_ToI64("12a3"); - DQN_TESTER_ASSERT(&test, result == 12); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_CString8_ToU64 + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("To U64: Convert nullptr") { + uint64_t result = Dqn_CString8_ToU64(nullptr); + DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + } - // NOTE: Dqn_CString8_ToU64 - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "To U64: Convert nullptr"); - uint64_t result = Dqn_CString8_ToU64(nullptr); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert empty string") { + uint64_t result = Dqn_CString8_ToU64(""); + DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert empty string"); - uint64_t result = Dqn_CString8_ToU64(""); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"1\"") { + uint64_t result = Dqn_CString8_ToU64("1"); + DQN_TESTER_ASSERTF(&test, result == 1, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"1\""); - uint64_t result = Dqn_CString8_ToU64("1"); - DQN_TESTER_ASSERTF(&test, result == 1, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"-0\"") { + uint64_t result = Dqn_CString8_ToU64("-0"); + DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"-0\""); - uint64_t result = Dqn_CString8_ToU64("-0"); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"-1\"") { + uint64_t result = Dqn_CString8_ToU64("-1"); + DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"-1\""); - uint64_t result = Dqn_CString8_ToU64("-1"); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"1.2\"") { + uint64_t result = Dqn_CString8_ToU64("1.2"); + DQN_TESTER_ASSERTF(&test, result == 1, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"1.2\""); - uint64_t result = Dqn_CString8_ToU64("1.2"); - DQN_TESTER_ASSERTF(&test, result == 1, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"1,234\"") { + uint64_t result = Dqn_CString8_ToU64("1,234"); + DQN_TESTER_ASSERTF(&test, result == 1234, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"1,234\""); - uint64_t result = Dqn_CString8_ToU64("1,234"); - DQN_TESTER_ASSERTF(&test, result == 1234, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"1,2\"") { + uint64_t result = Dqn_CString8_ToU64("1,2"); + DQN_TESTER_ASSERTF(&test, result == 12, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"1,2\""); - uint64_t result = Dqn_CString8_ToU64("1,2"); - DQN_TESTER_ASSERTF(&test, result == 12, "result: %zu", result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("To U64: Convert \"12a3\"") { + uint64_t result = Dqn_CString8_ToU64("12a3"); + DQN_TESTER_ASSERTF(&test, result == 12, "result: %zu", result); + } - { - Dqn_Tester_Begin(&test, "To U64: Convert \"12a3\""); - uint64_t result = Dqn_CString8_ToU64("12a3"); - DQN_TESTER_ASSERTF(&test, result == 12, "result: %zu", result); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_CString8_Find + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("Find: String (char) is not in buffer") { + char const buf[] = "836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"; + char const find[] = "2"; + char const *result = Dqn_CString8_Find(buf, find, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(find)); + DQN_TESTER_ASSERT(&test, result == nullptr); + } - // NOTE: Dqn_CString8_Find - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "Find: String (char) is not in buffer"); - char const buf[] = "836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"; - char const find[] = "2"; - char const *result = Dqn_CString8_Find(buf, find, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(find)); - DQN_TESTER_ASSERT(&test, result == nullptr); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Find: String (char) is in buffer") { + char const buf[] = "836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"; + char const find[] = "6"; + char const *result = Dqn_CString8_Find(buf, find, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(find)); + DQN_TESTER_ASSERT(&test, result != nullptr); + DQN_TESTER_ASSERT(&test, result[0] == '6' && result[1] == 'a'); + } - { - Dqn_Tester_Begin(&test, "Find: String (char) is in buffer"); - char const buf[] = "836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"; - char const find[] = "6"; - char const *result = Dqn_CString8_Find(buf, find, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(find)); - DQN_TESTER_ASSERT(&test, result != nullptr); - DQN_TESTER_ASSERT(&test, result[0] == '6' && result[1] == 'a'); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_CString8_FileNameFromPath + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("File name from Windows path") { + Dqn_isize file_name_size = 0; + char const buf[] = "C:\\ABC\\test.exe"; + char const *result = Dqn_CString8_FileNameFromPath(buf, Dqn_CString8_ArrayCountI(buf), &file_name_size); + DQN_TESTER_ASSERTF(&test, file_name_size == 8, "size: %I64d", file_name_size); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(Dqn_String8_Init(result, file_name_size), DQN_STRING8("test.exe")), "%.*s", DQN_CAST(int)file_name_size, result); + } - // NOTE: Dqn_CString8_FileNameFromPath - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "File name from Windows path"); - Dqn_isize file_name_size = 0; - char const buf[] = "C:\\ABC\\test.exe"; - char const *result = Dqn_CString8_FileNameFromPath(buf, Dqn_CString8_ArrayCountI(buf), &file_name_size); - DQN_TESTER_ASSERTF(&test, file_name_size == 8, "size: %I64d", file_name_size); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(Dqn_String8_Init(result, file_name_size), DQN_STRING8("test.exe")), "%.*s", DQN_CAST(int)file_name_size, result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("File name from Linux path") { + Dqn_isize file_name_size = 0; + char const buf[] = "/ABC/test.exe"; + char const *result = Dqn_CString8_FileNameFromPath(buf, Dqn_CString8_ArrayCountI(buf), &file_name_size); + DQN_TESTER_ASSERTF(&test, file_name_size == 8, "size: %I64d", file_name_size); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(Dqn_String8_Init(result, file_name_size), DQN_STRING8("test.exe")), "%.*s", (int)file_name_size, result); + } - { - Dqn_Tester_Begin(&test, "File name from Linux path"); - Dqn_isize file_name_size = 0; - char const buf[] = "/ABC/test.exe"; - char const *result = Dqn_CString8_FileNameFromPath(buf, Dqn_CString8_ArrayCountI(buf), &file_name_size); - DQN_TESTER_ASSERTF(&test, file_name_size == 8, "size: %I64d", file_name_size); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(Dqn_String8_Init(result, file_name_size), DQN_STRING8("test.exe")), "%.*s", (int)file_name_size, result); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_CString8_TrimPrefix + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("Trim prefix") { + char const prefix[] = "@123"; + char const buf[] = "@123string"; + Dqn_isize trimmed_size = 0; + char const *result = Dqn_CString8_TrimPrefix(buf, prefix, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(prefix), Dqn_CString8EqCase::Sensitive, &trimmed_size); + DQN_TESTER_ASSERTF(&test, trimmed_size == 6, "size: %I64d", trimmed_size); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(Dqn_String8_Init(result, trimmed_size), DQN_STRING8("string")), "%.*s", (int)trimmed_size, result); + } - // NOTE: Dqn_CString8_TrimPrefix - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "Trim prefix"); - char const prefix[] = "@123"; - char const buf[] = "@123string"; - Dqn_isize trimmed_size = 0; - char const *result = Dqn_CString8_TrimPrefix(buf, prefix, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(prefix), Dqn_CString8EqCase::Sensitive, &trimmed_size); - DQN_TESTER_ASSERTF(&test, trimmed_size == 6, "size: %I64d", trimmed_size); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(Dqn_String8_Init(result, trimmed_size), DQN_STRING8("string")), "%.*s", (int)trimmed_size, result); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Trim prefix, nullptr trimmed size") { + char const prefix[] = "@123"; + char const buf[] = "@123string"; + char const *result = Dqn_CString8_TrimPrefix(buf, prefix, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(prefix), Dqn_CString8EqCase::Sensitive, nullptr); + DQN_TESTER_ASSERT(&test, result); + } - { - Dqn_Tester_Begin(&test, "Trim prefix, nullptr trimmed size"); - char const prefix[] = "@123"; - char const buf[] = "@123string"; - char const *result = Dqn_CString8_TrimPrefix(buf, prefix, Dqn_CString8_ArrayCountI(buf), Dqn_CString8_ArrayCountI(prefix), Dqn_CString8EqCase::Sensitive, nullptr); - DQN_TESTER_ASSERT(&test, result); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_CString8_IsAllDigits + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("Is all digits fails on non-digit string") { + char const buf[] = "@123string"; + Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, Dqn_CString8_ArrayCountI(buf)); + DQN_TESTER_ASSERT(&test, result == false); + } - // NOTE: Dqn_CString8_IsAllDigits - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "Is all digits fails on non-digit string"); - char const buf[] = "@123string"; - Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, Dqn_CString8_ArrayCountI(buf)); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on nullptr") { + Dqn_b32 result = Dqn_CString8_IsAllDigits(nullptr, 0); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on nullptr"); - Dqn_b32 result = Dqn_CString8_IsAllDigits(nullptr, 0); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on nullptr w/ size") { + Dqn_b32 result = Dqn_CString8_IsAllDigits(nullptr, 1); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on nullptr w/ size"); - Dqn_b32 result = Dqn_CString8_IsAllDigits(nullptr, 1); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on 0 size w/ string") { + char const buf[] = "@123string"; + Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, 0); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on 0 size w/ string"); - char const buf[] = "@123string"; - Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, 0); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits success") { + char const buf[] = "23"; + Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, Dqn_CString8_ArrayCountI(buf)); + DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == true); + } - { - Dqn_Tester_Begin(&test, "Is all digits success"); - char const buf[] = "23"; - Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, Dqn_CString8_ArrayCountI(buf)); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == true); - Dqn_Tester_End(&test); + DQN_TESTER_TEST("Is all digits fails on whitespace") { + char const buf[] = "23 "; + Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, Dqn_CString8_ArrayCountI(buf)); + DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == false); + } } - - { - Dqn_Tester_Begin(&test, "Is all digits fails on whitespace"); - char const buf[] = "23 "; - Dqn_b32 result = Dqn_CString8_IsAllDigits(buf, Dqn_CString8_ArrayCountI(buf)); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == false); - Dqn_Tester_End(&test); - } - DQN_TESTER_END_GROUP(&test); return test; } Dqn_Tester Dqn_Test_String8() { Dqn_Tester test = {}; - DQN_TESTER_BEGIN_GROUP("Dqn_String8"); - { - Dqn_Tester_Begin(&test, "Initialise with string literal w/ macro"); - Dqn_String8 string = DQN_STRING8("AB"); - DQN_TESTER_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); - DQN_TESTER_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); - DQN_TESTER_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); - Dqn_Tester_End(&test); - } + DQN_TESTER_GROUP(test, "Dqn_String8") { + DQN_TESTER_TEST("Initialise with string literal w/ macro") { + Dqn_String8 string = DQN_STRING8("AB"); + DQN_TESTER_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); + DQN_TESTER_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); + DQN_TESTER_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); + } - { - Dqn_Tester_Begin(&test, "Initialise with format string"); - Dqn_Arena arena = {}; - Dqn_String8 string = Dqn_String8_InitF(Dqn_Arena_Allocator(&arena), "%s", "AB"); - DQN_TESTER_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); - DQN_TESTER_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); - DQN_TESTER_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); - DQN_TESTER_ASSERTF(&test, string.data[2] == 0, "string[2]: %c", string.data[2]); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Initialise with format string") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 string = Dqn_String8_InitF(scratch.allocator, "%s", "AB"); + DQN_TESTER_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); + DQN_TESTER_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); + DQN_TESTER_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); + DQN_TESTER_ASSERTF(&test, string.data[2] == 0, "string[2]: %c", string.data[2]); + } - { - Dqn_Tester_Begin(&test, "Copy string"); - Dqn_Arena arena = {}; - Dqn_String8 string = DQN_STRING8("AB"); - Dqn_String8 copy = Dqn_String8_Copy(Dqn_Arena_Allocator(&arena), string); - DQN_TESTER_ASSERTF(&test, copy.size == 2, "size: %I64d", copy.size); - DQN_TESTER_ASSERTF(&test, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); - DQN_TESTER_ASSERTF(&test, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); - DQN_TESTER_ASSERTF(&test, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Copy string") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 string = DQN_STRING8("AB"); + Dqn_String8 copy = Dqn_String8_Copy(scratch.allocator, string); + DQN_TESTER_ASSERTF(&test, copy.size == 2, "size: %I64d", copy.size); + DQN_TESTER_ASSERTF(&test, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); + DQN_TESTER_ASSERTF(&test, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); + DQN_TESTER_ASSERTF(&test, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); + } - { - Dqn_Tester_Begin(&test, "Trim whitespace around string"); - Dqn_String8 string = Dqn_String8_TrimWhitespaceAround(DQN_STRING8(" AB ")); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(string, DQN_STRING8("AB")), "[string=%.*s]", DQN_STRING_FMT(string)); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Trim whitespace around string") { + Dqn_String8 string = Dqn_String8_TrimWhitespaceAround(DQN_STRING8(" AB ")); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(string, DQN_STRING8("AB")), "[string=%.*s]", DQN_STRING_FMT(string)); + } - { - Dqn_Tester_Begin(&test, "Allocate string from arena"); - Dqn_Arena arena = {}; - Dqn_String8 string = Dqn_String8_Allocate(Dqn_Arena_Allocator(&arena), 2, Dqn_ZeroMem_No); - DQN_TESTER_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Allocate string from arena") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 string = Dqn_String8_Allocate(scratch.allocator, 2, Dqn_ZeroMem_No); + DQN_TESTER_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); + } - // NOTE: Dqn_CString8_Trim[Prefix/Suffix] - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "Trim prefix with matching prefix"); - Dqn_String8 input = DQN_STRING8("nft/abc"); - Dqn_String8 result = Dqn_String8_TrimPrefix(input, DQN_STRING8("nft/")); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, DQN_STRING8("abc")), "%.*s", DQN_STRING_FMT(result)); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_CString8_Trim[Prefix/Suffix] + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("Trim prefix with matching prefix") { + Dqn_String8 input = DQN_STRING8("nft/abc"); + Dqn_String8 result = Dqn_String8_TrimPrefix(input, DQN_STRING8("nft/")); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, DQN_STRING8("abc")), "%.*s", DQN_STRING_FMT(result)); + } - { - Dqn_Tester_Begin(&test, "Trim prefix with non matching prefix"); - Dqn_String8 input = DQN_STRING8("nft/abc"); - Dqn_String8 result = Dqn_String8_TrimPrefix(input, DQN_STRING8(" ft/")); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, input), "%.*s", DQN_STRING_FMT(result)); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Trim prefix with non matching prefix") { + Dqn_String8 input = DQN_STRING8("nft/abc"); + Dqn_String8 result = Dqn_String8_TrimPrefix(input, DQN_STRING8(" ft/")); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, input), "%.*s", DQN_STRING_FMT(result)); + } - { - Dqn_Tester_Begin(&test, "Trim suffix with matching suffix"); - Dqn_String8 input = DQN_STRING8("nft/abc"); - Dqn_String8 result = Dqn_String8_TrimSuffix(input, DQN_STRING8("abc")); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, DQN_STRING8("nft/")), "%.*s", DQN_STRING_FMT(result)); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Trim suffix with matching suffix") { + Dqn_String8 input = DQN_STRING8("nft/abc"); + Dqn_String8 result = Dqn_String8_TrimSuffix(input, DQN_STRING8("abc")); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, DQN_STRING8("nft/")), "%.*s", DQN_STRING_FMT(result)); + } - { - Dqn_Tester_Begin(&test, "Trim suffix with non matching suffix"); - Dqn_String8 input = DQN_STRING8("nft/abc"); - Dqn_String8 result = Dqn_String8_TrimSuffix(input, DQN_STRING8("ab")); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, input), "%.*s", DQN_STRING_FMT(result)); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Trim suffix with non matching suffix") { + Dqn_String8 input = DQN_STRING8("nft/abc"); + Dqn_String8 result = Dqn_String8_TrimSuffix(input, DQN_STRING8("ab")); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(result, input), "%.*s", DQN_STRING_FMT(result)); + } - // NOTE: Dqn_String8_IsAllDigits - // --------------------------------------------------------------------------------------------- - { - Dqn_Tester_Begin(&test, "Is all digits fails on non-digit string"); - Dqn_b32 result = Dqn_String8_IsAllDigits(DQN_STRING8("@123string")); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + // NOTE: Dqn_String8_IsAllDigits + // --------------------------------------------------------------------------------------------- + DQN_TESTER_TEST("Is all digits fails on non-digit string") { + Dqn_b32 result = Dqn_String8_IsAllDigits(DQN_STRING8("@123string")); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on nullptr"); - Dqn_b32 result = Dqn_String8_IsAllDigits(Dqn_String8_Init(nullptr, 0)); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on nullptr") { + Dqn_b32 result = Dqn_String8_IsAllDigits(Dqn_String8_Init(nullptr, 0)); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on nullptr w/ size"); - Dqn_b32 result = Dqn_String8_IsAllDigits(Dqn_String8_Init(nullptr, 1)); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on nullptr w/ size") { + Dqn_b32 result = Dqn_String8_IsAllDigits(Dqn_String8_Init(nullptr, 1)); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on string w/ 0 size"); - char const buf[] = "@123string"; - Dqn_b32 result = Dqn_String8_IsAllDigits(Dqn_String8_Init(buf, 0)); - DQN_TESTER_ASSERT(&test, result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on string w/ 0 size") { + char const buf[] = "@123string"; + Dqn_b32 result = Dqn_String8_IsAllDigits(Dqn_String8_Init(buf, 0)); + DQN_TESTER_ASSERT(&test, result == false); + } - { - Dqn_Tester_Begin(&test, "Is all digits success"); - Dqn_b32 result = Dqn_String8_IsAllDigits(DQN_STRING8("23")); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == true); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits success") { + Dqn_b32 result = Dqn_String8_IsAllDigits(DQN_STRING8("23")); + DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == true); + } - { - Dqn_Tester_Begin(&test, "Is all digits fails on whitespace"); - Dqn_b32 result = Dqn_String8_IsAllDigits(DQN_STRING8("23 ")); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == false); - Dqn_Tester_End(&test); - } + DQN_TESTER_TEST("Is all digits fails on whitespace") { + Dqn_b32 result = Dqn_String8_IsAllDigits(DQN_STRING8("23 ")); + DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == false); + } - // NOTE: Dqn_String8_BinarySplit - // --------------------------------------------------------------------------------------------- - { - char const *TEST_FMT = "Dqn_String8_BinarySplit: with '%.*s' with '%c'"; + // NOTE: Dqn_String8_BinarySplit + // --------------------------------------------------------------------------------------------- { + char const *TEST_FMT = "Dqn_String8_BinarySplit \"%s\" with 'c'"; + + char delimiter = '/'; Dqn_String8 input = DQN_STRING8("abcdef"); - char delimiter = '/'; - Dqn_Tester_Begin(&test, TEST_FMT, DQN_STRING_FMT(input), delimiter); + DQN_TESTER_TEST(TEST_FMT, input.data, delimiter) { + Dqn_String8 rhs = {}; + Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); - Dqn_String8 rhs = {}; - Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abcdef")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); + } - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abcdef")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); - Dqn_Tester_End(&test); - } + input = DQN_STRING8("abc/def"); + DQN_TESTER_TEST(TEST_FMT, input.data, delimiter) { + Dqn_String8 rhs = {}; + Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abc")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("def")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); + } - { - Dqn_String8 input = DQN_STRING8("abc/def"); - char delimiter = '/'; - Dqn_Tester_Begin(&test, TEST_FMT, DQN_STRING_FMT(input), delimiter); - - Dqn_String8 rhs = {}; - Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); - - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abc")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("def")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); - Dqn_Tester_End(&test); - } - - { - Dqn_String8 input = DQN_STRING8("/abcdef"); - char delimiter = '/'; - Dqn_Tester_Begin(&test, TEST_FMT, DQN_STRING_FMT(input), delimiter); - - Dqn_String8 rhs = {}; - Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); - - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("abcdef")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); - Dqn_Tester_End(&test); + input = DQN_STRING8("/abcdef"); + DQN_TESTER_TEST(TEST_FMT, input.data, delimiter) { + Dqn_String8 rhs = {}; + Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); + DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("abcdef")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); + } } } - - DQN_TESTER_END_GROUP(&test); return test; } Dqn_Tester Dqn_Test_TicketMutex() { Dqn_Tester test = {}; - DQN_TESTER_BEGIN_GROUP("Dqn_TicketMutex"); - { - // TODO: We don't have a meaningful test but since atomics are - // implemented with a macro this ensures that we test that they are - // written correctly. - Dqn_Tester_Begin(&test, "Ticket mutex start and stop"); - Dqn_TicketMutex mutex = {}; - Dqn_TicketMutex_Begin(&mutex); - Dqn_TicketMutex_End(&mutex); - DQN_TESTER_ASSERT(&test, mutex.ticket == mutex.serving); - Dqn_Tester_End(&test); + DQN_TESTER_GROUP(test, "Dqn_TicketMutex") { + DQN_TESTER_TEST("Ticket mutex start and stop") { + // TODO: We don't have a meaningful test but since atomics are + // implemented with a macro this ensures that we test that they are + // written correctly. + Dqn_TicketMutex mutex = {}; + Dqn_TicketMutex_Begin(&mutex); + Dqn_TicketMutex_End(&mutex); + DQN_TESTER_ASSERT(&test, mutex.ticket == mutex.serving); + } + + DQN_TESTER_TEST("Ticket mutex start and stop w/ advanced API") { + Dqn_TicketMutex mutex = {}; + unsigned int ticket_a = Dqn_TicketMutex_MakeTicket(&mutex); + unsigned int ticket_b = Dqn_TicketMutex_MakeTicket(&mutex); + DQN_TESTER_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_b) == false); + DQN_TESTER_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_a) == true); + + Dqn_TicketMutex_BeginTicket(&mutex, ticket_a); + Dqn_TicketMutex_End(&mutex); + Dqn_TicketMutex_BeginTicket(&mutex, ticket_b); + Dqn_TicketMutex_End(&mutex); + + DQN_TESTER_ASSERT(&test, mutex.ticket == mutex.serving); + DQN_TESTER_ASSERT(&test, mutex.ticket == ticket_b + 1); + } } - - { - Dqn_Tester_Begin(&test, "Ticket mutex start and stop w/ advanced API"); - Dqn_TicketMutex mutex = {}; - unsigned int ticket_a = Dqn_TicketMutex_MakeTicket(&mutex); - unsigned int ticket_b = Dqn_TicketMutex_MakeTicket(&mutex); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_b) == false); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_a) == true); - - Dqn_TicketMutex_BeginTicket(&mutex, ticket_a); - Dqn_TicketMutex_End(&mutex); - Dqn_TicketMutex_BeginTicket(&mutex, ticket_b); - Dqn_TicketMutex_End(&mutex); - - DQN_TESTER_ASSERT(&test, mutex.ticket == mutex.serving); - DQN_TESTER_ASSERT(&test, mutex.ticket == ticket_b + 1); - Dqn_Tester_End(&test); - } - DQN_TESTER_END_GROUP(&test); return test; } Dqn_Tester Dqn_Test_Win() { Dqn_Tester test = {}; -#if defined(DQN_OS_WIN32) - DQN_TESTER_BEGIN_GROUP("Dqn_Win"); - { - Dqn_Tester_Begin(&test, "String8 to String16 size required"); - int result = Dqn_Win_String8ToCString16(DQN_STRING8("a"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 2, "Size returned: %d. This size should include the null-terminator", result); - Dqn_Tester_End(&test); + DQN_TESTER_GROUP(test, "Dqn_Win") { + DQN_TESTER_TEST("String8 to String16 size required") { + int result = Dqn_Win_String8ToCString16(DQN_STRING8("a"), nullptr, 0); + DQN_TESTER_ASSERTF(&test, result == 2, "Size returned: %d. This size should include the null-terminator", result); + } + + DQN_TESTER_TEST("String16 to String8 size required") { + int result = Dqn_Win_String16ToCString8(DQN_STRING16(L"a"), nullptr, 0); + DQN_TESTER_ASSERTF(&test, result == 2, "Size returned: %d. This size should include the null-terminator", result); + } + + DQN_TESTER_TEST("String8 to String16 size required") { + int result = Dqn_Win_String8ToCString16(DQN_STRING8("String"), nullptr, 0); + DQN_TESTER_ASSERTF(&test, result == 7, "Size returned: %d. This size should include the null-terminator", result); + } + + DQN_TESTER_TEST("String16 to String8 size required") { + int result = Dqn_Win_String16ToCString8(DQN_STRING16(L"String"), nullptr, 0); + DQN_TESTER_ASSERTF(&test, result == 7, "Size returned: %d. This size should include the null-terminator", result); + } + + DQN_TESTER_TEST("String8 to String16") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 const INPUT = DQN_STRING8("String"); + int size_required = Dqn_Win_String8ToCString16(INPUT, nullptr, 0); + wchar_t *string = Dqn_Arena_NewArray(scratch.arena, wchar_t, size_required, Dqn_ZeroMem_No); + + // Fill the string with error sentinels, which ensures the string is zero terminated + DQN_MEMSET(string, 'Z', size_required); + + int size_returned = Dqn_Win_String8ToCString16(INPUT, string, size_required); + wchar_t const EXPECTED[] = {L'S', L't', L'r', L'i', L'n', L'g', 0}; + + DQN_TESTER_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); + DQN_TESTER_ASSERTF(&test, size_returned == Dqn_CArray_Count(EXPECTED), "string_size: %d, expected: %zu", size_returned, Dqn_CArray_Count(EXPECTED)); + DQN_TESTER_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); + } + + DQN_TESTER_TEST("String16 to String8: No null-terminate") { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String16 INPUT = DQN_STRING16(L"String"); + int size_required = Dqn_Win_String16ToCString8(INPUT, nullptr, 0); + char *string = Dqn_Arena_NewArray(scratch.arena, char, size_required, Dqn_ZeroMem_No); + + // Fill the string with error sentinels, which ensures the string is zero terminated + DQN_MEMSET(string, 'Z', size_required); + + int size_returned = Dqn_Win_String16ToCString8(INPUT, string, size_required); + char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; + + DQN_TESTER_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); + DQN_TESTER_ASSERTF(&test, size_returned == Dqn_CArray_Count(EXPECTED), "string_size: %d, expected: %zu", size_returned, Dqn_CArray_Count(EXPECTED)); + DQN_TESTER_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); + } } - - { - Dqn_Tester_Begin(&test, "String16 to String8 size required"); - int result = Dqn_Win_String16ToCString8(DQN_STRING16(L"a"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 2, "Size returned: %d. This size should include the null-terminator", result); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "String8 to String16 size required"); - int result = Dqn_Win_String8ToCString16(DQN_STRING8("String"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 7, "Size returned: %d. This size should include the null-terminator", result); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "String16 to String8 size required"); - int result = Dqn_Win_String16ToCString8(DQN_STRING16(L"String"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 7, "Size returned: %d. This size should include the null-terminator", result); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "String8 to String16"); - Dqn_Arena arena = {}; - Dqn_String8 const INPUT = DQN_STRING8("String"); - int size_required = Dqn_Win_String8ToCString16(INPUT, nullptr, 0); - wchar_t *string = Dqn_Arena_NewArray(&arena, wchar_t, size_required, Dqn_ZeroMem_No); - - // Fill the string with error sentinels, which ensures the string is zero terminated - DQN_MEMSET(string, 'Z', size_required); - - int size_returned = Dqn_Win_String8ToCString16(INPUT, string, size_required); - wchar_t const EXPECTED[] = {L'S', L't', L'r', L'i', L'n', L'g', 0}; - - DQN_TESTER_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); - DQN_TESTER_ASSERTF(&test, size_returned == Dqn_CArray_Count(EXPECTED), "string_size: %d, expected: %zu", size_returned, Dqn_CArray_Count(EXPECTED)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - - { - Dqn_Tester_Begin(&test, "String16 to String8: No null-terminate"); - Dqn_Arena arena = {}; - Dqn_String16 INPUT = DQN_STRING16(L"String"); - int size_required = Dqn_Win_String16ToCString8(INPUT, nullptr, 0); - char *string = Dqn_Arena_NewArray(&arena, char, size_required, Dqn_ZeroMem_No); - - // Fill the string with error sentinels, which ensures the string is zero terminated - DQN_MEMSET(string, 'Z', size_required); - - int size_returned = Dqn_Win_String16ToCString8(INPUT, string, size_required); - char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; - - DQN_TESTER_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); - DQN_TESTER_ASSERTF(&test, size_returned == Dqn_CArray_Count(EXPECTED), "string_size: %d, expected: %zu", size_returned, Dqn_CArray_Count(EXPECTED)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); - Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); - Dqn_Tester_End(&test); - } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_OS_WIN32 - return test; } -#define DQN_TESTS_HASH_X_MACRO \ - DQN_TESTS_HASH_X_ENTRY(SHA3_224, "SHA3-224") \ - DQN_TESTS_HASH_X_ENTRY(SHA3_256, "SHA3-256") \ - DQN_TESTS_HASH_X_ENTRY(SHA3_384, "SHA3-384") \ - DQN_TESTS_HASH_X_ENTRY(SHA3_512, "SHA3-512") \ - DQN_TESTS_HASH_X_ENTRY(Keccak_224, "Keccak-224") \ - DQN_TESTS_HASH_X_ENTRY(Keccak_256, "Keccak-256") \ - DQN_TESTS_HASH_X_ENTRY(Keccak_384, "Keccak-384") \ - DQN_TESTS_HASH_X_ENTRY(Keccak_512, "Keccak-512") \ - DQN_TESTS_HASH_X_ENTRY(Count, "Keccak-512") +#define DQN_TESTER_HASH_X_MACRO \ + DQN_TESTER_HASH_X_ENTRY(SHA3_224, "SHA3-224") \ + DQN_TESTER_HASH_X_ENTRY(SHA3_256, "SHA3-256") \ + DQN_TESTER_HASH_X_ENTRY(SHA3_384, "SHA3-384") \ + DQN_TESTER_HASH_X_ENTRY(SHA3_512, "SHA3-512") \ + DQN_TESTER_HASH_X_ENTRY(Keccak_224, "Keccak-224") \ + DQN_TESTER_HASH_X_ENTRY(Keccak_256, "Keccak-256") \ + DQN_TESTER_HASH_X_ENTRY(Keccak_384, "Keccak-384") \ + DQN_TESTER_HASH_X_ENTRY(Keccak_512, "Keccak-512") \ + DQN_TESTER_HASH_X_ENTRY(Count, "Keccak-512") enum Dqn_Tests__HashType { -#define DQN_TESTS_HASH_X_ENTRY(enum_val, string) Hash_##enum_val, - DQN_TESTS_HASH_X_MACRO -#undef DQN_TESTS_HASH_X_ENTRY +#define DQN_TESTER_HASH_X_ENTRY(enum_val, string) Hash_##enum_val, + DQN_TESTER_HASH_X_MACRO +#undef DQN_TESTER_HASH_X_ENTRY }; -Dqn_String8 const DQN_TESTS__HASH_STRING[] = +Dqn_String8 const DQN_TESTER_HASH_STRING_[] = { -#define DQN_TESTS_HASH_X_ENTRY(enum_val, string) DQN_STRING8(string), - DQN_TESTS_HASH_X_MACRO -#undef DQN_TESTS_HASH_X_ENTRY +#define DQN_TESTER_HASH_X_ENTRY(enum_val, string) DQN_STRING8(string), + DQN_TESTER_HASH_X_MACRO +#undef DQN_TESTER_HASH_X_ENTRY }; -void Dqn_Test__KeccakDispatch(Dqn_Tester *test, int hash_type, Dqn_String8 input) +void Dqn_Test_KeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) { -#if defined(DQN_KECCAK_H) Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); Dqn_String8 input_hex = Dqn_Hex_BytesToString8Arena(scratch.arena, input.data, input.size); @@ -1587,13 +1297,11 @@ void Dqn_Test__KeccakDispatch(Dqn_Tester *test, int hash_type, Dqn_String8 input break; } -#endif // DQN_KECCAK_H } Dqn_Tester Dqn_Test_Keccak() { Dqn_Tester test = {}; -#if defined(DQN_KECCAK_H) Dqn_String8 const INPUTS[] = { DQN_STRING8("abc"), DQN_STRING8(""), @@ -1602,35 +1310,32 @@ Dqn_Tester Dqn_Test_Keccak() "pqrstnopqrstu"), }; - DQN_TESTER_BEGIN_GROUP("Dqn_Keccak"); - for (int hash_type = 0; hash_type < Hash_Count; hash_type++) + DQN_TESTER_GROUP(test, "Dqn_Keccak") { - pcg32_random_t rng = {}; - pcg32_srandom_r(&rng, 0xd48e'be21'2af8'733d, 0x3f89'3bd2'd6b0'4eef); + for (int hash_type = 0; hash_type < Hash_Count; hash_type++) { + pcg32_random_t rng = {}; + pcg32_srandom_r(&rng, 0xd48e'be21'2af8'733d, 0x3f89'3bd2'd6b0'4eef); - for (Dqn_String8 input : INPUTS) - { - Dqn_Tester_Begin(&test, "%.*s - Input: %.*s", DQN_STRING_FMT(DQN_TESTS__HASH_STRING[hash_type]), DQN_CAST(int)DQN_MIN(input.size, 54), input.data); - Dqn_Test__KeccakDispatch(&test, hash_type, input); + for (Dqn_String8 input : INPUTS) { + Dqn_Tester_Begin(&test, "%.*s - Input: %.*s", DQN_STRING_FMT(DQN_TESTER_HASH_STRING_[hash_type]), DQN_CAST(int)DQN_MIN(input.size, 54), input.data); + Dqn_Test_KeccakDispatch_(&test, hash_type, input); + Dqn_Tester_End(&test); + } + + Dqn_Tester_Begin(&test, "%.*s - Deterministic random inputs", DQN_STRING_FMT(DQN_TESTER_HASH_STRING_[hash_type])); + for (int index = 0; index < 128; index++) { + char src[4096] = {}; + uint32_t src_size = pcg32_boundedrand_r(&rng, sizeof(src)); + + for (int src_index = 0; src_index < src_size; src_index++) + src[src_index] = pcg32_boundedrand_r(&rng, 255); + + Dqn_String8 input = Dqn_String8_Init(src, src_size); + Dqn_Test_KeccakDispatch_(&test, hash_type, input); + } Dqn_Tester_End(&test); } - - Dqn_Tester_Begin(&test, "%.*s - Deterministic random inputs", DQN_STRING_FMT(DQN_TESTS__HASH_STRING[hash_type])); - for (int index = 0; index < 128; index++) - { - char src[4096] = {}; - uint32_t src_size = pcg32_boundedrand_r(&rng, sizeof(src)); - - for (int src_index = 0; src_index < src_size; src_index++) - src[src_index] = pcg32_boundedrand_r(&rng, 255); - - Dqn_String8 input = Dqn_String8_Init(src, src_size); - Dqn_Test__KeccakDispatch(&test, hash_type, input); - } - Dqn_Tester_End(&test); } - DQN_TESTER_END_GROUP(&test); -#endif // DQN_KECCAK_H return test; }