Introduced memory_arena_tests

This commit is contained in:
PS 2021-08-06 14:51:04 -05:00
parent 7a67bd8c74
commit baf4c5d5a6
3 changed files with 277 additions and 86 deletions

View File

@ -37,7 +37,9 @@ cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp
REM COMPILE AND RUN TESTS REM COMPILE AND RUN TESTS
cl %CommonCompilerFlags% %ProjectDevPath%\src\tests\sanity_tests.cpp /Fesanity_tests.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib 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 sanity_tests.exe
ECHO SANITY TESTS END
popd popd

View File

@ -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);
}
}

View File

@ -5,6 +5,7 @@
// //
#ifndef SANITY_TESTS_CPP #ifndef SANITY_TESTS_CPP
#include <windows.h>
#include <stdio.h> #include <stdio.h>
#include "../gs_libs/gs_types.h" #include "../gs_libs/gs_types.h"
#include "../gs_libs/gs_types.cpp" #include "../gs_libs/gs_types.cpp"
@ -13,21 +14,23 @@
#include "../gs_libs/gs_path.h" #include "../gs_libs/gs_path.h"
#include "../gs_libs/gs_csv.h" #include "../gs_libs/gs_csv.h"
#include "./memory_arena_tests.cpp"
gs_memory_arena Scratch = {}; gs_memory_arena Scratch = {};
void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); } void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); }
void Free(void* Ptr, u64 Size) { return free(Ptr); } void Free(void* Ptr, u64 Size) { return free(Ptr); }
bool StringTest (gs_const_string StrA, gs_const_string StrB) 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) bool StringTest (gs_string StrA, gs_string StrB)
{ {
return StringsEqual(StrA, StrB); return StringsEqual(StrA, StrB);
} }
bool PathTest (char* In, char* Out) { 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 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) int main (int ArgCount, char** Args)
{ {
Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch"); Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch");
Test("gs_string") Test("gs_string")
{ {
gs_string TestString = PushStringF(&Scratch, 256, "Hello there, Sailor!"); gs_string TestString = PushStringF(&Scratch, 256, "Hello there, Sailor!");
NullTerminate(&TestString); NullTerminate(&TestString);
TestResult(IsNullTerminated(TestString)); TestResult(IsNullTerminated(TestString));
TestResult(StringTest(GetStringPrefix(TestString.ConstString, 5), ConstString("Hello"))); TestResult(StringTest(GetStringPrefix(TestString.ConstString, 5), ConstString("Hello")));
TestResult(StringTest(GetStringPostfix(TestString.ConstString, 5), ConstString("ilor!"))); TestResult(StringTest(GetStringPostfix(TestString.ConstString, 5), ConstString("ilor!")));
TestResult(StringTest(GetStringAfter(TestString.ConstString, 13), ConstString("Sailor!"))); TestResult(StringTest(GetStringAfter(TestString.ConstString, 13), ConstString("Sailor!")));
TestResult(StringTest(GetStringBefore(TestString.ConstString, 5), ConstString("Hello"))); TestResult(StringTest(GetStringBefore(TestString.ConstString, 5), ConstString("Hello")));
TestResult(StringTest(Substring(TestString.ConstString, 5, 11), ConstString(" there"))); TestResult(StringTest(Substring(TestString.ConstString, 5, 11), ConstString(" there")));
TestResult(FindFirst(TestString, 5, 'l') == 16); TestResult(FindFirst(TestString, 5, 'l') == 16);
TestResult(FindFirst(TestString, 0, 'k') == -1); TestResult(FindFirst(TestString, 0, 'k') == -1);
TestResult(FindLast(TestString, 10, 'l') == 3); TestResult(FindLast(TestString, 10, 'l') == 3);
TestResult(FindLast(TestString, 'k') == -1); TestResult(FindLast(TestString, 'k') == -1);
TestResult(FindFirstFromSet(TestString.ConstString, "re") == 1); TestResult(FindFirstFromSet(TestString.ConstString, "re") == 1);
TestResult(FindFirstFromSet(TestString.ConstString, "er") == 1); TestResult(FindFirstFromSet(TestString.ConstString, "er") == 1);
TestResult(FindFirstFromSet(TestString.ConstString, "bk") == -1); TestResult(FindFirstFromSet(TestString.ConstString, "bk") == -1);
TestResult(FindFirstFromSet(TestString.ConstString, "ek") == 1); TestResult(FindFirstFromSet(TestString.ConstString, "ek") == 1);
TestResult(FindLastFromSet(TestString.ConstString, "re") == 18); TestResult(FindLastFromSet(TestString.ConstString, "re") == 18);
TestResult(FindLastFromSet(TestString.ConstString, "er") == 18); TestResult(FindLastFromSet(TestString.ConstString, "er") == 18);
TestResult(FindLastFromSet(TestString.ConstString, "bk") == -1); TestResult(FindLastFromSet(TestString.ConstString, "bk") == -1);
TestResult(FindLastFromSet(TestString.ConstString, "rk") == 18); TestResult(FindLastFromSet(TestString.ConstString, "rk") == 18);
TestResult(StringContains(TestString.ConstString, ',')); TestResult(StringContains(TestString.ConstString, ','));
TestResult(!StringContains(TestString.ConstString, '@')); TestResult(!StringContains(TestString.ConstString, '@'));
TestResult(StringsEqual(TestString, TestString)); TestResult(StringsEqual(TestString, TestString));
TestResult(StringEqualsCharArray(TestString, "Hello there, Sailor!")); TestResult(StringEqualsCharArray(TestString, "Hello there, Sailor!"));
TestResult(!StringEqualsCharArray(TestString, "Hello there, Sailor")); TestResult(!StringEqualsCharArray(TestString, "Hello there, Sailor"));
TestResult(!StringEqualsCharArray(TestString, "Foobar")); TestResult(!StringEqualsCharArray(TestString, "Foobar"));
ReverseStringInPlace(&TestString); ReverseStringInPlace(&TestString);
TestResult(StringTest(TestString, MakeString("!roliaS ,ereht olleH"))); TestResult(StringTest(TestString, MakeString("!roliaS ,ereht olleH")));
ReverseStringInPlace(&TestString); ReverseStringInPlace(&TestString);
TestResult(ParseUInt(ConstString("532")) == 532); TestResult(ParseUInt(ConstString("532")) == 532);
TestResult(ParseInt(ConstString("-1234567890")) == -1234567890); TestResult(ParseInt(ConstString("-1234567890")) == -1234567890);
TestResult(ParseFloat(ConstString("-12345.6789")) == -12345.6789); TestResult(ParseFloat(ConstString("-12345.6789")) == -12345.6789);
TestResult(ParseFloat(ConstString("-1")) == -1); TestResult(ParseFloat(ConstString("-1")) == -1);
TestResult(ParseFloat(ConstString("-.035")) == -.035); TestResult(ParseFloat(ConstString("-.035")) == -.035);
TestString.Length = 0; TestString.Length = 0;
U64ToASCII(&TestString, 53298, 10); U64ToASCII(&TestString, 53298, 10);
TestResult(StringTest(TestString.ConstString, ConstString("53298"))); TestResult(StringTest(TestString.ConstString, ConstString("53298")));
TestString.Length = 0; TestString.Length = 0;
R64ToASCII(&TestString, -145732.321, 2); R64ToASCII(&TestString, -145732.321, 2);
TestResult(StringTest(TestString.ConstString, ConstString("-145732.32"))); TestResult(StringTest(TestString.ConstString, ConstString("-145732.32")));
} }
Test("gs_path.h") Test("gs_path.h")
{ {
TestResult(PathTest(".", ".")); TestResult(PathTest(".", "."));
TestResult(PathTest(".\\", ".\\")); TestResult(PathTest(".\\", ".\\"));
TestResult(PathTest("./", ".\\")); TestResult(PathTest("./", ".\\"));
TestResult(PathTest("./../", "..\\")); TestResult(PathTest("./../", "..\\"));
TestResult(PathTest("C:/users/pslattery\\test.foo", "C:\\users\\pslattery\\test.foo")); TestResult(PathTest("C:/users/pslattery\\test.foo", "C:\\users\\pslattery\\test.foo"));
TestResult(PathTest("./test/../foo.bar", ".\\foo.bar")); TestResult(PathTest("./test/../foo.bar", ".\\foo.bar"));
TestResult(PathTest("C:\\hello\\world\\.\\test", "C:\\hello\\world\\test")); TestResult(PathTest("C:\\hello\\world\\.\\test", "C:\\hello\\world\\test"));
} }
Test("gs_csv.h") Test("gs_csv.h")
{ {
gs_const_string TestCSV = ConstString(SampleCSV); gs_const_string TestCSV = ConstString(SampleCSV);
gscsv_sheet Sheet = CSV_Parse(TestCSV, { '\t' }, &Scratch); gscsv_sheet Sheet = CSV_Parse(TestCSV, { '\t' }, &Scratch);
gs_const_string Cell = CSVSheet_GetCell(Sheet, 0, 0); gs_const_string Cell = CSVSheet_GetCell(Sheet, 0, 0);
TestResult(StringsEqual(Cell, ConstString("Flower"))); TestResult(StringsEqual(Cell, ConstString("Flower")));
Cell = CSVSheet_GetCell(Sheet, 1, 1); Cell = CSVSheet_GetCell(Sheet, 1, 1);
TestResult(StringsEqual(Cell, ConstString("55"))); TestResult(StringsEqual(Cell, ConstString("55")));
Cell = CSVSheet_GetCell(Sheet, 4, 1); Cell = CSVSheet_GetCell(Sheet, 4, 1);
TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever"))); TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever")));
Cell = CSVSheet_GetCell(Sheet, 4, 3); Cell = CSVSheet_GetCell(Sheet, 4, 3);
TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever"))); TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever")));
} }
return 0; MemoryArenaTests();
return 0;
} }