diff --git a/dqn.h b/dqn.h index 91ea78f..23a18aa 100644 --- a/dqn.h +++ b/dqn.h @@ -57,6 +57,10 @@ // #define DQN_NO_ASSERT // Turn all assertion macros to no-ops // +// #define DQN_NO_CHECK_BREAK +// Disable debug break when a check macro's expression fails. Instead only +// the error will be logged. +// // #define DQN_NO_WIN32_MINIMAL_HEADER // Define this to stop this library from defining a minimal subset of Win32 // prototypes and definitions in this file. Useful for stopping redefinition @@ -283,6 +287,30 @@ } #endif +#define DQN_CHECK(expr) DQN_CHECKF(expr, "") +#if defined(DQN_NO_CHECK_BREAK) + #define DQN_CHECKF(expr, fmt, ...) \ + ((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, ## __VA_ARGS__), false)) +#else + #define DQN_CHECKF(expr, fmt, ...) \ + ((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, ## __VA_ARGS__), DQN_DEBUG_BREAK, false)) +#endif + +#if 0 +DQN_API bool DQN_CHECKF_(bool assertion_expr, Dqn_CallSite call_site, char const *fmt, ...) +{ + bool result = assertion_expr; + if (!result) { + va_list args; + va_start(args, fmt); + Dqn_Log_TypeFVCallSite(Dqn_LogType_Error, call_site, fmt, args); + va_end(args); + DQN_DEBUG_BREAK; + } + return result; +} +#endif + #if defined(__cplusplus) #define DQN_ZERO_INIT {} #else @@ -1310,10 +1338,11 @@ typedef void Dqn_LogProc(Dqn_String8 type, int log_type, void *user_data, Dqn_Ca #define Dqn_Log_FV(type, fmt, args) Dqn_Log_FVCallSite(type, DQN_CALL_SITE, fmt, args) #define Dqn_Log_F(type, fmt, ...) Dqn_Log_FCallSite(type, DQN_CALL_SITE, fmt, ## __VA_ARGS__) -DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, va_list va); -DQN_API void Dqn_Log_TypeFCallSite (Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, ...); -DQN_API void Dqn_Log_FVCallSite (Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, va_list va); -DQN_API void Dqn_Log_FCallSite (Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, ...); +DQN_API Dqn_String8 Dqn_Log_MakeString (Dqn_Allocator allocator, bool colour, Dqn_String8 type, int log_type, Dqn_CallSite call_site, char const *fmt, va_list args); +DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, va_list va); +DQN_API void Dqn_Log_TypeFCallSite (Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, ...); +DQN_API void Dqn_Log_FVCallSite (Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, va_list va); +DQN_API void Dqn_Log_FCallSite (Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, ...); // ================================================================================================= // [$VMEM] Dqn_VMem | | Virtual memory allocation @@ -1488,7 +1517,7 @@ struct Dqn_ArenaStatString struct Dqn_Arena { bool use_after_free_guard; - + uint32_t temp_memory_count; Dqn_String8 label; ///< Optional label to describe the arena Dqn_ArenaBlock *head; ///< Active block the arena is allocating from Dqn_ArenaBlock *curr; ///< Active block the arena is allocating from @@ -2424,26 +2453,17 @@ DQN_API bool Dqn_Bit_IsNotSet(uint32_t bits, uint32_t bits_to_check); // ================================================================================================= // [$SAFE] Dqn_Safe | | Safe arithmetic, casts, asserts // ================================================================================================= -#if defined(NDEBUG) - #define Dqn_Safe_AssertF(expr, fmt, ...) - #define Dqn_Safe_Assert(expr, fmt, ...) -#else - #define Dqn_Safe_AssertF(expr, fmt, ...) \ - Dqn_Safe_AssertF_(expr, DQN_CALL_SITE, "Safe assert triggered " #expr ": " fmt, ## __VA_ARGS__) - #define Dqn_Safe_Assert(expr) Dqn_Safe_AssertF(expr, "") -#endif - /// Assert the expression given in debug, whilst in release- assertion is /// removed and the expression is evaluated and returned. /// /// This function provides dual logic which allows handling of the condition /// gracefully in release mode, but asserting in debug mode. This is an internal -/// function, prefer the @see Dqn_Safe_Assert macros. +/// function, prefer the @see DQN_CHECK macros. /// /// @param assertion_expr[in] Expressin to assert on /// @param fmt[in] Format string for providing a message on assertion /// @return True if the expression evaluated to true, false otherwise. -DQN_API bool Dqn_Safe_AssertF_(bool assertion_expr, Dqn_CallSite call_site, char const *fmt, ...); +DQN_API bool DQN_CHECKF_(bool assertion_expr, Dqn_CallSite call_site, char const *fmt, ...); // NOTE: Dqn_Safe Arithmetic // ----------------------------------------------------------------------------- @@ -3606,7 +3626,7 @@ DQN_API template T *Dqn_VArray_Make(Dqn_VArray *array, Dqn_usize if (!Dqn_VArray_IsValid(array)) return nullptr; - if (!Dqn_Safe_AssertF((array->size + count) < array->max, "Array is out of virtual memory")) + if (!DQN_CHECKF((array->size + count) < array->max, "Array is out of virtual memory")) return nullptr; // TODO: Use placement new? Why doesn't this work? @@ -3696,7 +3716,7 @@ template Dqn_DSMap Dqn_DSMap_Init(uint32_t size) { Dqn_DSMap result = {}; - if (Dqn_Safe_AssertF((size & (size - 1)) == 0, "Power-of-two size required")) { + if (DQN_CHECKF((size & (size - 1)) == 0, "Power-of-two size required")) { result.hash_to_slot = Dqn_Allocator_NewArray(result.allocator, uint32_t, size, Dqn_ZeroMem_Yes); if (result.hash_to_slot) { result.slots = Dqn_Allocator_NewArray(result.allocator, Dqn_DSMapSlot, size, Dqn_ZeroMem_Yes); @@ -4200,7 +4220,7 @@ DQN_API template T *Dqn_FArray_Make(Dqn_FArray * if (!Dqn_FArray_IsValid(array)) return nullptr; - if (!Dqn_Safe_AssertF((array->size + count) < DQN_ARRAY_UCOUNT(array->data), "Array is out of memory")) + if (!DQN_CHECKF((array->size + count) < DQN_ARRAY_UCOUNT(array->data), "Array is out of memory")) return nullptr; // TODO: Use placement new? Why doesn't this work? @@ -4892,6 +4912,78 @@ DQN_API void Dqn_Allocator_Dealloc_(DQN_LEAK_TRACE_FUNCTION Dqn_Allocator alloca // ================================================================================================= // [$LLOG] Dqn_Log | | Library logging // ================================================================================================= +DQN_API Dqn_String8 Dqn_Log_MakeString(Dqn_Allocator allocator, + bool colour, + Dqn_String8 type, + int log_type, + Dqn_CallSite call_site, + char const *fmt, + va_list args) +{ + Dqn_usize header_size_no_ansi_codes = 0; + Dqn_String8 header = {}; + { + DQN_LOCAL_PERSIST Dqn_usize max_type_length = 0; + max_type_length = DQN_MAX(max_type_length, type.size); + int type_padding = DQN_CAST(int)(max_type_length - type.size); + + Dqn_String8 colour_esc = {}; + Dqn_String8 bold_esc = {}; + Dqn_String8 reset_esc = {}; + if (colour) { + bold_esc = Dqn_Print_ESCBoldString; + reset_esc = Dqn_Print_ESCResetString; + switch (log_type) { + case Dqn_LogType_Debug: break; + case Dqn_LogType_Info: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Info); break; + case Dqn_LogType_Warning: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Warning); break; + case Dqn_LogType_Error: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Error); break; + } + } + + Dqn_String8 file_name = Dqn_String8_FileNameFromPath(call_site.file); + Dqn_DateHMSTimeString const time = Dqn_Date_HMSLocalTimeStringNow(); + header = Dqn_String8_InitF(allocator, + "%.*s " // date + "%.*s " // hms + "%.*s" // colour + "%.*s" // bold + "%.*s" // type + "%*s" // type padding + "%.*s" // reset + " %.*s" // file name + ":%05u ", // line number + time.date_size - 2, time.date + 2, + time.hms_size, time.hms, + colour_esc.size, colour_esc.data, + bold_esc.size, bold_esc.data, + type.size, type.data, + type_padding, "", + reset_esc.size, reset_esc.data, + file_name.size, file_name.data, + call_site.line); + header_size_no_ansi_codes = header.size - colour_esc.size - Dqn_Print_ESCResetString.size; + } + + // NOTE: Header padding + // ========================================================================= + Dqn_usize header_padding = 0; + { + DQN_LOCAL_PERSIST Dqn_usize max_header_length = 0; + max_header_length = DQN_MAX(max_header_length, header_size_no_ansi_codes); + header_padding = max_header_length - header_size_no_ansi_codes; + } + + // NOTE: Construct final log + // ========================================================================= + Dqn_String8 user_msg = Dqn_String8_InitFV(allocator, fmt, args); + Dqn_String8 result = Dqn_String8_Allocate(allocator, header.size + header_padding + user_msg.size, Dqn_ZeroMem_No); + DQN_MEMCPY(result.data, header.data, header.size); + DQN_MEMSET(result.data + header.size, ' ', header_padding); + DQN_MEMCPY(result.data + header.size + header_padding, user_msg.data, user_msg.size); + return result; +} + DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list args) { (void)log_type; @@ -4910,69 +5002,14 @@ DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_String8 type, int log_type, void *use // NOTE: Generate the log header // ========================================================================= - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_usize header_size_no_ansi_codes = 0; - Dqn_String8 header = {}; - { - DQN_LOCAL_PERSIST Dqn_usize max_type_length = 0; - max_type_length = DQN_MAX(max_type_length, type.size); - int type_padding = DQN_CAST(int)(max_type_length - type.size); - - Dqn_String8 colour = {}; - Dqn_String8 bold = {}; - Dqn_String8 reset = {}; - if (!dqn_library.log_no_colour) { - bold = Dqn_Print_ESCBoldString; - reset = Dqn_Print_ESCResetString; - switch (log_type) { - case Dqn_LogType_Debug: break; - case Dqn_LogType_Info: colour = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Info); break; - case Dqn_LogType_Warning: colour = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Warning); break; - case Dqn_LogType_Error: colour = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Error); break; - } - } - - Dqn_String8 file_name = Dqn_String8_FileNameFromPath(call_site.file); - Dqn_DateHMSTimeString const time = Dqn_Date_HMSLocalTimeStringNow(); - header = Dqn_String8_InitF(scratch.allocator, - "%.*s " // date - "%.*s " // hms - "%.*s" // colour - "%.*s" // bold - "%.*s" // type - "%*s" // type padding - "%.*s" // reset - " %.*s" // file name - ":%05u ", // line number - time.date_size - 2, time.date + 2, - time.hms_size, time.hms, - colour.size, colour.data, - bold.size, bold.data, - type.size, type.data, - type_padding, "", - reset.size, reset.data, - file_name.size, file_name.data, - call_site.line); - header_size_no_ansi_codes = header.size - colour.size - Dqn_Print_ESCResetString.size; - } - - // NOTE: Header padding - // ========================================================================= - Dqn_usize header_padding = 0; - { - DQN_LOCAL_PERSIST Dqn_usize max_header_length = 0; - max_header_length = DQN_MAX(max_header_length, header_size_no_ansi_codes); - header_padding = max_header_length - header_size_no_ansi_codes; - } - - // NOTE: Construct final log - // ========================================================================= - Dqn_String8 msg = Dqn_String8_InitFV(scratch.allocator, fmt, args); - - Dqn_String8 log_line = Dqn_String8_Allocate(scratch.allocator, header.size + header_padding + msg.size, Dqn_ZeroMem_No); - DQN_MEMCPY(log_line.data, header.data, header.size); - DQN_MEMSET(log_line.data + header.size, ' ', header_padding); - DQN_MEMCPY(log_line.data + header.size + header_padding, msg.data, msg.size); + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 log_line = Dqn_Log_MakeString(scratch.allocator, + !dqn_library.log_no_colour, + type, + log_type, + call_site, + fmt, + args); // NOTE: Print log // ========================================================================= @@ -6362,12 +6399,15 @@ DQN_API void Dqn_Arena_Reset(Dqn_Arena *arena, Dqn_ZeroMem zero_mem) DQN_API Dqn_ArenaTempMemory Dqn_Arena_BeginTempMemory(Dqn_Arena *arena) { Dqn_ArenaTempMemory result = {}; - result.arena = arena; - result.head = arena->head; - result.curr = arena->curr; - result.tail = arena->tail; - result.curr_used = (arena->curr) ? arena->curr->used : 0; - result.stats = arena->stats; + if (arena) { + arena->temp_memory_count++; + result.arena = arena; + result.head = arena->head; + result.curr = arena->curr; + result.tail = arena->tail; + result.curr_used = (arena->curr) ? arena->curr->used : 0; + result.stats = arena->stats; + } return result; } @@ -6376,8 +6416,12 @@ DQN_API void Dqn_Arena_EndTempMemory_(DQN_LEAK_TRACE_FUNCTION Dqn_ArenaTempMemor if (!scope.arena) return; + Dqn_Arena *arena = scope.arena; + if (!DQN_CHECKF(arena->temp_memory_count > 0, "End temp memory has been called without a matching begin pair on the arena")) + return; + // NOTE: Revert arena stats - Dqn_Arena *arena = scope.arena; + arena->temp_memory_count--; arena->stats.capacity = scope.stats.capacity; arena->stats.used = scope.stats.used; arena->stats.wasted = scope.stats.wasted; @@ -6597,6 +6641,9 @@ DQN_API void Dqn_Arena_Free_(DQN_LEAK_TRACE_FUNCTION Dqn_Arena *arena, Dqn_ZeroM if (!arena) return; + if (!DQN_CHECKF(arena->temp_memory_count == 0, "You cannot free an arena whilst in an temp memory region")) + return; + while (arena->tail) { Dqn_ArenaBlock *block = arena->tail; arena->tail = block->prev; @@ -7148,52 +7195,39 @@ DQN_API bool Dqn_Bit_IsNotSet(uint64_t bits, uint64_t bits_to_check) // ================================================================================================= // [$SAFE] Dqn_Safe | | Safe arithmetic, casts, asserts // ================================================================================================= -DQN_API bool Dqn_Safe_AssertF_(bool assertion_expr, Dqn_CallSite call_site, char const *fmt, ...) -{ - bool result = assertion_expr; - if (!result) { - va_list args; - va_start(args, fmt); - Dqn_Log_TypeFVCallSite(Dqn_LogType_Error, call_site, fmt, args); - va_end(args); - DQN_DEBUG_BREAK; - } - return result; -} - DQN_API int64_t Dqn_Safe_AddI64(int64_t a, int64_t b) { - int64_t result = Dqn_Safe_AssertF(a <= INT64_MAX - b, "a=%zd, b=%zd", a, b) ? (a + b) : INT64_MAX; + int64_t result = DQN_CHECKF(a <= INT64_MAX - b, "a=%zd, b=%zd", a, b) ? (a + b) : INT64_MAX; return result; } DQN_API int64_t Dqn_Safe_MulI64(int64_t a, int64_t b) { - int64_t result = Dqn_Safe_AssertF(a <= INT64_MAX / b, "a=%zd, b=%zd", a, b) ? (a * b) : INT64_MAX; + int64_t result = DQN_CHECKF(a <= INT64_MAX / b, "a=%zd, b=%zd", a, b) ? (a * b) : INT64_MAX; return result; } DQN_API uint64_t Dqn_Safe_AddU64(uint64_t a, uint64_t b) { - uint64_t result = Dqn_Safe_AssertF(a <= UINT64_MAX - b, "a=%zu, b=%zu", a, b) ? (a + b) : UINT64_MAX; + uint64_t result = DQN_CHECKF(a <= UINT64_MAX - b, "a=%zu, b=%zu", a, b) ? (a + b) : UINT64_MAX; return result; } DQN_API uint64_t Dqn_Safe_SubU64(uint64_t a, uint64_t b) { - uint64_t result = Dqn_Safe_AssertF(a >= b, "a=%zu, b=%zu", a, b) ? (a - b) : 0; + uint64_t result = DQN_CHECKF(a >= b, "a=%zu, b=%zu", a, b) ? (a - b) : 0; return result; } DQN_API uint64_t Dqn_Safe_MulU64(uint64_t a, uint64_t b) { - uint64_t result = Dqn_Safe_AssertF(a <= UINT64_MAX / b, "a=%zu, b=%zu", a, b) ? (a * b) : UINT64_MAX; + uint64_t result = DQN_CHECKF(a <= UINT64_MAX / b, "a=%zu, b=%zu", a, b) ? (a * b) : UINT64_MAX; return result; } DQN_API uint32_t Dqn_Safe_SubU32(uint32_t a, uint32_t b) { - uint32_t result = Dqn_Safe_AssertF(a >= b, "a=%u, b=%u", a, b) ? (a - b) : 0; + uint32_t result = DQN_CHECKF(a >= b, "a=%u, b=%u", a, b) ? (a - b) : 0; return result; } @@ -7203,31 +7237,31 @@ DQN_API uint32_t Dqn_Safe_SubU32(uint32_t a, uint32_t b) // the highest possible rank (unsigned > signed). DQN_API int Dqn_Safe_SaturateCastUSizeToInt(Dqn_usize val) { - int result = Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= INT_MAX) ? DQN_CAST(int)val : INT_MAX; + int result = DQN_CHECK(DQN_CAST(uintmax_t)val <= INT_MAX) ? DQN_CAST(int)val : INT_MAX; return result; } DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8(Dqn_usize val) { - int8_t result = Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= INT8_MAX) ? DQN_CAST(int8_t)val : INT8_MAX; + int8_t result = DQN_CHECK(DQN_CAST(uintmax_t)val <= INT8_MAX) ? DQN_CAST(int8_t)val : INT8_MAX; return result; } DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16(Dqn_usize val) { - int16_t result = Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= INT16_MAX) ? DQN_CAST(int16_t)val : INT16_MAX; + int16_t result = DQN_CHECK(DQN_CAST(uintmax_t)val <= INT16_MAX) ? DQN_CAST(int16_t)val : INT16_MAX; return result; } DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32(Dqn_usize val) { - int32_t result = Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= INT32_MAX) ? DQN_CAST(int32_t)val : INT32_MAX; + int32_t result = DQN_CHECK(DQN_CAST(uintmax_t)val <= INT32_MAX) ? DQN_CAST(int32_t)val : INT32_MAX; return result; } DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64(Dqn_usize val) { - int64_t result = Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= INT64_MAX) ? DQN_CAST(int64_t)val : INT64_MAX; + int64_t result = DQN_CHECK(DQN_CAST(uintmax_t)val <= INT64_MAX) ? DQN_CAST(int64_t)val : INT64_MAX; return result; } @@ -7237,25 +7271,25 @@ DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64(Dqn_usize val) // match the highest rank operand. DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8(Dqn_usize val) { - uint8_t result = Dqn_Safe_Assert(val <= UINT8_MAX) ? DQN_CAST(uint8_t)val : UINT8_MAX; + uint8_t result = DQN_CHECK(val <= UINT8_MAX) ? DQN_CAST(uint8_t)val : UINT8_MAX; return result; } DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16(Dqn_usize val) { - uint16_t result = Dqn_Safe_Assert(val <= UINT16_MAX) ? DQN_CAST(uint16_t)val : UINT16_MAX; + uint16_t result = DQN_CHECK(val <= UINT16_MAX) ? DQN_CAST(uint16_t)val : UINT16_MAX; return result; } DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32(Dqn_usize val) { - uint32_t result = Dqn_Safe_Assert(val <= UINT32_MAX) ? DQN_CAST(uint32_t)val : UINT32_MAX; + uint32_t result = DQN_CHECK(val <= UINT32_MAX) ? DQN_CAST(uint32_t)val : UINT32_MAX; return result; } DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64(Dqn_usize val) { - uint64_t result = Dqn_Safe_Assert(val <= UINT64_MAX) ? DQN_CAST(uint64_t)val : UINT64_MAX; + uint64_t result = DQN_CHECK(val <= UINT64_MAX) ? DQN_CAST(uint64_t)val : UINT64_MAX; return result; } @@ -7265,25 +7299,25 @@ DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64(Dqn_usize val) // match the highest rank operand. DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt(uint64_t val) { - unsigned int result = Dqn_Safe_Assert(val <= UINT8_MAX) ? DQN_CAST(unsigned int)val : UINT_MAX; + unsigned int result = DQN_CHECK(val <= UINT8_MAX) ? DQN_CAST(unsigned int)val : UINT_MAX; return result; } DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8(uint64_t val) { - uint8_t result = Dqn_Safe_Assert(val <= UINT8_MAX) ? DQN_CAST(uint8_t)val : UINT8_MAX; + uint8_t result = DQN_CHECK(val <= UINT8_MAX) ? DQN_CAST(uint8_t)val : UINT8_MAX; return result; } DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16(uint64_t val) { - uint16_t result = Dqn_Safe_Assert(val <= UINT16_MAX) ? DQN_CAST(uint16_t)val : UINT16_MAX; + uint16_t result = DQN_CHECK(val <= UINT16_MAX) ? DQN_CAST(uint16_t)val : UINT16_MAX; return result; } DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32(uint64_t val) { - uint32_t result = Dqn_Safe_Assert(val <= UINT32_MAX) ? DQN_CAST(uint32_t)val : UINT32_MAX; + uint32_t result = DQN_CHECK(val <= UINT32_MAX) ? DQN_CAST(uint32_t)val : UINT32_MAX; return result; } @@ -7294,35 +7328,35 @@ DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32(uint64_t val) // match the highest rank operand. DQN_API int Dqn_Safe_SaturateCastISizeToInt(Dqn_isize val) { - Dqn_Safe_Assert(val >= INT_MIN && val <= INT_MAX); + DQN_ASSERT(val >= INT_MIN && val <= INT_MAX); int result = DQN_CAST(int)DQN_CLAMP(val, INT_MIN, INT_MAX); return result; } DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8(Dqn_isize val) { - Dqn_Safe_Assert(val >= INT8_MIN && val <= INT8_MAX); + DQN_ASSERT(val >= INT8_MIN && val <= INT8_MAX); int8_t result = DQN_CAST(int8_t)DQN_CLAMP(val, INT8_MIN, INT8_MAX); return result; } DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16(Dqn_isize val) { - Dqn_Safe_Assert(val >= INT16_MIN && val <= INT16_MAX); + DQN_ASSERT(val >= INT16_MIN && val <= INT16_MAX); int16_t result = DQN_CAST(int16_t)DQN_CLAMP(val, INT16_MIN, INT16_MAX); return result; } DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32(Dqn_isize val) { - Dqn_Safe_Assert(val >= INT32_MIN && val <= INT32_MAX); + DQN_ASSERT(val >= INT32_MIN && val <= INT32_MAX); int32_t result = DQN_CAST(int32_t)DQN_CLAMP(val, INT32_MIN, INT32_MAX); return result; } DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64(Dqn_isize val) { - Dqn_Safe_Assert(val >= INT64_MIN && val <= INT64_MAX); + DQN_ASSERT(val >= INT64_MIN && val <= INT64_MAX); int64_t result = DQN_CAST(int64_t)DQN_CLAMP(val, INT64_MIN, INT64_MAX); return result; } @@ -7335,8 +7369,8 @@ DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64(Dqn_isize val) DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt(Dqn_isize val) { unsigned int result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT_MAX)) result = DQN_CAST(unsigned int)val; else result = UINT_MAX; @@ -7347,8 +7381,8 @@ DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt(Dqn_isize val) DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8(Dqn_isize val) { uint8_t result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT8_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT8_MAX)) result = DQN_CAST(uint8_t)val; else result = UINT8_MAX; @@ -7359,8 +7393,8 @@ DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8(Dqn_isize val) DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16(Dqn_isize val) { uint16_t result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT16_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT16_MAX)) result = DQN_CAST(uint16_t)val; else result = UINT16_MAX; @@ -7371,8 +7405,8 @@ DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16(Dqn_isize val) DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32(Dqn_isize val) { uint32_t result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT32_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT32_MAX)) result = DQN_CAST(uint32_t)val; else result = UINT32_MAX; @@ -7383,8 +7417,8 @@ DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32(Dqn_isize val) DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64(Dqn_isize val) { uint64_t result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT64_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT64_MAX)) result = DQN_CAST(uint64_t)val; else result = UINT64_MAX; @@ -7398,28 +7432,28 @@ DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64(Dqn_isize val) // match the highest rank operand. DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize(int64_t val) { - Dqn_Safe_Assert(val >= DQN_ISIZE_MIN && val <= DQN_ISIZE_MAX); + DQN_CHECK(val >= DQN_ISIZE_MIN && val <= DQN_ISIZE_MAX); Dqn_isize result = DQN_CAST(int64_t)DQN_CLAMP(val, DQN_ISIZE_MIN, DQN_ISIZE_MAX); return result; } DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8(int64_t val) { - Dqn_Safe_Assert(val >= INT8_MIN && val <= INT8_MAX); + DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX); int8_t result = DQN_CAST(int8_t)DQN_CLAMP(val, INT8_MIN, INT8_MAX); return result; } DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16(int64_t val) { - Dqn_Safe_Assert(val >= INT16_MIN && val <= INT16_MAX); + DQN_CHECK(val >= INT16_MIN && val <= INT16_MAX); int16_t result = DQN_CAST(int16_t)DQN_CLAMP(val, INT16_MIN, INT16_MAX); return result; } DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32(int64_t val) { - Dqn_Safe_Assert(val >= INT32_MIN && val <= INT32_MAX); + DQN_CHECK(val >= INT32_MIN && val <= INT32_MAX); int32_t result = DQN_CAST(int32_t)DQN_CLAMP(val, INT32_MIN, INT32_MAX); return result; } @@ -7428,14 +7462,14 @@ DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32(int64_t val) // ----------------------------------------------------------------------------- DQN_API int8_t Dqn_Safe_SaturateCastIntToI8(int val) { - Dqn_Safe_Assert(val >= INT8_MIN && val <= INT8_MAX); + DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX); int8_t result = DQN_CAST(int8_t)DQN_CLAMP(val, INT8_MIN, INT8_MAX); return result; } DQN_API int16_t Dqn_Safe_SaturateCastIntToI16(int val) { - Dqn_Safe_Assert(val >= INT16_MIN && val <= INT16_MAX); + DQN_CHECK(val >= INT16_MIN && val <= INT16_MAX); int16_t result = DQN_CAST(int16_t)DQN_CLAMP(val, INT16_MIN, INT16_MAX); return result; } @@ -7443,8 +7477,8 @@ DQN_API int16_t Dqn_Safe_SaturateCastIntToI16(int val) DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8(int val) { uint8_t result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT8_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT8_MAX)) result = DQN_CAST(uint8_t)val; else result = UINT8_MAX; @@ -7455,8 +7489,8 @@ DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8(int val) DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16(int val) { uint16_t result = 0; - if (Dqn_Safe_Assert(val >= DQN_CAST(Dqn_isize)0)) { - if (Dqn_Safe_Assert(DQN_CAST(uintmax_t)val <= UINT16_MAX)) + if (DQN_CHECK(val >= DQN_CAST(Dqn_isize)0)) { + if (DQN_CHECK(DQN_CAST(uintmax_t)val <= UINT16_MAX)) result = DQN_CAST(uint16_t)val; else result = UINT16_MAX; @@ -7468,7 +7502,7 @@ DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32(int val) { static_assert(sizeof(val) <= sizeof(uint32_t), "Sanity check to allow simplifying of casting"); uint32_t result = 0; - if (Dqn_Safe_Assert(val >= 0)) + if (DQN_CHECK(val >= 0)) result = DQN_CAST(uint32_t)val; return result; } @@ -7477,7 +7511,7 @@ DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64(int val) { static_assert(sizeof(val) <= sizeof(uint64_t), "Sanity check to allow simplifying of casting"); uint64_t result = 0; - if (Dqn_Safe_Assert(val >= 0)) + if (DQN_CHECK(val >= 0)) result = DQN_CAST(uint64_t)val; return result; } @@ -7727,7 +7761,7 @@ DQN_API bool Dqn_Bin_BytesToHexBuffer(void const *src, Dqn_usize src_size, char if (!src || !dest) return false; - if (!Dqn_Safe_Assert(dest_size >= src_size * 2)) + if (!DQN_CHECK(dest_size >= src_size * 2)) return false; char const *HEX = "0123456789abcdef"; @@ -8433,7 +8467,7 @@ DQN_API bool Dqn_Win_NetHandleSetRequestHeaderCString8(Dqn_WinNetHandle *handle, if (handle->state < Dqn_WinNetHandleState_HttpMethodReady) return false; - if (!Dqn_Safe_Assert(handle->http_handle)) + if (!DQN_CHECK(handle->http_handle)) return false; unsigned long modifier = 0; @@ -8489,7 +8523,7 @@ DQN_API Dqn_WinNetHandleResponse Dqn_Win_NetHandleSendRequest(Dqn_WinNetHandle * handle->state = Dqn_WinNetHandleState_RequestGood; unsigned long buffer_size = 0; int query_result = HttpQueryInfoA(handle->http_handle, HTTP_QUERY_RAW_HEADERS_CRLF, nullptr, &buffer_size, nullptr); - if (!Dqn_Safe_Assert(query_result != ERROR_INSUFFICIENT_BUFFER)) + if (!DQN_CHECK(query_result != ERROR_INSUFFICIENT_BUFFER)) return result; result.raw_headers = Dqn_String8_Allocate(allocator, buffer_size, Dqn_ZeroMem_No); @@ -9326,8 +9360,8 @@ DQN_API char *Dqn_Fs_ReadCString8_(DQN_LEAK_TRACE_FUNCTION char const *path, Dqn } unsigned long const bytes_desired = DQN_CAST(unsigned long)win_file_size.QuadPart; - if (!Dqn_Safe_AssertF(bytes_desired == win_file_size.QuadPart, - "Current implementation doesn't support >4GiB, implement Win32 overlapped IO")) { + if (!DQN_CHECKF(bytes_desired == win_file_size.QuadPart, + "Current implementation doesn't support >4GiB, implement Win32 overlapped IO")) { return nullptr; } diff --git a/dqn_tester.h b/dqn_tester.h deleted file mode 100644 index a569ed9..0000000 --- a/dqn_tester.h +++ /dev/null @@ -1,256 +0,0 @@ -#if !defined(DQN_TESTER_H) -#define DQN_TESTER_H -// -// NOTE: Overview -// ----------------------------------------------------------------------------- -// A super minimal testing framework, most of the logic here is the pretty -// printing of test results. - -// NOTE: Configuration -// ----------------------------------------------------------------------------- -// #define DQN_TESTER_IMPLEMENTATION -// Define this in one and only one C++ file to enable the implementation -// code of the header file. This will also automatically enable the JSMN -// implementation. -// -// #define DQN_TESTER_RESULT_LPAD -// Define this to a number to specify how much to pad the output of the test -// result line before the test result is printed. -// -// #define DQN_TESTER_RESULT_PAD_CHAR -// Define this to a character to specify the default character to use for -// padding. By default this is '.' -// -// #define DQN_TESTER_SPACING -// Define this to a number to specify the number of spaces between the group -// declaration and the test output in the group. -// -// #define DQN_TESTER_BAD_COLOR -// Define this to a terminal color code to specify what color errors will be -// presented as. -// -// #define DQN_TESTER_GOOD_COLOR -// Define this to a terminal color code to specify what color sucess will be -// presented as. - -// NOTE: Macros -// ----------------------------------------------------------------------------- -#include -#include -#include - -#if !defined(DQN_TESTER_RESULT_LPAD) - #define DQN_TESTER_RESULT_LPAD 90 -#endif - -#if !defined(DQN_TESTER_RESULT_PAD_CHAR) - #define DQN_TESTER_RESULT_PAD_CHAR '.' -#endif - -#if !defined(DQN_TESTER_SPACING) - #define DQN_TESTER_SPACING 2 -#endif - -#if !defined(DQN_TESTER_BAD_COLOR) - #define DQN_TESTER_BAD_COLOR "\x1b[31m" -#endif - -#if !defined(DQN_TESTER_GOOD_COLOR) - #define DQN_TESTER_GOOD_COLOR "\x1b[32m" -#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) - -/// 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__) - -#define DQN_TESTER_ASSERT(test, expr) DQN_TESTER_ASSERT_AT((test), __FILE__, __LINE__, (expr)) - -#define DQN_TESTER_LOG(test, fmt, ...) \ - do { \ - if ((test)->log_count++ == 0) { \ - fprintf(stdout, "\n"); \ - } \ - fprintf(stdout, "%*sLog: " fmt "\n", DQN_TESTER_SPACING * 2, "", ##__VA_ARGS__); \ - } while (0) - -#define DQN_TESTER_ASSERTF_AT(test, file, line, expr, fmt, ...) \ - do { \ - if (!(expr)) { \ - if ((test)->log_count++ == 0) { \ - fprintf(stdout, "\n"); \ - } \ - (test)->state = Dqn_TesterTestState_TestFailed; \ - fprintf(stderr, \ - "%*sAssertion Triggered\n" \ - "%*sFile: %s:%d\n" \ - "%*sExpression: [" #expr "]\n" \ - "%*sReason: " fmt "\n", \ - DQN_TESTER_SPACING * 2, \ - "", \ - DQN_TESTER_SPACING * 3, \ - "", \ - file, \ - line, \ - DQN_TESTER_SPACING * 3, \ - "", \ - DQN_TESTER_SPACING * 3, \ - "", \ - ##__VA_ARGS__); \ - } \ - } while (0) - -#define DQN_TESTER_ASSERT_AT(test, file, line, expr) \ - do { \ - if (!(expr)) { \ - if ((test)->log_count++ == 0) { \ - fprintf(stdout, "\n"); \ - } \ - (test)->state = Dqn_TesterTestState_TestFailed; \ - fprintf(stderr, \ - "%*sFile: %s:%d\n" \ - "%*sExpression: [" #expr "]\n", \ - DQN_TESTER_SPACING * 2, \ - "", \ - file, \ - line, \ - DQN_TESTER_SPACING * 2, \ - ""); \ - } \ - } while (0) - -// NOTE: Header -// ----------------------------------------------------------------------------- -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_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); - -// 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_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_TesterTestState_TestBegun; - test->log_count = 0; - - int size_required = 0; - { - va_list args_copy; - va_copy(args_copy, args); - size_required = vsnprintf(NULL, 0, fmt, args_copy); - va_end(args_copy); - } - - printf("%*s", DQN_TESTER_SPACING, ""); - vprintf(fmt, args); - for (int pad = DQN_TESTER_SPACING + size_required; pad < DQN_TESTER_RESULT_LPAD; pad++) - putc(DQN_TESTER_RESULT_PAD_CHAR, stdout); -} - -void Dqn_Tester_Begin(Dqn_Tester *test, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Tester_BeginV(test, fmt, args); - va_end(args); -} - -void Dqn_Tester_End(Dqn_Tester *test) -{ - 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 - // the result on a new line. - printf("%*s", DQN_TESTER_SPACING, ""); - for (int pad = DQN_TESTER_SPACING; pad < DQN_TESTER_RESULT_LPAD; pad++) - putc(DQN_TESTER_RESULT_PAD_CHAR, stdout); - } - - if (test->state == Dqn_TesterTestState_TestFailed) { - fprintf(stdout, DQN_TESTER_BAD_COLOR " FAILED"); - } else { - fprintf(stdout, DQN_TESTER_GOOD_COLOR " OK"); - test->num_tests_ok_in_group++; - } - - fprintf(stdout, DQN_TESTER_COLOR_RESET "\n"); - if (test->log_count != 0) { - putc('\n', stdout); - } - - test->state = Dqn_TesterTestState_Nil; -} -#endif // DQN_TESTER_IMPLEMENTATION -#endif // DQN_TESTER_H diff --git a/dqn_unit_tests.cpp b/dqn_unit_tests.cpp index a5e6a75..023ece1 100644 --- a/dqn_unit_tests.cpp +++ b/dqn_unit_tests.cpp @@ -18,6 +18,7 @@ #define STBSP__ASAN __declspec(no_sanitize_address) #endif + #define DQN_NO_CHECK_BREAK #define DQN_IMPLEMENTATION #include "dqn.h" #endif @@ -28,8 +29,8 @@ #include "dqn_tests_helpers.cpp" #endif -#define DQN_TESTER_IMPLEMENTATION -#include "dqn_tester.h" +#define DQN_UTEST_IMPLEMENTATION +#include "dqn_utest.h" enum Guard { Guard_None, @@ -47,13 +48,13 @@ static Dqn_String8 ArenaGuardTestSuffix(uint32_t guard) return result; } -Dqn_Tester TestArena() +Dqn_UTest TestArena() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_Arena") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_Arena") { for (Dqn_usize guard = 0; guard < Guard_Count; guard++) { Dqn_String8 test_suffix = ArenaGuardTestSuffix(guard); - DQN_TESTER_TEST("Reused memory is zeroed out%.*s", DQN_STRING_FMT(test_suffix)) { + DQN_UTEST_TEST("Reused memory is zeroed out%.*s", DQN_STRING_FMT(test_suffix)) { Dqn_Arena arena = {}; arena.use_after_free_guard = guard == Guard_UseAfterFree; @@ -72,26 +73,26 @@ Dqn_Tester TestArena() char *ptr = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, size, 1, Dqn_ZeroMem_Yes); // NOTE: Double check we got the same pointer - DQN_TESTER_ASSERT(&test, first_ptr_address == DQN_CAST(uintptr_t)ptr); + DQN_UTEST_ASSERT(&test, first_ptr_address == DQN_CAST(uintptr_t)ptr); // NOTE: Check that the bytes are set to 0 for (Dqn_usize i = 0; i < size; i++) - DQN_TESTER_ASSERT(&test, ptr[i] == 0); + DQN_UTEST_ASSERT(&test, ptr[i] == 0); Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); } } for (Dqn_usize guard = 0; guard < Guard_Count; guard++) { Dqn_String8 test_suffix = ArenaGuardTestSuffix(guard); - DQN_TESTER_TEST("Test arena grows naturally, 1mb + 4mb%.*s", DQN_STRING_FMT(test_suffix)) { + DQN_UTEST_TEST("Test arena grows naturally, 1mb + 4mb%.*s", DQN_STRING_FMT(test_suffix)) { Dqn_Arena arena = {}; arena.use_after_free_guard = guard == Guard_UseAfterFree; // NOTE: Allocate 1mb, then 4mb, this should force the arena to grow char *ptr_1mb = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(1), 1 /*align*/, Dqn_ZeroMem_Yes); char *ptr_4mb = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(4), 1 /*align*/, Dqn_ZeroMem_Yes); - DQN_TESTER_ASSERT(&test, ptr_1mb); - DQN_TESTER_ASSERT(&test, ptr_4mb); + DQN_UTEST_ASSERT(&test, ptr_1mb); + DQN_UTEST_ASSERT(&test, ptr_4mb); Dqn_ArenaBlock const *block_1mb = arena.head; char const *block_1mb_begin = DQN_CAST(char *)block_1mb->memory; @@ -101,17 +102,96 @@ Dqn_Tester TestArena() char const *block_4mb_begin = DQN_CAST(char *)block_4mb->memory; char const *block_4mb_end = DQN_CAST(char *)block_4mb->memory + block_4mb->size; - DQN_TESTER_ASSERTF(&test, block_1mb != block_4mb, "New block should have been allocated and linked"); - DQN_TESTER_ASSERTF(&test, ptr_1mb >= block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); - DQN_TESTER_ASSERTF(&test, ptr_4mb >= block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); + DQN_UTEST_ASSERTF(&test, block_1mb != block_4mb, "New block should have been allocated and linked"); + DQN_UTEST_ASSERTF(&test, ptr_1mb >= block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); + DQN_UTEST_ASSERTF(&test, ptr_4mb >= block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); + DQN_UTEST_ASSERT (&test, arena.curr == arena.tail); + DQN_UTEST_ASSERT (&test, arena.curr != arena.head); Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); } } + for (Dqn_usize guard = 0; guard < Guard_Count; guard++) { + Dqn_String8 test_suffix = ArenaGuardTestSuffix(guard); + DQN_UTEST_TEST("Test arena grows naturally, 1mb, temp memory 4mb%.*s", DQN_STRING_FMT(test_suffix)) { + Dqn_Arena arena = {}; + arena.use_after_free_guard = guard == Guard_UseAfterFree; + + // NOTE: Allocate 1mb, then 4mb, this should force the arena to grow + char *ptr_1mb = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(1), 1 /*align*/, Dqn_ZeroMem_Yes); + DQN_UTEST_ASSERT(&test, ptr_1mb); + + Dqn_ArenaTempMemory temp_memory = Dqn_Arena_BeginTempMemory(&arena); + { + char *ptr_4mb = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(4), 1 /*align*/, Dqn_ZeroMem_Yes); + DQN_UTEST_ASSERT(&test, ptr_4mb); + + Dqn_ArenaBlock const *block_1mb = arena.head; + char const *block_1mb_begin = DQN_CAST(char *)block_1mb->memory; + char const *block_1mb_end = DQN_CAST(char *)block_1mb->memory + block_1mb->size; + + Dqn_ArenaBlock const *block_4mb = arena.curr; + char const *block_4mb_begin = DQN_CAST(char *)block_4mb->memory; + char const *block_4mb_end = DQN_CAST(char *)block_4mb->memory + block_4mb->size; + + DQN_UTEST_ASSERTF(&test, block_1mb != block_4mb, "New block should have been allocated and linked"); + DQN_UTEST_ASSERTF(&test, ptr_1mb >= block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); + DQN_UTEST_ASSERTF(&test, ptr_4mb >= block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); + DQN_UTEST_ASSERT (&test, arena.curr == arena.tail); + DQN_UTEST_ASSERT (&test, arena.curr != arena.head); + } + Dqn_Arena_EndTempMemory(temp_memory); + + DQN_UTEST_ASSERT (&test, arena.curr == arena.head); + DQN_UTEST_ASSERT (&test, arena.curr == arena.tail); + DQN_UTEST_ASSERT (&test, arena.curr->next == nullptr); + DQN_UTEST_ASSERTF(&test, arena.curr->size >= DQN_MEGABYTES(1), + "size=%zuMiB (%zuB), expect=%zuB", (arena.curr->size / 1024 / 1024), arena.curr->size, DQN_MEGABYTES(1)); + + Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); + } + } + + for (Dqn_usize guard = 0; guard < Guard_Count; guard++) { + Dqn_String8 test_suffix = ArenaGuardTestSuffix(guard); + DQN_UTEST_TEST("Zero init arena, temp region then free inside region%.*s", DQN_STRING_FMT(test_suffix)) { + Dqn_Arena arena = {}; + arena.use_after_free_guard = guard == Guard_UseAfterFree; + Dqn_ArenaTempMemory temp_memory = Dqn_Arena_BeginTempMemory(&arena); + { + char *ptr = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(1), 1 /*align*/, Dqn_ZeroMem_Yes); + DQN_UTEST_ASSERT(&test, ptr); + Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); + } + Dqn_Arena_EndTempMemory(temp_memory); + Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); + } + } + + for (Dqn_usize guard = 0; guard < Guard_Count; guard++) { + Dqn_String8 test_suffix = ArenaGuardTestSuffix(guard); + DQN_UTEST_TEST("Zero init arena, allocate, temp region then free inside region%.*s", DQN_STRING_FMT(test_suffix)) { + Dqn_Arena arena = {}; + arena.use_after_free_guard = guard == Guard_UseAfterFree; + + char *outside = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(1), 1 /*align*/, Dqn_ZeroMem_Yes); + DQN_UTEST_ASSERT(&test, outside); + + Dqn_ArenaTempMemory temp_memory = Dqn_Arena_BeginTempMemory(&arena); + { + char *inside = DQN_CAST(char *)Dqn_Arena_Allocate(&arena, DQN_MEGABYTES(2), 1 /*align*/, Dqn_ZeroMem_Yes); + DQN_UTEST_ASSERT(&test, inside); + Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); + } + Dqn_Arena_EndTempMemory(temp_memory); + Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); + } + } + Dqn_usize sizes[] = {DQN_KILOBYTES(1), DQN_KILOBYTES(4), DQN_KILOBYTES(5)}; for (Dqn_usize size : sizes) { - DQN_TESTER_TEST("Use-after-free guard on %.1f KiB allocation", size / 1024.0) { + DQN_UTEST_TEST("Use-after-free guard on %.1f KiB allocation", size / 1024.0) { Dqn_Arena arena = {}; arena.use_after_free_guard = true; Dqn_Arena_Grow(&arena, size, false /*commit*/, 0 /*flags*/); @@ -132,91 +212,90 @@ Dqn_Tester TestArena() caught = true; } - DQN_TESTER_ASSERTF(&test, caught, "Exception was not triggered, was page protected properly?"); + DQN_UTEST_ASSERTF(&test, caught, "Exception was not triggered, was page protected properly?"); Dqn_Arena_Free(&arena, Dqn_ZeroMem_No); } } } - return test; } -Dqn_Tester TestBin() +Dqn_UTest TestBin() { Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_Bin") { - DQN_TESTER_TEST("Convert 0x123") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_Bin") { + DQN_UTEST_TEST("Convert 0x123") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("0x123")); - DQN_TESTER_ASSERTF(&test, result == 0x123, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0x123, "result: %zu", result); } - DQN_TESTER_TEST("Convert 0xFFFF") { + DQN_UTEST_TEST("Convert 0xFFFF") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("0xFFFF")); - DQN_TESTER_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); } - DQN_TESTER_TEST("Convert FFFF") { + DQN_UTEST_TEST("Convert FFFF") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("FFFF")); - DQN_TESTER_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0xFFFF, "result: %zu", result); } - DQN_TESTER_TEST("Convert abCD") { + DQN_UTEST_TEST("Convert abCD") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("abCD")); - DQN_TESTER_ASSERTF(&test, result == 0xabCD, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0xabCD, "result: %zu", result); } - DQN_TESTER_TEST("Convert 0xabCD") { + DQN_UTEST_TEST("Convert 0xabCD") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("0xabCD")); - DQN_TESTER_ASSERTF(&test, result == 0xabCD, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0xabCD, "result: %zu", result); } - DQN_TESTER_TEST("Convert 0x") { + DQN_UTEST_TEST("Convert 0x") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("0x")); - DQN_TESTER_ASSERTF(&test, result == 0x0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0x0, "result: %zu", result); } - DQN_TESTER_TEST("Convert 0X") { + DQN_UTEST_TEST("Convert 0X") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("0X")); - DQN_TESTER_ASSERTF(&test, result == 0x0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0x0, "result: %zu", result); } - DQN_TESTER_TEST("Convert 3") { + DQN_UTEST_TEST("Convert 3") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("3")); - DQN_TESTER_ASSERTF(&test, result == 3, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 3, "result: %zu", result); } - DQN_TESTER_TEST("Convert f") { + DQN_UTEST_TEST("Convert f") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("f")); - DQN_TESTER_ASSERTF(&test, result == 0xf, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0xf, "result: %zu", result); } - DQN_TESTER_TEST("Convert g") { + DQN_UTEST_TEST("Convert g") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("g")); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0, "result: %zu", result); } - DQN_TESTER_TEST("Convert -0x3") { + DQN_UTEST_TEST("Convert -0x3") { uint64_t result = Dqn_Bin_HexToU64(DQN_STRING8("-0x3")); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0, "result: %zu", result); } uint32_t number = 0xd095f6; - DQN_TESTER_TEST("Convert %x to string", number) { + DQN_UTEST_TEST("Convert %x to string", number) { Dqn_String8 number_hex = Dqn_Bin_BytesToHexArena(scratch.arena, &number, sizeof(number)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(number_hex, DQN_STRING8("f695d000")), "number_hex=%.*s", DQN_STRING_FMT(number_hex)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(number_hex, DQN_STRING8("f695d000")), "number_hex=%.*s", DQN_STRING_FMT(number_hex)); } number = 0xf6ed00; - DQN_TESTER_TEST("Convert %x to string", number) { + DQN_UTEST_TEST("Convert %x to string", number) { Dqn_String8 number_hex = Dqn_Bin_BytesToHexArena(scratch.arena, &number, sizeof(number)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(number_hex, DQN_STRING8("00edf600")), "number_hex=%.*s", DQN_STRING_FMT(number_hex)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(number_hex, DQN_STRING8("00edf600")), "number_hex=%.*s", DQN_STRING_FMT(number_hex)); } Dqn_String8 hex = DQN_STRING8("0xf6ed00"); - DQN_TESTER_TEST("Convert %.*s to bytes", DQN_STRING_FMT(hex)) { + DQN_UTEST_TEST("Convert %.*s to bytes", DQN_STRING_FMT(hex)) { Dqn_String8 bytes = Dqn_Bin_HexToBytesArena(scratch.arena, hex); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(bytes, DQN_STRING8("\xf6\xed\x00")), "number_hex=%.*s", DQN_STRING_FMT(Dqn_Bin_BytesToHexArena(scratch.arena, bytes.data, bytes.size))); @@ -227,213 +306,213 @@ Dqn_Tester TestBin() } -Dqn_Tester TestBinarySearch() +Dqn_UTest TestBinarySearch() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_BinarySearch") { - DQN_TESTER_TEST("Search array of 1 item") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_BinarySearch") { + DQN_UTEST_TEST("Search array of 1 item") { uint32_t array[] = {1}; Dqn_BinarySearchResult result = {}; result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); } - DQN_TESTER_TEST("Search array of 2 items") { + DQN_UTEST_TEST("Search array of 2 items") { uint32_t array[] = {1, 2}; Dqn_BinarySearchResult result = {}; result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 2); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 2); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 2); } - DQN_TESTER_TEST("Search array of 3 items") { + DQN_UTEST_TEST("Search array of 3 items") { uint32_t array[] = {1, 2, 3}; Dqn_BinarySearchResult result = {}; result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 2); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 2); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 3); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 3); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 3); } - DQN_TESTER_TEST("Search array of 4 items") { + DQN_UTEST_TEST("Search array of 4 items") { uint32_t array[] = {1, 2, 3, 4}; Dqn_BinarySearchResult result = {}; result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 2); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 3); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5 /*find*/, Dqn_BinarySearchType_Match); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 0); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 1); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 1); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 2); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 2); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 3); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 3); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.index == 4); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.index == 4); result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5 /*find*/, Dqn_BinarySearchType_OnePastMatch); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.index == 4); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.index == 4); } } return test; } -Dqn_Tester TestDSMap() +Dqn_UTest TestDSMap() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_DSMap") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_DSMap") { Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); { uint32_t const MAP_SIZE = 64; Dqn_DSMap map = Dqn_DSMap_Init(MAP_SIZE); DQN_DEFER { Dqn_DSMap_Deinit(&map); }; - DQN_TESTER_TEST("Find non-existent value") { + DQN_UTEST_TEST("Find non-existent value") { uint64_t *value = Dqn_DSMap_Find(&map, Dqn_DSMap_KeyCStringLit(&map, "Foo")); - DQN_TESTER_ASSERT(&test, !value); - DQN_TESTER_ASSERT(&test, map.size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.occupied == 1 /*Sentinel*/); + DQN_UTEST_ASSERT(&test, !value); + DQN_UTEST_ASSERT(&test, map.size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); } Dqn_DSMapKey key = Dqn_DSMap_KeyCStringLit(&map, "Bar"); - DQN_TESTER_TEST("Insert value and lookup") { + DQN_UTEST_TEST("Insert value and lookup") { uint64_t desired_value = 0xF00BAA; uint64_t *slot_value = Dqn_DSMap_Set(&map, key, desired_value, nullptr /*found*/); - DQN_TESTER_ASSERT(&test, slot_value); - DQN_TESTER_ASSERT(&test, map.size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.occupied == 2); + DQN_UTEST_ASSERT(&test, slot_value); + DQN_UTEST_ASSERT(&test, map.size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.occupied == 2); uint64_t *value = Dqn_DSMap_Find(&map, key); - DQN_TESTER_ASSERT(&test, value); - DQN_TESTER_ASSERT(&test, *value == desired_value); + DQN_UTEST_ASSERT(&test, value); + DQN_UTEST_ASSERT(&test, *value == desired_value); } - DQN_TESTER_TEST("Remove key") { + DQN_UTEST_TEST("Remove key") { Dqn_DSMap_Erase(&map, key); - DQN_TESTER_ASSERT(&test, map.size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.occupied == 1 /*Sentinel*/); + DQN_UTEST_ASSERT(&test, map.size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); } } @@ -450,28 +529,28 @@ Dqn_Tester TestDSMap() Dqn_DSMap map = Dqn_DSMap_Init(MAP_SIZE); DQN_DEFER { Dqn_DSMap_Deinit(&map); }; - DQN_TESTER_TEST("%.*s: Test growing", DQN_STRING_FMT(prefix)) { + DQN_UTEST_TEST("%.*s: Test growing", DQN_STRING_FMT(prefix)) { uint64_t map_start_size = map.size; uint64_t value = 0; uint64_t grow_threshold = map_start_size * 3 / 4; for (; map.occupied != grow_threshold; value++) { uint64_t *val_copy = Dqn_Arena_Copy(scratch.arena, uint64_t, &value, 1); Dqn_DSMapKey key = Dqn_DSMap_KeyBuffer(&map, (char *)val_copy, sizeof(*val_copy)); - DQN_TESTER_ASSERT(&test, !Dqn_DSMap_Find(&map, key)); - DQN_TESTER_ASSERT(&test, !Dqn_DSMap_FindSlot(&map, key)); + DQN_UTEST_ASSERT(&test, !Dqn_DSMap_Find(&map, key)); + DQN_UTEST_ASSERT(&test, !Dqn_DSMap_FindSlot(&map, key)); bool found = false; if (test_type == DSMapTestType_Set) { Dqn_DSMap_Set(&map, key, value, &found); } else { Dqn_DSMap_MakeSlot(&map, key, &found); } - DQN_TESTER_ASSERT(&test, !found); - DQN_TESTER_ASSERT(&test, Dqn_DSMap_Find(&map, key)); - DQN_TESTER_ASSERT(&test, Dqn_DSMap_FindSlot(&map, key)); + DQN_UTEST_ASSERT(&test, !found); + DQN_UTEST_ASSERT(&test, Dqn_DSMap_Find(&map, key)); + DQN_UTEST_ASSERT(&test, Dqn_DSMap_FindSlot(&map, key)); } - DQN_TESTER_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.size == map_start_size); - DQN_TESTER_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); + DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.size == map_start_size); + DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); { // NOTE: One more item should cause the table to grow by 2x uint64_t *val_copy = Dqn_Arena_Copy(scratch.arena, uint64_t, &value, 1); @@ -484,41 +563,41 @@ Dqn_Tester TestDSMap() } value++; - DQN_TESTER_ASSERT(&test, !found); - DQN_TESTER_ASSERT(&test, map.size == map_start_size * 2); - DQN_TESTER_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); + DQN_UTEST_ASSERT(&test, !found); + DQN_UTEST_ASSERT(&test, map.size == map_start_size * 2); + DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); } } - DQN_TESTER_TEST("%.*s: Check the sentinel is present", DQN_STRING_FMT(prefix)) { + DQN_UTEST_TEST("%.*s: Check the sentinel is present", DQN_STRING_FMT(prefix)) { Dqn_DSMapSlot NIL_SLOT = {}; Dqn_DSMapSlot sentinel = map.slots[DQN_DS_MAP_SENTINEL_SLOT]; - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); } - DQN_TESTER_TEST("%.*s: Recheck all the hash tables values after growing", DQN_STRING_FMT(prefix)) { + DQN_UTEST_TEST("%.*s: Recheck all the hash tables values after growing", DQN_STRING_FMT(prefix)) { for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) { Dqn_DSMapSlot const *slot = map.slots + index; // NOTE: Validate each slot value uint64_t value_test = index - 1; Dqn_DSMapKey key = Dqn_DSMap_KeyBuffer(&map, &value_test, sizeof(value_test)); - DQN_TESTER_ASSERT(&test, Dqn_DSMap_KeyEquals(slot->key, key)); + DQN_UTEST_ASSERT(&test, Dqn_DSMap_KeyEquals(slot->key, key)); if (test_type == DSMapTestType_Set) { - DQN_TESTER_ASSERT(&test, slot->value == value_test); + DQN_UTEST_ASSERT(&test, slot->value == value_test); } else { - DQN_TESTER_ASSERT(&test, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 + DQN_UTEST_ASSERT(&test, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 } - DQN_TESTER_ASSERT(&test, slot->key.hash == Dqn_DSMap_Hash(&map, slot->key)); + DQN_UTEST_ASSERT(&test, slot->key.hash == Dqn_DSMap_Hash(&map, slot->key)); // NOTE: Check the reverse lookup is correct Dqn_DSMapSlot const *check = Dqn_DSMap_FindSlot(&map, slot->key); - DQN_TESTER_ASSERT(&test, slot == check); + DQN_UTEST_ASSERT(&test, slot == check); } } - DQN_TESTER_TEST("%.*s: Test shrinking", DQN_STRING_FMT(prefix)) { + DQN_UTEST_TEST("%.*s: Test shrinking", DQN_STRING_FMT(prefix)) { uint64_t start_map_size = map.size; uint64_t start_map_occupied = map.occupied; uint64_t value = 0; @@ -527,14 +606,14 @@ Dqn_Tester TestDSMap() uint64_t *val_copy = Dqn_Arena_Copy(scratch.arena, uint64_t, &value, 1); Dqn_DSMapKey key = Dqn_DSMap_KeyBuffer(&map, (char *)val_copy, sizeof(*val_copy)); - DQN_TESTER_ASSERT(&test, Dqn_DSMap_Find(&map, key)); - DQN_TESTER_ASSERT(&test, Dqn_DSMap_FindSlot(&map, key)); + DQN_UTEST_ASSERT(&test, Dqn_DSMap_Find(&map, key)); + DQN_UTEST_ASSERT(&test, Dqn_DSMap_FindSlot(&map, key)); Dqn_DSMap_Erase(&map, key); - DQN_TESTER_ASSERT(&test, !Dqn_DSMap_Find(&map, key)); - DQN_TESTER_ASSERT(&test, !Dqn_DSMap_FindSlot(&map, key)); + DQN_UTEST_ASSERT(&test, !Dqn_DSMap_Find(&map, key)); + DQN_UTEST_ASSERT(&test, !Dqn_DSMap_FindSlot(&map, key)); } - DQN_TESTER_ASSERT(&test, map.size == start_map_size); - DQN_TESTER_ASSERT(&test, map.occupied == start_map_occupied - value); + DQN_UTEST_ASSERT(&test, map.size == start_map_size); + DQN_UTEST_ASSERT(&test, map.occupied == start_map_occupied - value); { // NOTE: One more item should cause the table to grow by 2x uint64_t *val_copy = Dqn_Arena_Copy(scratch.arena, uint64_t, &value, 1); @@ -542,14 +621,14 @@ Dqn_Tester TestDSMap() Dqn_DSMap_Erase(&map, key); value++; - DQN_TESTER_ASSERT(&test, map.size == start_map_size / 2); - DQN_TESTER_ASSERT(&test, map.occupied == start_map_occupied - value); + DQN_UTEST_ASSERT(&test, map.size == start_map_size / 2); + DQN_UTEST_ASSERT(&test, map.occupied == start_map_occupied - value); } { // NOTE: Check the sentinel is present Dqn_DSMapSlot NIL_SLOT = {}; Dqn_DSMapSlot sentinel = map.slots[DQN_DS_MAP_SENTINEL_SLOT]; - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); } // NOTE: Recheck all the hash table values after growing @@ -561,249 +640,249 @@ Dqn_Tester TestDSMap() // NOTE: Validate each slot value Dqn_DSMapSlot const *slot = Dqn_DSMap_FindSlot(&map, key); - DQN_TESTER_ASSERT(&test, slot); - DQN_TESTER_ASSERT(&test, slot->key == key); + DQN_UTEST_ASSERT(&test, slot); + DQN_UTEST_ASSERT(&test, slot->key == key); if (test_type == DSMapTestType_Set) { - DQN_TESTER_ASSERT(&test, slot->value == value_test); + DQN_UTEST_ASSERT(&test, slot->value == value_test); } else { - DQN_TESTER_ASSERT(&test, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 + DQN_UTEST_ASSERT(&test, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 } - DQN_TESTER_ASSERT(&test, slot->key.hash == Dqn_DSMap_Hash(&map, slot->key)); + DQN_UTEST_ASSERT(&test, slot->key.hash == Dqn_DSMap_Hash(&map, slot->key)); // NOTE: Check the reverse lookup is correct Dqn_DSMapSlot const *check = Dqn_DSMap_FindSlot(&map, slot->key); - DQN_TESTER_ASSERT(&test, slot == check); + DQN_UTEST_ASSERT(&test, slot == check); } for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table uint64_t *val_copy = Dqn_Arena_Copy(scratch.arena, uint64_t, &value, 1); Dqn_DSMapKey key = Dqn_DSMap_KeyBuffer(&map, (char *)val_copy, sizeof(*val_copy)); - DQN_TESTER_ASSERT(&test, Dqn_DSMap_Find(&map, key)); + DQN_UTEST_ASSERT(&test, Dqn_DSMap_Find(&map, key)); Dqn_DSMap_Erase(&map, key); - DQN_TESTER_ASSERT(&test, !Dqn_DSMap_Find(&map, key)); + DQN_UTEST_ASSERT(&test, !Dqn_DSMap_Find(&map, key)); } - DQN_TESTER_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_TESTER_ASSERT(&test, map.size == map.initial_size); - DQN_TESTER_ASSERT(&test, map.occupied == 1 /*Sentinel*/); + DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DQN_UTEST_ASSERT(&test, map.size == map.initial_size); + DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); } } } return test; } -Dqn_Tester TestFString8() +Dqn_UTest TestFString8() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_FString8") { - DQN_TESTER_TEST("Append too much fails") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_FString8") { + DQN_UTEST_TEST("Append too much fails") { Dqn_FString8<4> str = {}; - DQN_TESTER_ASSERT(&test, !Dqn_FString8_Append(&str, DQN_STRING8("abcde"))); + DQN_UTEST_ASSERT(&test, !Dqn_FString8_Append(&str, DQN_STRING8("abcde"))); } - DQN_TESTER_TEST("Append format string too much fails") { + DQN_UTEST_TEST("Append format string too much fails") { Dqn_FString8<4> str = {}; - DQN_TESTER_ASSERT(&test, !Dqn_FString8_AppendF(&str, "abcde")); + DQN_UTEST_ASSERT(&test, !Dqn_FString8_AppendF(&str, "abcde")); } } return test; } -Dqn_Tester TestFs() +Dqn_UTest TestFs() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_Fs") { - 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_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_Fs") { + DQN_UTEST_TEST("Make directory recursive \"abcd/efgh\"") { + DQN_UTEST_ASSERTF(&test, Dqn_Fs_MakeDir(DQN_STRING8("abcd/efgh")), "Failed to make directory"); + DQN_UTEST_ASSERTF(&test, Dqn_Fs_DirExists(DQN_STRING8("abcd")), "Directory was not made"); + DQN_UTEST_ASSERTF(&test, Dqn_Fs_DirExists(DQN_STRING8("abcd/efgh")), "Subdirectory was not made"); + DQN_UTEST_ASSERTF(&test, Dqn_Fs_Exists(DQN_STRING8("abcd")) == false, "This function should only return true for files"); + DQN_UTEST_ASSERTF(&test, Dqn_Fs_Exists(DQN_STRING8("abcd/efgh")) == false, "This function should only return true for files"); + DQN_UTEST_ASSERTF(&test, Dqn_Fs_Delete(DQN_STRING8("abcd/efgh")), "Failed to delete directory"); + DQN_UTEST_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") { + DQN_UTEST_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)); + DQN_UTEST_ASSERT(&test, write_result); + DQN_UTEST_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)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_IsValid(read_file), "Failed to load file"); + DQN_UTEST_ASSERTF(&test, read_file.size == 4, "File read wrong amount of bytes"); + DQN_UTEST_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)); + DQN_UTEST_ASSERT(&test, copy_result); + DQN_UTEST_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"); + DQN_UTEST_ASSERT(&test, move_result); + DQN_UTEST_ASSERT(&test, Dqn_Fs_Exists(MOVE_FILE)); + DQN_UTEST_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); + DQN_UTEST_ASSERT(&test, delete_src_file); + DQN_UTEST_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_UTEST_ASSERT(&test, delete_non_existent_moved_file == false); + DQN_UTEST_ASSERT(&test, delete_non_existent_src_file == false); } } return test; } -Dqn_Tester TestFixedArray() +Dqn_UTest TestFixedArray() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_FArray") { - DQN_TESTER_TEST("Initialise from raw array") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_FArray") { + DQN_UTEST_TEST("Initialise from raw array") { int raw_array[] = {1, 2}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(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_UTEST_ASSERT(&test, array.size == 2); + DQN_UTEST_ASSERT(&test, array.data[0] == 1); + DQN_UTEST_ASSERT(&test, array.data[1] == 2); } - DQN_TESTER_TEST("Erase stable 1 element from array") { + DQN_UTEST_TEST("Erase stable 1 element from array") { int raw_array[] = {1, 2, 3}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); Dqn_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, Dqn_FArrayErase_Stable); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 1); - DQN_TESTER_ASSERT(&test, array.data[1] == 3); + DQN_UTEST_ASSERT(&test, array.size == 2); + DQN_UTEST_ASSERT(&test, array.data[0] == 1); + DQN_UTEST_ASSERT(&test, array.data[1] == 3); } - DQN_TESTER_TEST("Erase unstable 1 element from array") { + DQN_UTEST_TEST("Erase unstable 1 element from array") { int raw_array[] = {1, 2, 3}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); Dqn_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, Dqn_FArrayErase_Unstable); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 3); - DQN_TESTER_ASSERT(&test, array.data[1] == 2); + DQN_UTEST_ASSERT(&test, array.size == 2); + DQN_UTEST_ASSERT(&test, array.data[0] == 3); + DQN_UTEST_ASSERT(&test, array.data[1] == 2); } - DQN_TESTER_TEST("Add 1 element to array") { + DQN_UTEST_TEST("Add 1 element to array") { int const ITEM = 2; int raw_array[] = {1}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); Dqn_FArray_Add(&array, &ITEM, 1); - DQN_TESTER_ASSERT(&test, array.size == 2); - DQN_TESTER_ASSERT(&test, array.data[0] == 1); - DQN_TESTER_ASSERT(&test, array.data[1] == ITEM); + DQN_UTEST_ASSERT(&test, array.size == 2); + DQN_UTEST_ASSERT(&test, array.data[0] == 1); + DQN_UTEST_ASSERT(&test, array.data[1] == ITEM); } - DQN_TESTER_TEST("Clear array") { + DQN_UTEST_TEST("Clear array") { int raw_array[] = {1}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); Dqn_FArray_Clear(&array); - DQN_TESTER_ASSERT(&test, array.size == 0); + DQN_UTEST_ASSERT(&test, array.size == 0); } } return test; } -Dqn_Tester TestIntrinsics() +Dqn_UTest TestIntrinsics() { - Dqn_Tester test = {}; + Dqn_UTest test = {}; // TODO(dqn): We don't have meaningful tests here, but since // atomics/intrinsics are implemented using macros we ensure the macro was // written properly with these tests. - DQN_TESTER_GROUP(test, "Dqn_Atomic") { - DQN_TESTER_TEST("Dqn_Atomic_AddU32") { + DQN_UTEST_GROUP(test, "Dqn_Atomic") { + DQN_UTEST_TEST("Dqn_Atomic_AddU32") { uint32_t val = 0; Dqn_Atomic_AddU32(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 1, "val: %u", val); + DQN_UTEST_ASSERTF(&test, val == 1, "val: %u", val); } - DQN_TESTER_TEST("Dqn_Atomic_AddU64") { + DQN_UTEST_TEST("Dqn_Atomic_AddU64") { uint64_t val = 0; Dqn_Atomic_AddU64(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 1, "val: %zu", val); + DQN_UTEST_ASSERTF(&test, val == 1, "val: %zu", val); } - DQN_TESTER_TEST("Dqn_Atomic_SubU32") { + DQN_UTEST_TEST("Dqn_Atomic_SubU32") { uint32_t val = 1; Dqn_Atomic_SubU32(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 0, "val: %u", val); + DQN_UTEST_ASSERTF(&test, val == 0, "val: %u", val); } - DQN_TESTER_TEST("Dqn_Atomic_SubU64") { + DQN_UTEST_TEST("Dqn_Atomic_SubU64") { uint64_t val = 1; Dqn_Atomic_SubU64(&val, 1); - DQN_TESTER_ASSERTF(&test, val == 0, "val: %zu", val); + DQN_UTEST_ASSERTF(&test, val == 0, "val: %zu", val); } - DQN_TESTER_TEST("Dqn_Atomic_SetValue32") { + DQN_UTEST_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_UTEST_ASSERTF(&test, a == b, "a: %lu, b: %lu", a, b); } - DQN_TESTER_TEST("Dqn_Atomic_SetValue64") { + DQN_UTEST_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_UTEST_ASSERTF(&test, a == b, "a: %I64i, b: %I64i", a, b); } - Dqn_Tester_Begin(&test, "Dqn_CPUClockCycle"); + Dqn_UTest_Begin(&test, "Dqn_CPUClockCycle"); Dqn_CPUClockCycle(); - Dqn_Tester_End(&test); + Dqn_UTest_End(&test); - Dqn_Tester_Begin(&test, "Dqn_CompilerReadBarrierAndCPUReadFence"); + Dqn_UTest_Begin(&test, "Dqn_CompilerReadBarrierAndCPUReadFence"); Dqn_CompilerReadBarrierAndCPUReadFence; - Dqn_Tester_End(&test); + Dqn_UTest_End(&test); - Dqn_Tester_Begin(&test, "Dqn_CompilerWriteBarrierAndCPUWriteFence"); + Dqn_UTest_Begin(&test, "Dqn_CompilerWriteBarrierAndCPUWriteFence"); Dqn_CompilerWriteBarrierAndCPUWriteFence; - Dqn_Tester_End(&test); + Dqn_UTest_End(&test); } return test; } #if defined(DQN_TEST_WITH_KECCAK) -#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") +#define DQN_UTEST_HASH_X_MACRO \ + DQN_UTEST_HASH_X_ENTRY(SHA3_224, "SHA3-224") \ + DQN_UTEST_HASH_X_ENTRY(SHA3_256, "SHA3-256") \ + DQN_UTEST_HASH_X_ENTRY(SHA3_384, "SHA3-384") \ + DQN_UTEST_HASH_X_ENTRY(SHA3_512, "SHA3-512") \ + DQN_UTEST_HASH_X_ENTRY(Keccak_224, "Keccak-224") \ + DQN_UTEST_HASH_X_ENTRY(Keccak_256, "Keccak-256") \ + DQN_UTEST_HASH_X_ENTRY(Keccak_384, "Keccak-384") \ + DQN_UTEST_HASH_X_ENTRY(Keccak_512, "Keccak-512") \ + DQN_UTEST_HASH_X_ENTRY(Count, "Keccak-512") enum Dqn_Tests__HashType { -#define DQN_TESTER_HASH_X_ENTRY(enum_val, string) Hash_##enum_val, - DQN_TESTER_HASH_X_MACRO -#undef DQN_TESTER_HASH_X_ENTRY +#define DQN_UTEST_HASH_X_ENTRY(enum_val, string) Hash_##enum_val, + DQN_UTEST_HASH_X_MACRO +#undef DQN_UTEST_HASH_X_ENTRY }; -Dqn_String8 const DQN_TESTER_HASH_STRING_[] = +Dqn_String8 const DQN_UTEST_HASH_STRING_[] = { -#define DQN_TESTER_HASH_X_ENTRY(enum_val, string) DQN_STRING8(string), - DQN_TESTER_HASH_X_MACRO -#undef DQN_TESTER_HASH_X_ENTRY +#define DQN_UTEST_HASH_X_ENTRY(enum_val, string) DQN_STRING8(string), + DQN_UTEST_HASH_X_MACRO +#undef DQN_UTEST_HASH_X_ENTRY }; -void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) +void TestKeccakDispatch_(Dqn_UTest *test, int hash_type, Dqn_String8 input) { Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); Dqn_String8 input_hex = Dqn_Hex_BytesToString8Arena(scratch.arena, input.data, input.size); @@ -815,7 +894,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes28 hash = Dqn_SHA3_224StringToBytes28(input); Dqn_KeccakBytes28 expect; FIPS202_SHA3_224(DQN_CAST(u8 *)input.data, input.size, (u8 *)expect.data); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes28Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -832,7 +911,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes32 hash = Dqn_SHA3_256StringToBytes32(input); Dqn_KeccakBytes32 expect; FIPS202_SHA3_256(DQN_CAST(u8 *)input.data, input.size, (u8 *)expect.data); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes32Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -849,7 +928,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes48 hash = Dqn_SHA3_384StringToBytes48(input); Dqn_KeccakBytes48 expect; FIPS202_SHA3_384(DQN_CAST(u8 *)input.data, input.size, (u8 *)expect.data); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes48Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -866,7 +945,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes64 hash = Dqn_SHA3_512StringToBytes64(input); Dqn_KeccakBytes64 expect; FIPS202_SHA3_512(DQN_CAST(u8 *)input.data, input.size, (u8 *)expect.data); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes64Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -883,7 +962,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes28 hash = Dqn_Keccak224StringToBytes28(input); Dqn_KeccakBytes28 expect; Keccak(1152, 448, DQN_CAST(u8 *)input.data, input.size, 0x01, (u8 *)expect.data, sizeof(expect)); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes28Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -900,7 +979,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes32 hash = Dqn_Keccak256StringToBytes32(input); Dqn_KeccakBytes32 expect; Keccak(1088, 512, DQN_CAST(u8 *)input.data, input.size, 0x01, (u8 *)expect.data, sizeof(expect)); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes32Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -917,7 +996,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes48 hash = Dqn_Keccak384StringToBytes48(input); Dqn_KeccakBytes48 expect; Keccak(832, 768, DQN_CAST(u8 *)input.data, input.size, 0x01, (u8 *)expect.data, sizeof(expect)); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes48Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -934,7 +1013,7 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) Dqn_KeccakBytes64 hash = Dqn_Keccak512StringToBytes64(input); Dqn_KeccakBytes64 expect; Keccak(576, 1024, DQN_CAST(u8 *)input.data, input.size, 0x01, (u8 *)expect.data, sizeof(expect)); - DQN_TESTER_ASSERTF(test, + DQN_UTEST_ASSERTF(test, Dqn_KeccakBytes64Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" @@ -949,9 +1028,9 @@ void TestKeccakDispatch_(Dqn_Tester *test, int hash_type, Dqn_String8 input) } } -Dqn_Tester TestKeccak() +Dqn_UTest TestKeccak() { - Dqn_Tester test = {}; + Dqn_UTest test = {}; Dqn_String8 const INPUTS[] = { DQN_STRING8("abc"), DQN_STRING8(""), @@ -960,19 +1039,19 @@ Dqn_Tester TestKeccak() "pqrstnopqrstu"), }; - DQN_TESTER_GROUP(test, "Dqn_Keccak") + DQN_UTEST_GROUP(test, "Dqn_Keccak") { 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_TESTER_HASH_STRING_[hash_type]), DQN_CAST(int)DQN_MIN(input.size, 54), input.data); + Dqn_UTest_Begin(&test, "%.*s - Input: %.*s", DQN_STRING_FMT(DQN_UTEST_HASH_STRING_[hash_type]), DQN_CAST(int)DQN_MIN(input.size, 54), input.data); TestKeccakDispatch_(&test, hash_type, input); - Dqn_Tester_End(&test); + Dqn_UTest_End(&test); } - Dqn_Tester_Begin(&test, "%.*s - Deterministic random inputs", DQN_STRING_FMT(DQN_TESTER_HASH_STRING_[hash_type])); + Dqn_UTest_Begin(&test, "%.*s - Deterministic random inputs", DQN_STRING_FMT(DQN_UTEST_HASH_STRING_[hash_type])); for (int index = 0; index < 128; index++) { char src[4096] = {}; uint32_t src_size = pcg32_boundedrand_r(&rng, sizeof(src)); @@ -983,18 +1062,18 @@ Dqn_Tester TestKeccak() Dqn_String8 input = Dqn_String8_Init(src, src_size); TestKeccakDispatch_(&test, hash_type, input); } - Dqn_Tester_End(&test); + Dqn_UTest_End(&test); } } return test; } #endif // defined(DQN_TEST_WITH_KECCAK) -Dqn_Tester TestM4() +Dqn_UTest TestM4() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_M4") { - DQN_TESTER_TEST("Simple translate and scale matrix") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_M4") { + DQN_UTEST_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); @@ -1006,7 +1085,7 @@ Dqn_Tester TestM4() {1, 2, 3, 1}, }}; - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, memcmp(result.columns, EXPECT.columns, sizeof(EXPECT)) == 0, "\nresult =\n%s\nexpected =\n%s", Dqn_M4_ColumnMajorString(result).data, @@ -1016,75 +1095,75 @@ Dqn_Tester TestM4() return test; } -Dqn_Tester TestOS() +Dqn_UTest TestOS() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_OS") { - DQN_TESTER_TEST("Generate secure RNG bytes with nullptr") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_OS") { + DQN_UTEST_TEST("Generate secure RNG bytes with nullptr") { Dqn_b32 result = Dqn_OS_SecureRNGBytes(nullptr, 1); - DQN_TESTER_ASSERT(&test, result == false); + DQN_UTEST_ASSERT(&test, result == false); } - DQN_TESTER_TEST("Generate secure RNG 32 bytes") { + DQN_UTEST_TEST("Generate secure RNG 32 bytes") { char const ZERO[32] = {}; char buf[32] = {}; bool result = Dqn_OS_SecureRNGBytes(buf, DQN_ARRAY_UCOUNT(buf)); - DQN_TESTER_ASSERT(&test, result); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(buf, ZERO, DQN_ARRAY_UCOUNT(buf)) != 0); + DQN_UTEST_ASSERT(&test, result); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(buf, ZERO, DQN_ARRAY_UCOUNT(buf)) != 0); } - DQN_TESTER_TEST("Generate secure RNG 0 bytes") { + DQN_UTEST_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_UTEST_ASSERT(&test, result); + DQN_UTEST_ASSERT(&test, buf[0] == 'Z'); } - DQN_TESTER_TEST("Query executable directory") { + DQN_UTEST_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_UTEST_ASSERT(&test, Dqn_String8_IsValid(result)); + DQN_UTEST_ASSERTF(&test, Dqn_Fs_DirExists(result), "result(%zu): %.*s", result.size, DQN_STRING_FMT(result)); } - DQN_TESTER_TEST("Dqn_OS_PerfCounterNow") { + DQN_UTEST_TEST("Dqn_OS_PerfCounterNow") { uint64_t result = Dqn_OS_PerfCounterNow(); - DQN_TESTER_ASSERT(&test, result != 0); + DQN_UTEST_ASSERT(&test, result != 0); } - DQN_TESTER_TEST("Consecutive ticks are ordered") { + DQN_UTEST_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_UTEST_ASSERTF(&test, b >= a, "a: %zu, b: %zu", a, b); } - DQN_TESTER_TEST("Ticks to time are a correct order of magnitude") { + DQN_UTEST_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_UTEST_ASSERTF(&test, s <= ms, "s: %f, ms: %f", s, ms); + DQN_UTEST_ASSERTF(&test, ms <= micro_s, "ms: %f, micro_s: %f", ms, micro_s); + DQN_UTEST_ASSERTF(&test, micro_s <= ns, "micro_s: %f, ns: %f", micro_s, ns); } } return test; } -Dqn_Tester TestRect() +Dqn_UTest TestRect() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_Rect") { - DQN_TESTER_TEST("No intersection") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_Rect") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 0 && ab.min.y == 0 && ab.max.x == 0 && ab.max.y == 0, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1093,12 +1172,12 @@ Dqn_Tester TestRect() ab.max.y); } - DQN_TESTER_TEST("A's min intersects B") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 50 && ab.min.y == 50 && ab.max.x == 100 && ab.max.y == 100, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1107,12 +1186,12 @@ Dqn_Tester TestRect() ab.max.y); } - DQN_TESTER_TEST("B's min intersects A") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 50 && ab.min.y == 50 && ab.max.x == 100 && ab.max.y == 100, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1121,12 +1200,12 @@ Dqn_Tester TestRect() ab.max.y); } - DQN_TESTER_TEST("A's max intersects B") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 0 && ab.min.y == 0 && ab.max.x == 50 && ab.max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1135,12 +1214,12 @@ Dqn_Tester TestRect() ab.max.y); } - DQN_TESTER_TEST("B's max intersects A") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 0 && ab.min.y == 0 && ab.max.x == 50 && ab.max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1150,12 +1229,12 @@ Dqn_Tester TestRect() } - DQN_TESTER_TEST("B contains A") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 25 && ab.min.y == 25 && ab.max.x == 50 && ab.max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1164,12 +1243,12 @@ Dqn_Tester TestRect() ab.max.y); } - DQN_TESTER_TEST("A contains B") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 25 && ab.min.y == 25 && ab.max.x == 50 && ab.max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1178,12 +1257,12 @@ Dqn_Tester TestRect() ab.max.y); } - DQN_TESTER_TEST("A equals B") { + DQN_UTEST_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); - DQN_TESTER_ASSERTF(&test, + DQN_UTEST_ASSERTF(&test, ab.min.x == 0 && ab.min.y == 0 && ab.max.x == 100 && ab.max.y == 100, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.min.x, @@ -1195,104 +1274,104 @@ Dqn_Tester TestRect() return test; } -Dqn_Tester TestString8() +Dqn_UTest TestString8() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_String8") { - DQN_TESTER_TEST("Initialise with string literal w/ macro") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_String8") { + DQN_UTEST_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_UTEST_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); + DQN_UTEST_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); + DQN_UTEST_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); } - DQN_TESTER_TEST("Initialise with format string") { + DQN_UTEST_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_UTEST_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); + DQN_UTEST_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); + DQN_UTEST_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); + DQN_UTEST_ASSERTF(&test, string.data[2] == 0, "string[2]: %c", string.data[2]); } - DQN_TESTER_TEST("Copy string") { + DQN_UTEST_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_UTEST_ASSERTF(&test, copy.size == 2, "size: %I64d", copy.size); + DQN_UTEST_ASSERTF(&test, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); + DQN_UTEST_ASSERTF(&test, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); + DQN_UTEST_ASSERTF(&test, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); } - DQN_TESTER_TEST("Trim whitespace around string") { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(string, DQN_STRING8("AB")), "[string=%.*s]", DQN_STRING_FMT(string)); } - DQN_TESTER_TEST("Allocate string from arena") { + DQN_UTEST_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); + DQN_UTEST_ASSERTF(&test, string.size == 2, "size: %I64d", string.size); } // NOTE: Dqn_CString8_Trim[Prefix/Suffix] // --------------------------------------------------------------------------------------------- - DQN_TESTER_TEST("Trim prefix with matching prefix") { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(result, DQN_STRING8("abc")), "%.*s", DQN_STRING_FMT(result)); } - DQN_TESTER_TEST("Trim prefix with non matching prefix") { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(result, input), "%.*s", DQN_STRING_FMT(result)); } - DQN_TESTER_TEST("Trim suffix with matching suffix") { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(result, DQN_STRING8("nft/")), "%.*s", DQN_STRING_FMT(result)); } - DQN_TESTER_TEST("Trim suffix with non matching suffix") { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(result, input), "%.*s", DQN_STRING_FMT(result)); } // NOTE: Dqn_String8_IsAllDigits // --------------------------------------------------------------------------------------------- - DQN_TESTER_TEST("Is all digits fails on non-digit string") { + DQN_UTEST_TEST("Is all digits fails on non-digit string") { Dqn_b32 result = Dqn_String8_IsAll(DQN_STRING8("@123string"), Dqn_String8IsAll_Digits); - DQN_TESTER_ASSERT(&test, result == false); + DQN_UTEST_ASSERT(&test, result == false); } - DQN_TESTER_TEST("Is all digits fails on nullptr") { + DQN_UTEST_TEST("Is all digits fails on nullptr") { Dqn_b32 result = Dqn_String8_IsAll(Dqn_String8_Init(nullptr, 0), Dqn_String8IsAll_Digits); - DQN_TESTER_ASSERT(&test, result == false); + DQN_UTEST_ASSERT(&test, result == false); } - DQN_TESTER_TEST("Is all digits fails on nullptr w/ size") { + DQN_UTEST_TEST("Is all digits fails on nullptr w/ size") { Dqn_b32 result = Dqn_String8_IsAll(Dqn_String8_Init(nullptr, 1), Dqn_String8IsAll_Digits); - DQN_TESTER_ASSERT(&test, result == false); + DQN_UTEST_ASSERT(&test, result == false); } - DQN_TESTER_TEST("Is all digits succeeds on string w/ 0 size") { + DQN_UTEST_TEST("Is all digits succeeds on string w/ 0 size") { char const buf[] = "@123string"; Dqn_b32 result = Dqn_String8_IsAll(Dqn_String8_Init(buf, 0), Dqn_String8IsAll_Digits); - DQN_TESTER_ASSERT(&test, result); + DQN_UTEST_ASSERT(&test, result); } - DQN_TESTER_TEST("Is all digits success") { + DQN_UTEST_TEST("Is all digits success") { Dqn_b32 result = Dqn_String8_IsAll(DQN_STRING8("23"), Dqn_String8IsAll_Digits); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == true); + DQN_UTEST_ASSERT(&test, DQN_CAST(bool)result == true); } - DQN_TESTER_TEST("Is all digits fails on whitespace") { + DQN_UTEST_TEST("Is all digits fails on whitespace") { Dqn_b32 result = Dqn_String8_IsAll(DQN_STRING8("23 "), Dqn_String8IsAll_Digits); - DQN_TESTER_ASSERT(&test, DQN_CAST(bool)result == false); + DQN_UTEST_ASSERT(&test, DQN_CAST(bool)result == false); } // NOTE: Dqn_String8_BinarySplit @@ -1302,288 +1381,288 @@ Dqn_Tester TestString8() char delimiter = '/'; Dqn_String8 input = DQN_STRING8("abcdef"); - DQN_TESTER_TEST(TEST_FMT, input.data, delimiter) { + DQN_UTEST_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("abcdef")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); - DQN_TESTER_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abcdef")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); } input = DQN_STRING8("abc/def"); - DQN_TESTER_TEST(TEST_FMT, input.data, delimiter) { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abc")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("def")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); } input = DQN_STRING8("/abcdef"); - DQN_TESTER_TEST(TEST_FMT, input.data, delimiter) { + DQN_UTEST_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_UTEST_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); + DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("abcdef")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); } } // NOTE: Dqn_String8_ToI64 // ========================================================================================= - DQN_TESTER_TEST("To I64: Convert null string") { + DQN_UTEST_TEST("To I64: Convert null string") { int64_t result = Dqn_String8_ToI64(Dqn_String8_Init(nullptr, 5), 0); - DQN_TESTER_ASSERT(&test, result == 0); + DQN_UTEST_ASSERT(&test, result == 0); } - DQN_TESTER_TEST("To I64: Convert empty string") { + DQN_UTEST_TEST("To I64: Convert empty string") { int64_t result = Dqn_String8_ToI64(DQN_STRING8(""), 0); - DQN_TESTER_ASSERT(&test, result == 0); + DQN_UTEST_ASSERT(&test, result == 0); } - DQN_TESTER_TEST("To I64: Convert \"1\"") { + DQN_UTEST_TEST("To I64: Convert \"1\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("1"), 0); - DQN_TESTER_ASSERT(&test, result == 1); + DQN_UTEST_ASSERT(&test, result == 1); } - DQN_TESTER_TEST("To I64: Convert \"-0\"") { + DQN_UTEST_TEST("To I64: Convert \"-0\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("-0"), 0); - DQN_TESTER_ASSERT(&test, result == 0); + DQN_UTEST_ASSERT(&test, result == 0); } - DQN_TESTER_TEST("To I64: Convert \"-1\"") { + DQN_UTEST_TEST("To I64: Convert \"-1\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("-1"), 0); - DQN_TESTER_ASSERT(&test, result == -1); + DQN_UTEST_ASSERT(&test, result == -1); } - DQN_TESTER_TEST("To I64: Convert \"1.2\"") { + DQN_UTEST_TEST("To I64: Convert \"1.2\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("1.2"), 0); - DQN_TESTER_ASSERT(&test, result == 1); + DQN_UTEST_ASSERT(&test, result == 1); } - DQN_TESTER_TEST("To I64: Convert \"1,234\"") { + DQN_UTEST_TEST("To I64: Convert \"1,234\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("1,234"), ','); - DQN_TESTER_ASSERT(&test, result == 1234); + DQN_UTEST_ASSERT(&test, result == 1234); } - DQN_TESTER_TEST("To I64: Convert \"1,2\"") { + DQN_UTEST_TEST("To I64: Convert \"1,2\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("1,2"), ','); - DQN_TESTER_ASSERT(&test, result == 12); + DQN_UTEST_ASSERT(&test, result == 12); } - DQN_TESTER_TEST("To I64: Convert \"12a3\"") { + DQN_UTEST_TEST("To I64: Convert \"12a3\"") { int64_t result = Dqn_String8_ToI64(DQN_STRING8("12a3"), 0); - DQN_TESTER_ASSERT(&test, result == 12); + DQN_UTEST_ASSERT(&test, result == 12); } // NOTE: Dqn_String8_ToU64 // --------------------------------------------------------------------------------------------- - DQN_TESTER_TEST("To U64: Convert nullptr") { + DQN_UTEST_TEST("To U64: Convert nullptr") { uint64_t result = Dqn_String8_ToU64(Dqn_String8_Init(nullptr, 5), 0); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert empty string") { + DQN_UTEST_TEST("To U64: Convert empty string") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8(""), 0); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"1\"") { + DQN_UTEST_TEST("To U64: Convert \"1\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("1"), 0); - DQN_TESTER_ASSERTF(&test, result == 1, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 1, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"-0\"") { + DQN_UTEST_TEST("To U64: Convert \"-0\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("-0"), 0); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"-1\"") { + DQN_UTEST_TEST("To U64: Convert \"-1\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("-1"), 0); - DQN_TESTER_ASSERTF(&test, result == 0, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 0, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"1.2\"") { + DQN_UTEST_TEST("To U64: Convert \"1.2\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("1.2"), 0); - DQN_TESTER_ASSERTF(&test, result == 1, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 1, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"1,234\"") { + DQN_UTEST_TEST("To U64: Convert \"1,234\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("1,234"), ','); - DQN_TESTER_ASSERTF(&test, result == 1234, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 1234, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"1,2\"") { + DQN_UTEST_TEST("To U64: Convert \"1,2\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("1,2"), ','); - DQN_TESTER_ASSERTF(&test, result == 12, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 12, "result: %zu", result); } - DQN_TESTER_TEST("To U64: Convert \"12a3\"") { + DQN_UTEST_TEST("To U64: Convert \"12a3\"") { uint64_t result = Dqn_String8_ToU64(DQN_STRING8("12a3"), 0); - DQN_TESTER_ASSERTF(&test, result == 12, "result: %zu", result); + DQN_UTEST_ASSERTF(&test, result == 12, "result: %zu", result); } // NOTE: Dqn_String8_Find // ========================================================================================= - DQN_TESTER_TEST("Find: String (char) is not in buffer") { + DQN_UTEST_TEST("Find: String (char) is not in buffer") { Dqn_String8 buf = DQN_STRING8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); Dqn_String8 find = DQN_STRING8("2"); Dqn_String8FindResult result = Dqn_String8_Find(buf, find, 0); - DQN_TESTER_ASSERT(&test, !result.found); - DQN_TESTER_ASSERT(&test, result.offset == 0); - DQN_TESTER_ASSERT(&test, result.string.data == nullptr); - DQN_TESTER_ASSERT(&test, result.string.size == 0); + DQN_UTEST_ASSERT(&test, !result.found); + DQN_UTEST_ASSERT(&test, result.offset == 0); + DQN_UTEST_ASSERT(&test, result.string.data == nullptr); + DQN_UTEST_ASSERT(&test, result.string.size == 0); } - DQN_TESTER_TEST("Find: String (char) is in buffer") { + DQN_UTEST_TEST("Find: String (char) is in buffer") { Dqn_String8 buf = DQN_STRING8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); Dqn_String8 find = DQN_STRING8("6"); Dqn_String8FindResult result = Dqn_String8_Find(buf, find, 0); - DQN_TESTER_ASSERT(&test, result.found); - DQN_TESTER_ASSERT(&test, result.offset == 2); - DQN_TESTER_ASSERT(&test, result.string.data[0] == '6'); + DQN_UTEST_ASSERT(&test, result.found); + DQN_UTEST_ASSERT(&test, result.offset == 2); + DQN_UTEST_ASSERT(&test, result.string.data[0] == '6'); } // NOTE: Dqn_String8_FileNameFromPath // ========================================================================================= - DQN_TESTER_TEST("File name from Windows path") { + DQN_UTEST_TEST("File name from Windows path") { Dqn_String8 buf = DQN_STRING8("C:\\ABC\\test.exe"); Dqn_String8 result = Dqn_String8_FileNameFromPath(buf); - DQN_TESTER_ASSERTF(&test, result == DQN_STRING8("test.exe"), "%.*s", DQN_STRING_FMT(result)); + DQN_UTEST_ASSERTF(&test, result == DQN_STRING8("test.exe"), "%.*s", DQN_STRING_FMT(result)); } - DQN_TESTER_TEST("File name from Linux path") { + DQN_UTEST_TEST("File name from Linux path") { Dqn_String8 buf = DQN_STRING8("/ABC/test.exe"); Dqn_String8 result = Dqn_String8_FileNameFromPath(buf); - DQN_TESTER_ASSERTF(&test, result == DQN_STRING8("test.exe"), "%.*s", DQN_STRING_FMT(result)); + DQN_UTEST_ASSERTF(&test, result == DQN_STRING8("test.exe"), "%.*s", DQN_STRING_FMT(result)); } // NOTE: Dqn_String8_TrimPrefix // ========================================================================================= - DQN_TESTER_TEST("Trim prefix") { + DQN_UTEST_TEST("Trim prefix") { Dqn_String8 prefix = DQN_STRING8("@123"); Dqn_String8 buf = DQN_STRING8("@123string"); Dqn_String8 result = Dqn_String8_TrimPrefix(buf, prefix, Dqn_String8EqCase_Sensitive); - DQN_TESTER_ASSERT(&test, result == DQN_STRING8("string")); + DQN_UTEST_ASSERT(&test, result == DQN_STRING8("string")); } } return test; } -Dqn_Tester TestTicketMutex() +Dqn_UTest TestTicketMutex() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_TicketMutex") { - DQN_TESTER_TEST("Ticket mutex start and stop") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_TicketMutex") { + DQN_UTEST_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_UTEST_ASSERT(&test, mutex.ticket == mutex.serving); } - DQN_TESTER_TEST("Ticket mutex start and stop w/ advanced API") { + DQN_UTEST_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_UTEST_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_b) == false); + DQN_UTEST_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_UTEST_ASSERT(&test, mutex.ticket == mutex.serving); + DQN_UTEST_ASSERT(&test, mutex.ticket == ticket_b + 1); } } return test; } -Dqn_Tester TestVArray() +Dqn_UTest TestVArray() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_VArray") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_VArray") { { Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); Dqn_VArray array = Dqn_VArray_InitByteSize(scratch.arena, DQN_KILOBYTES(64)); - DQN_TESTER_TEST("Test adding an array of items to the array") { + DQN_UTEST_TEST("Test adding an array of items to the array") { uint32_t array_literal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; Dqn_VArray_Add(&array, array_literal, DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test stable erase, 1 item, the '2' value from the array") { + DQN_UTEST_TEST("Test stable erase, 1 item, the '2' value from the array") { Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, Dqn_VArrayErase_Stable); uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test unstable erase, 1 item, the '1' value from the array") { + DQN_UTEST_TEST("Test unstable erase, 1 item, the '1' value from the array") { Dqn_VArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, Dqn_VArrayErase_Unstable); uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } Dqn_VArrayErase erase_enums[] = {Dqn_VArrayErase_Stable, Dqn_VArrayErase_Unstable}; - DQN_TESTER_TEST("Test un/stable erase, OOB") { + DQN_UTEST_TEST("Test un/stable erase, OOB") { for (Dqn_VArrayErase erase : erase_enums) { uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; Dqn_VArray_EraseRange(&array, DQN_ARRAY_UCOUNT(array_literal) /*begin_index*/, DQN_ARRAY_UCOUNT(array_literal) + 100 /*count*/, erase); - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } } - DQN_TESTER_TEST("Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array") { + DQN_UTEST_TEST("Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array") { Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, Dqn_VArrayErase_Stable); uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array") { + DQN_UTEST_TEST("Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array") { Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, Dqn_VArrayErase_Unstable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array") { + DQN_UTEST_TEST("Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array") { Dqn_VArray_EraseRange(&array, 8 /*begin_index*/, 3 /*count*/, Dqn_VArrayErase_Stable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array") { + DQN_UTEST_TEST("Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array") { Dqn_VArray_EraseRange(&array, 6 /*begin_index*/, 3 /*count*/, Dqn_VArrayErase_Unstable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test stable erase -overflow OOB, erasing the '0, 13' value from the array") { + DQN_UTEST_TEST("Test stable erase -overflow OOB, erasing the '0, 13' value from the array") { Dqn_VArray_EraseRange(&array, 1 /*begin_index*/, -DQN_ISIZE_MAX /*count*/, Dqn_VArrayErase_Stable); uint32_t array_literal[] = {14, 6, 7, 8}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_TESTER_TEST("Test unstable erase +overflow OOB, erasing the '7, 8' value from the array") { + DQN_UTEST_TEST("Test unstable erase +overflow OOB, erasing the '7, 8' value from the array") { Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, DQN_ISIZE_MAX /*count*/, Dqn_VArrayErase_Unstable); uint32_t array_literal[] = {14, 6}; - DQN_TESTER_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } } - DQN_TESTER_TEST("Array of unaligned objects are contiguously laid out in memory") { + DQN_UTEST_TEST("Array of unaligned objects are contiguously laid out in memory") { // NOTE: Since we allocate from a virtual memory block, each time // we request memory from the block we can demand some alignment // on the returned pointer from the memory block. If there's @@ -1614,54 +1693,54 @@ Dqn_Tester TestVArray() UnalignedObject *make_item_b = Dqn_VArray_Make(&array, 1, Dqn_ZeroMem_Yes); DQN_MEMSET(make_item_a->data, 'a', sizeof(make_item_a->data)); DQN_MEMSET(make_item_b->data, 'b', sizeof(make_item_b->data)); - DQN_TESTER_ASSERT(&test, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); + DQN_UTEST_ASSERT(&test, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); // NOTE: Verify that accessing the items from the data array yield // the same object. - DQN_TESTER_ASSERT(&test, array.size == 2); + DQN_UTEST_ASSERT(&test, array.size == 2); UnalignedObject *data_item_a = array.data + 0; UnalignedObject *data_item_b = array.data + 1; - DQN_TESTER_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(data_item_a + 1)); - DQN_TESTER_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(make_item_a + 1)); - DQN_TESTER_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)make_item_b); + DQN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(data_item_a + 1)); + DQN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(make_item_a + 1)); + DQN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)make_item_b); for (Dqn_usize i = 0; i < sizeof(data_item_a->data); i++) { - DQN_TESTER_ASSERT(&test, data_item_a->data[i] == 'a'); + DQN_UTEST_ASSERT(&test, data_item_a->data[i] == 'a'); } for (Dqn_usize i = 0; i < sizeof(data_item_b->data); i++) { - DQN_TESTER_ASSERT(&test, data_item_b->data[i] == 'b'); + DQN_UTEST_ASSERT(&test, data_item_b->data[i] == 'b'); } } } return test; } -Dqn_Tester TestWin() +Dqn_UTest TestWin() { - Dqn_Tester test = {}; - DQN_TESTER_GROUP(test, "Dqn_Win") { - DQN_TESTER_TEST("String8 to String16 size required") { + Dqn_UTest test = {}; + DQN_UTEST_GROUP(test, "Dqn_Win") { + DQN_UTEST_TEST("String8 to String16 size required") { int result = Dqn_Win_String8ToCString16(DQN_STRING8("a"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 1, "Size returned: %d. This size should not include the null-terminator", result); + DQN_UTEST_ASSERTF(&test, result == 1, "Size returned: %d. This size should not include the null-terminator", result); } - DQN_TESTER_TEST("String16 to String8 size required") { + DQN_UTEST_TEST("String16 to String8 size required") { int result = Dqn_Win_String16ToCString8(DQN_STRING16(L"a"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 1, "Size returned: %d. This size should not include the null-terminator", result); + DQN_UTEST_ASSERTF(&test, result == 1, "Size returned: %d. This size should not include the null-terminator", result); } - DQN_TESTER_TEST("String8 to String16 size required") { + DQN_UTEST_TEST("String8 to String16 size required") { int result = Dqn_Win_String8ToCString16(DQN_STRING8("String"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 6, "Size returned: %d. This size should not include the null-terminator", result); + DQN_UTEST_ASSERTF(&test, result == 6, "Size returned: %d. This size should not include the null-terminator", result); } - DQN_TESTER_TEST("String16 to String8 size required") { + DQN_UTEST_TEST("String16 to String8 size required") { int result = Dqn_Win_String16ToCString8(DQN_STRING16(L"String"), nullptr, 0); - DQN_TESTER_ASSERTF(&test, result == 6, "Size returned: %d. This size should not include the null-terminator", result); + DQN_UTEST_ASSERTF(&test, result == 6, "Size returned: %d. This size should not include the null-terminator", result); } - DQN_TESTER_TEST("String8 to String16") { + DQN_UTEST_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); @@ -1673,12 +1752,12 @@ Dqn_Tester TestWin() int size_returned = Dqn_Win_String8ToCString16(INPUT, string, size_required + 1); 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_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", size_returned, DQN_ARRAY_UCOUNT(EXPECTED) - 1); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); + DQN_UTEST_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); + DQN_UTEST_ASSERTF(&test, size_returned == DQN_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", size_returned, DQN_ARRAY_UCOUNT(EXPECTED) - 1); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); } - DQN_TESTER_TEST("String16 to String8: No null-terminate") { + DQN_UTEST_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); @@ -1690,18 +1769,27 @@ Dqn_Tester TestWin() int size_returned = Dqn_Win_String16ToCString8(INPUT, string, size_required + 1); 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_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", size_returned, DQN_ARRAY_UCOUNT(EXPECTED) - 1); - DQN_TESTER_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); + DQN_UTEST_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); + DQN_UTEST_ASSERTF(&test, size_returned == DQN_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", size_returned, DQN_ARRAY_UCOUNT(EXPECTED) - 1); + DQN_UTEST_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); } } return test; } +void CustomLogProc(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list args) +{ + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 log = Dqn_Log_MakeString(scratch.allocator, true /*colour*/, type, log_type, call_site, fmt, args); + DQN_UTEST_LOG("%.*s", DQN_STRING_FMT(log)); +} + void TestRunSuite() { - Dqn_Library_Init(nullptr); - Dqn_Tester tests[] + Dqn_Library *dqn_library = Dqn_Library_Init(nullptr); + dqn_library->log_callback = CustomLogProc; + + Dqn_UTest tests[] = { TestArena(), TestBin(), @@ -1725,7 +1813,7 @@ void TestRunSuite() int total_tests = 0; int total_good_tests = 0; - for (Dqn_Tester &test : tests) { + for (Dqn_UTest &test : tests) { total_tests += test.num_tests_in_group; total_good_tests += test.num_tests_ok_in_group; } diff --git a/dqn_utest.h b/dqn_utest.h new file mode 100644 index 0000000..138f82d --- /dev/null +++ b/dqn_utest.h @@ -0,0 +1,215 @@ +#if !defined(DQN_UTEST_H) +#define DQN_UTEST_H +// +// NOTE: Overview +// ----------------------------------------------------------------------------- +// A super minimal testing framework, most of the logic here is the pretty +// printing of test results. + +// NOTE: Configuration +// ----------------------------------------------------------------------------- +// #define DQN_UTEST_IMPLEMENTATION +// Define this in one and only one C++ file to enable the implementation +// code of the header file. This will also automatically enable the JSMN +// implementation. +// +// #define DQN_UTEST_RESULT_LPAD +// Define this to a number to specify how much to pad the output of the test +// result line before the test result is printed. +// +// #define DQN_UTEST_RESULT_PAD_CHAR +// Define this to a character to specify the default character to use for +// padding. By default this is '.' +// +// #define DQN_UTEST_SPACING +// Define this to a number to specify the number of spaces between the group +// declaration and the test output in the group. +// +// #define DQN_UTEST_BAD_COLOR +// Define this to a terminal color code to specify what color errors will be +// presented as. +// +// #define DQN_UTEST_GOOD_COLOR +// Define this to a terminal color code to specify what color sucess will be +// presented as. + +// NOTE: Macros +// ----------------------------------------------------------------------------- +#include +#include +#include + +#if !defined(DQN_UTEST_RESULT_LPAD) + #define DQN_UTEST_RESULT_LPAD 90 +#endif + +#if !defined(DQN_UTEST_RESULT_PAD_CHAR) + #define DQN_UTEST_RESULT_PAD_CHAR '.' +#endif + +#if !defined(DQN_UTEST_SPACING) + #define DQN_UTEST_SPACING 2 +#endif + +#if !defined(DQN_UTEST_BAD_COLOR) + #define DQN_UTEST_BAD_COLOR "\x1b[31m" +#endif + +#if !defined(DQN_UTEST_GOOD_COLOR) + #define DQN_UTEST_GOOD_COLOR "\x1b[32m" +#endif + +#define DQN_UTEST_COLOR_RESET "\x1b[0m" + +#define DQN_UTEST_GROUP(test, fmt, ...) \ + for (Dqn_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \ + test_var_ != nullptr; \ + Dqn_UTest_PrintStats(&test), test_var_ = nullptr) + +#define DQN_UTEST_TEST(fmt, ...) \ + for (int dummy_ = (Dqn_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \ + (void)dummy_, test_var_->state == Dqn_UTestState_TestBegun; \ + Dqn_UTest_End(test_var_)) + +#define DQN_UTEST_ASSERTF(test, expr, fmt, ...) \ + DQN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__) + +#define DQN_UTEST_ASSERT(test, expr) \ + DQN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr)) + +// TODO: Fix the logs. They print before the tests, we should accumulate logs +// per test, then, dump them on test on. But to do this nicely without crappy +// mem management we need to implement an arena. +#define DQN_UTEST_LOG(fmt, ...) \ + fprintf(stdout, "%*s" fmt "\n", DQN_UTEST_SPACING * 2, "", ##__VA_ARGS__) + +#define DQN_UTEST_ASSERTF_AT(test, file, line, expr, fmt, ...) \ + do { \ + if (!(expr)) { \ + (test)->state = Dqn_UTestState_TestFailed; \ + fprintf(stderr, \ + "%*sAssertion Triggered\n" \ + "%*sFile: %s:%d\n" \ + "%*sExpression: [" #expr "]\n" \ + "%*sReason: " fmt "\n", \ + DQN_UTEST_SPACING * 2, \ + "", \ + DQN_UTEST_SPACING * 3, \ + "", \ + file, \ + line, \ + DQN_UTEST_SPACING * 3, \ + "", \ + DQN_UTEST_SPACING * 3, \ + "", \ + ##__VA_ARGS__); \ + } \ + } while (0) + +#define DQN_UTEST_ASSERT_AT(test, file, line, expr) \ + do { \ + if (!(expr)) { \ + (test)->state = Dqn_UTestState_TestFailed; \ + fprintf(stderr, \ + "%*sFile: %s:%d\n" \ + "%*sExpression: [" #expr "]\n", \ + DQN_UTEST_SPACING * 2, \ + "", \ + file, \ + line, \ + DQN_UTEST_SPACING * 2, \ + ""); \ + } \ + } while (0) + +// NOTE: Header +// ----------------------------------------------------------------------------- +typedef enum Dqn_UTestState { + Dqn_UTestState_Nil, + Dqn_UTestState_TestBegun, + Dqn_UTestState_TestFailed, +} Dqn_UTestState; + +typedef struct Dqn_UTest { + int num_tests_in_group; + int num_tests_ok_in_group; + Dqn_UTestState state; + bool finished; + char name[1024]; + size_t name_size; +} Dqn_UTest; + +void Dqn_UTest_PrintStats(Dqn_UTest *test); +void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args); +void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...); +void Dqn_UTest_End(Dqn_UTest *test); + +// NOTE: Implementation +// ----------------------------------------------------------------------------- +#if defined(DQN_UTEST_IMPLEMENTATION) +void Dqn_UTest_PrintStats(Dqn_UTest *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_UTEST_COLOR_RESET, + all_clear ? DQN_UTEST_GOOD_COLOR : DQN_UTEST_BAD_COLOR, + test->num_tests_ok_in_group, + test->num_tests_in_group, + all_clear ? "OK" : "FAILED"); +} + +void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args) +{ + assert(test->state == Dqn_UTestState_Nil && + "Nesting a unit test within another unit test is not allowed, ensure" + "the first test has finished by calling Dqn_UTest_End"); + + test->num_tests_in_group++; + test->state = Dqn_UTestState_TestBegun; + + test->name_size = 0; + { + va_list args_copy; + va_copy(args_copy, args); + test->name_size = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + } + + assert(test->name_size < sizeof(test->name)); + vsnprintf(test->name, sizeof(test->name), fmt, args); +} + +void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_UTest_BeginV(test, fmt, args); + va_end(args); +} + +void Dqn_UTest_End(Dqn_UTest *test) +{ + assert(test->state != Dqn_UTestState_Nil && "Test was marked as ended but a test was never commenced using Dqn_UTest_Begin"); + int pad_size = DQN_UTEST_RESULT_LPAD - (DQN_UTEST_SPACING + test->name_size); + if (pad_size < 0) + pad_size = 0; + + char pad_buffer[DQN_UTEST_RESULT_LPAD] = {}; + memset(pad_buffer, DQN_UTEST_RESULT_PAD_CHAR, pad_size); + + printf("%*s%.*s%.*s", DQN_UTEST_SPACING, "", (int)test->name_size, test->name, pad_size, pad_buffer); + if (test->state == Dqn_UTestState_TestFailed) { + printf(DQN_UTEST_BAD_COLOR " FAILED"); + } else { + printf(DQN_UTEST_GOOD_COLOR " OK"); + test->num_tests_ok_in_group++; + } + printf(DQN_UTEST_COLOR_RESET "\n"); + test->state = Dqn_UTestState_Nil; +} +#endif // DQN_UTEST_IMPLEMENTATION +#endif // DQN_UTEST_H