diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index 7494131..1997c89 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -37,7 +37,9 @@ cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp REM COMPILE AND RUN TESTS cl %CommonCompilerFlags% %ProjectDevPath%\src\tests\sanity_tests.cpp /Fesanity_tests.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib +ECHO SANITY TESTS BEGIN sanity_tests.exe +ECHO SANITY TESTS END popd diff --git a/src/tests/memory_arena_tests.cpp b/src/tests/memory_arena_tests.cpp new file mode 100644 index 0000000..d52623a --- /dev/null +++ b/src/tests/memory_arena_tests.cpp @@ -0,0 +1,184 @@ +#include "../app/platform_win32/win32_foldhaus_memory.h" + +internal u32 +TESTNextRandom(u32* LastRandomValue) +{ + u32 Result = *LastRandomValue; + Result ^= Result << 13; + Result ^= Result >> 17; + Result ^= Result << 5; + *LastRandomValue = Result; + return Result; +} + +internal void +MemoryArenaTests() +{ + Test("Allocator") + { + gs_allocator Allocator = CreateAllocator(Win32Alloc, Win32Free); + + u8* Data = AllocatorAllocArray(Allocator, u8, 4096); + for (int i = 0; i < 4096; i++) Data[i] = (i % MaxU8); + bool Success = true; + for (int i = 0; i < 4096; i++) Success &= (Data[i] == (i % MaxU8)); + TestResult(Success); + + AllocatorFreeArray(Allocator, Data, u8, 4096); + // idk how to test free + } + + Test("Memory Cursor") + { + gs_allocator A = CreateAllocator(Win32Alloc, Win32Free); + + u64 Size = 4096; + gs_data D = AllocatorAlloc(A, Size); + gs_memory_cursor C = CreateMemoryCursor(D); + + u64 RoomLeft = CursorRoomLeft(C); + TestResult(RoomLeft == Size); + + TestResult(CursorHasRoom(C, 2048)); + TestResult(CursorHasRoom(C, Size)); + TestResult(!CursorHasRoom(C, Size + 1)); + + for (u64 i = 0; i < 2048; i++) + { + u8* Byte = PushSizeOnCursor(&C, 1).Memory; + *Byte = (u8)(i % 256); + } + RoomLeft = CursorRoomLeft(C); + TestResult(RoomLeft == (Size - 2048)); + + PopSizeOnCursor(&C, 2048); + TestResult(C.Position == 0); + + bool Success = true; + for (u64 i = 0; i < 2048; i++) + { + u8* Byte = PushSizeOnCursor(&C, 1).Memory; + Success &= *Byte == (u8)(i % 256); + } + TestResult(Success); + + AllocatorFree(A, D.Memory, D.Size); + } + + Test("Memory Arena") + { + gs_allocator Al = CreateAllocator(Win32Alloc, Win32Free); + gs_memory_arena A = CreateMemoryArena(Al, "test", 128, 4); + + // NOTE(PS): We loop through this block 3 times + // 1. Make sure the arena works out of the box + // 2. Make sure the arena works the same way after clearing + // 3. Make sure the arena works the same way after freeing + for (int i = 0; i < 3; i++) + { + gs_data D0 = PushSize_(&A, 32, FileNameAndLineNumberString); + TestResult(D0.Size == 32); + + // NOTE(PS): This should still result in 32 bytes + // because its going to align the Cursor after + // it allocates to a multiple of 4 bytes + gs_data D1 = PushSize_(&A, 30, FileNameAndLineNumberString); + TestResult(D1.Size == 32); + + // NOTE(PS): Allocating bigger than the size remaining + // in the current cursor + gs_data D2 = PushSize_(&A, 128, FileNameAndLineNumberString); + TestResult(D2.Size == 128); + TestResult(A.CursorsCount != 1); + + // NOTE(PS): Because there is still room in cursor + // 0, the head of this gs_data should be one byte + // past the end of D1 + gs_data D3 = PushSize_(&A, 32, FileNameAndLineNumberString); + TestResult(D3.Memory == D1.Memory + D1.Size); + + if (i == 0) + { + ClearArena(&A); + } else if (i == 1) { + FreeMemoryArena(&A); + } + } + + FreeMemoryArena(&A); + } + + Test("Memory Arena: Push") + { + gs_allocator Al = CreateAllocator(Win32Alloc, Win32Free); + gs_memory_arena A = CreateMemoryArena(Al, "test", 128, 4); + + // NOTE(PS): This makes sure that the Arena is moving its next allocation + // pointer forward the appropriate amount after each allocation. If it isnt' + // then Array1 should be overlapping with Array0 in the event that the arena + // doesn't push the pointer forward enough + u32* Array0 = PushArray(&A, u32, 32); + u32* Array1 = PushArray(&A, u32, 32); + + for (u32 i = 0; i < 32; i++) + { + Array0[i] = i; + Array1[i] = i * 4; + } + + bool Success = true; + for (u32 i = 0; i < 32; i++) + { + Success &= Array0[i] == i && Array1[i] == i * 4; + } + TestResult(Success); + + FreeArena(&A); + } + + int FreeCount = 0; + int ClearCount = 0; + + Test("Memory Arena: Stress Test") + { + gs_allocator Al = CreateAllocator(Win32Alloc, Win32Free); + gs_memory_arena A = CreateMemoryArena(Al, "test", 128, 4); + + // NOTE(PS): This is an array of allocation sizes + // As we repeat the loop we will get values out of this array + // semi-randomly. + // * if the value is 0, we will clear the arena + // * if the value is 2, we will free the arena + // * otherwise we will push a value sized allocation on the arena + u64 RandomSizes[] = { 8, 32, 128, 93, 1256, 4098, 0, 1024, 7, 18, 967, 53, 1, 2 }; + u32 RandomSizesCount = sizeof(RandomSizes) / sizeof(u64); + + bool Success = true; + u32 RandomSeed = 1923; + for (u64 i = 0; i < (4096 * 14); i++) + { + TESTNextRandom(&RandomSeed); + u32 SizeIndex = RandomSeed % RandomSizesCount; + u64 RandomSize = RandomSizes[SizeIndex]; + + if (RandomSize == 0) + { + ClearArena(&A); + ClearCount++; + } else if (RandomSize == 2) { + FreeArena(&A); + FreeCount++; + } else { + gs_data D = PushSize_(&A, RandomSize, FileNameAndLineNumberString); + // NOTE(PS): This check has to be >= because the arena + // might have adjusted to maintain alignment on this + // allocation. + Success &= D.Size >= RandomSize; + } + } + + TestResult(Success); + + } + +} diff --git a/src/tests/sanity_tests.cpp b/src/tests/sanity_tests.cpp index cd4576e..fa8f271 100644 --- a/src/tests/sanity_tests.cpp +++ b/src/tests/sanity_tests.cpp @@ -5,6 +5,7 @@ // #ifndef SANITY_TESTS_CPP +#include #include #include "../gs_libs/gs_types.h" #include "../gs_libs/gs_types.cpp" @@ -13,21 +14,23 @@ #include "../gs_libs/gs_path.h" #include "../gs_libs/gs_csv.h" +#include "./memory_arena_tests.cpp" + gs_memory_arena Scratch = {}; void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); } void Free(void* Ptr, u64 Size) { return free(Ptr); } bool StringTest (gs_const_string StrA, gs_const_string StrB) { - return StringsEqual(StrA, StrB); + return StringsEqual(StrA, StrB); } bool StringTest (gs_string StrA, gs_string StrB) { - return StringsEqual(StrA, StrB); + return StringsEqual(StrA, StrB); } bool PathTest (char* In, char* Out) { - return StringsEqual(SanitizePath(ConstString(In), &Scratch), ConstString(Out)); + return StringsEqual(SanitizePath(ConstString(In), &Scratch), ConstString(Out)); } global char* SampleCSV = R"FOO(Flower Primary Hue (0-365) Secondary Hue (0-365) Tertiary Hue (0-365) Homonyms @@ -37,93 +40,95 @@ Flower C 55 32 128 foo, bar, blah, baz, whatever)FOO"; int main (int ArgCount, char** Args) { - Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch"); + Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch"); + + Test("gs_string") + { + gs_string TestString = PushStringF(&Scratch, 256, "Hello there, Sailor!"); - Test("gs_string") - { - gs_string TestString = PushStringF(&Scratch, 256, "Hello there, Sailor!"); - - NullTerminate(&TestString); - TestResult(IsNullTerminated(TestString)); - - TestResult(StringTest(GetStringPrefix(TestString.ConstString, 5), ConstString("Hello"))); - TestResult(StringTest(GetStringPostfix(TestString.ConstString, 5), ConstString("ilor!"))); - TestResult(StringTest(GetStringAfter(TestString.ConstString, 13), ConstString("Sailor!"))); - TestResult(StringTest(GetStringBefore(TestString.ConstString, 5), ConstString("Hello"))); - TestResult(StringTest(Substring(TestString.ConstString, 5, 11), ConstString(" there"))); - - TestResult(FindFirst(TestString, 5, 'l') == 16); - TestResult(FindFirst(TestString, 0, 'k') == -1); - TestResult(FindLast(TestString, 10, 'l') == 3); - TestResult(FindLast(TestString, 'k') == -1); - - TestResult(FindFirstFromSet(TestString.ConstString, "re") == 1); - TestResult(FindFirstFromSet(TestString.ConstString, "er") == 1); - TestResult(FindFirstFromSet(TestString.ConstString, "bk") == -1); - TestResult(FindFirstFromSet(TestString.ConstString, "ek") == 1); - - TestResult(FindLastFromSet(TestString.ConstString, "re") == 18); - TestResult(FindLastFromSet(TestString.ConstString, "er") == 18); - TestResult(FindLastFromSet(TestString.ConstString, "bk") == -1); - TestResult(FindLastFromSet(TestString.ConstString, "rk") == 18); - - TestResult(StringContains(TestString.ConstString, ',')); - TestResult(!StringContains(TestString.ConstString, '@')); - TestResult(StringsEqual(TestString, TestString)); - - TestResult(StringEqualsCharArray(TestString, "Hello there, Sailor!")); - TestResult(!StringEqualsCharArray(TestString, "Hello there, Sailor")); - TestResult(!StringEqualsCharArray(TestString, "Foobar")); - - ReverseStringInPlace(&TestString); - TestResult(StringTest(TestString, MakeString("!roliaS ,ereht olleH"))); - ReverseStringInPlace(&TestString); - - TestResult(ParseUInt(ConstString("532")) == 532); - TestResult(ParseInt(ConstString("-1234567890")) == -1234567890); - TestResult(ParseFloat(ConstString("-12345.6789")) == -12345.6789); - TestResult(ParseFloat(ConstString("-1")) == -1); - TestResult(ParseFloat(ConstString("-.035")) == -.035); - - TestString.Length = 0; - U64ToASCII(&TestString, 53298, 10); - TestResult(StringTest(TestString.ConstString, ConstString("53298"))); - - TestString.Length = 0; - R64ToASCII(&TestString, -145732.321, 2); - TestResult(StringTest(TestString.ConstString, ConstString("-145732.32"))); - } + NullTerminate(&TestString); + TestResult(IsNullTerminated(TestString)); - Test("gs_path.h") - { - TestResult(PathTest(".", ".")); - TestResult(PathTest(".\\", ".\\")); - TestResult(PathTest("./", ".\\")); - TestResult(PathTest("./../", "..\\")); - TestResult(PathTest("C:/users/pslattery\\test.foo", "C:\\users\\pslattery\\test.foo")); - TestResult(PathTest("./test/../foo.bar", ".\\foo.bar")); - TestResult(PathTest("C:\\hello\\world\\.\\test", "C:\\hello\\world\\test")); - } + TestResult(StringTest(GetStringPrefix(TestString.ConstString, 5), ConstString("Hello"))); + TestResult(StringTest(GetStringPostfix(TestString.ConstString, 5), ConstString("ilor!"))); + TestResult(StringTest(GetStringAfter(TestString.ConstString, 13), ConstString("Sailor!"))); + TestResult(StringTest(GetStringBefore(TestString.ConstString, 5), ConstString("Hello"))); + TestResult(StringTest(Substring(TestString.ConstString, 5, 11), ConstString(" there"))); - Test("gs_csv.h") - { - gs_const_string TestCSV = ConstString(SampleCSV); - gscsv_sheet Sheet = CSV_Parse(TestCSV, { '\t' }, &Scratch); - - gs_const_string Cell = CSVSheet_GetCell(Sheet, 0, 0); - TestResult(StringsEqual(Cell, ConstString("Flower"))); - - Cell = CSVSheet_GetCell(Sheet, 1, 1); - TestResult(StringsEqual(Cell, ConstString("55"))); - - Cell = CSVSheet_GetCell(Sheet, 4, 1); - TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever"))); - - Cell = CSVSheet_GetCell(Sheet, 4, 3); - TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever"))); - } + TestResult(FindFirst(TestString, 5, 'l') == 16); + TestResult(FindFirst(TestString, 0, 'k') == -1); + TestResult(FindLast(TestString, 10, 'l') == 3); + TestResult(FindLast(TestString, 'k') == -1); - return 0; + TestResult(FindFirstFromSet(TestString.ConstString, "re") == 1); + TestResult(FindFirstFromSet(TestString.ConstString, "er") == 1); + TestResult(FindFirstFromSet(TestString.ConstString, "bk") == -1); + TestResult(FindFirstFromSet(TestString.ConstString, "ek") == 1); + + TestResult(FindLastFromSet(TestString.ConstString, "re") == 18); + TestResult(FindLastFromSet(TestString.ConstString, "er") == 18); + TestResult(FindLastFromSet(TestString.ConstString, "bk") == -1); + TestResult(FindLastFromSet(TestString.ConstString, "rk") == 18); + + TestResult(StringContains(TestString.ConstString, ',')); + TestResult(!StringContains(TestString.ConstString, '@')); + TestResult(StringsEqual(TestString, TestString)); + + TestResult(StringEqualsCharArray(TestString, "Hello there, Sailor!")); + TestResult(!StringEqualsCharArray(TestString, "Hello there, Sailor")); + TestResult(!StringEqualsCharArray(TestString, "Foobar")); + + ReverseStringInPlace(&TestString); + TestResult(StringTest(TestString, MakeString("!roliaS ,ereht olleH"))); + ReverseStringInPlace(&TestString); + + TestResult(ParseUInt(ConstString("532")) == 532); + TestResult(ParseInt(ConstString("-1234567890")) == -1234567890); + TestResult(ParseFloat(ConstString("-12345.6789")) == -12345.6789); + TestResult(ParseFloat(ConstString("-1")) == -1); + TestResult(ParseFloat(ConstString("-.035")) == -.035); + + TestString.Length = 0; + U64ToASCII(&TestString, 53298, 10); + TestResult(StringTest(TestString.ConstString, ConstString("53298"))); + + TestString.Length = 0; + R64ToASCII(&TestString, -145732.321, 2); + TestResult(StringTest(TestString.ConstString, ConstString("-145732.32"))); + } + + Test("gs_path.h") + { + TestResult(PathTest(".", ".")); + TestResult(PathTest(".\\", ".\\")); + TestResult(PathTest("./", ".\\")); + TestResult(PathTest("./../", "..\\")); + TestResult(PathTest("C:/users/pslattery\\test.foo", "C:\\users\\pslattery\\test.foo")); + TestResult(PathTest("./test/../foo.bar", ".\\foo.bar")); + TestResult(PathTest("C:\\hello\\world\\.\\test", "C:\\hello\\world\\test")); + } + + Test("gs_csv.h") + { + gs_const_string TestCSV = ConstString(SampleCSV); + gscsv_sheet Sheet = CSV_Parse(TestCSV, { '\t' }, &Scratch); + + gs_const_string Cell = CSVSheet_GetCell(Sheet, 0, 0); + TestResult(StringsEqual(Cell, ConstString("Flower"))); + + Cell = CSVSheet_GetCell(Sheet, 1, 1); + TestResult(StringsEqual(Cell, ConstString("55"))); + + Cell = CSVSheet_GetCell(Sheet, 4, 1); + TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever"))); + + Cell = CSVSheet_GetCell(Sheet, 4, 3); + TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever"))); + } + + MemoryArenaTests(); + + return 0; }