From afab59eb211e9bdf3b460aa939178cc6eec23236 Mon Sep 17 00:00:00 2001 From: Ilusha Date: Fri, 15 Mar 2024 23:42:10 +0300 Subject: [PATCH] tmp --- Allocators/CMakeLists.txt | 8 +- Allocators/private/Allocators.cpp | 6 +- Allocators/private/HeapAllocatorGlobal.cpp | 21 ++- Allocators/public/HeapAllocatorGlobal.hpp | 5 +- Allocators/public/PrivateConfig.hpp | 1 - Allocators/tests/Test.cpp | 2 +- CMakeLists.txt | 2 +- CMakeOptions.txt | 5 + {Utils => Callstack}/CMakeLists.txt | 12 +- .../private/Callstack.cpp | 154 ++++++++++++++---- .../public/Callstack.hpp | 61 ++----- Callstack/tests/Test.cpp | 44 +++++ Containers/CMakeLists.txt | 7 +- Containers/private/Containers.cpp | 3 - Containers/public/Buffer2D.hpp | 7 +- Containers/public/ContainersCommon.hpp | 1 - Containers/public/Map.hpp | 9 +- Containers/public/Tree.hpp | 2 +- Containers/tests/Buffer2DTest.cpp | 4 +- Containers/tests/BufferTest.cpp | 4 +- Containers/tests/IntervalTreeTests.cpp | 2 +- Containers/tests/ListTest.cpp | 12 +- Containers/tests/MapTest.cpp | 10 +- Containers/tests/Tests.cpp | 33 ++-- Containers/tests/Tests.hpp | 13 +- Containers/tests/TreeTest.cpp | 4 +- Modules/private/Module.cpp | 8 - {Utils => Modules}/private/Timing.cpp | 2 + {Utils => Modules}/private/Utils.cpp | 11 -- Modules/public/Module.hpp | 2 - {Utils => Modules}/public/Sorting.hpp | 0 {Utils => Modules}/public/Timing.hpp | 0 {Utils => Modules}/public/Utils.hpp | 32 ---- Utils/tests/Tests.cpp | 65 -------- 34 files changed, 288 insertions(+), 264 deletions(-) rename {Utils => Callstack}/CMakeLists.txt (56%) rename Utils/private/Debugging.cpp => Callstack/private/Callstack.cpp (61%) rename Utils/public/Debugging.hpp => Callstack/public/Callstack.hpp (67%) create mode 100644 Callstack/tests/Test.cpp rename {Utils => Modules}/private/Timing.cpp (98%) rename {Utils => Modules}/private/Utils.cpp (89%) rename {Utils => Modules}/public/Sorting.hpp (100%) rename {Utils => Modules}/public/Timing.hpp (100%) rename {Utils => Modules}/public/Utils.hpp (79%) delete mode 100644 Utils/tests/Tests.cpp diff --git a/Allocators/CMakeLists.txt b/Allocators/CMakeLists.txt index 55c2989..8b59432 100644 --- a/Allocators/CMakeLists.txt +++ b/Allocators/CMakeLists.txt @@ -5,11 +5,11 @@ file(GLOB SOURCES "./private/*.cpp") file(GLOB HEADERS "./public/*.hpp") add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) target_include_directories(${PROJECT_NAME} PUBLIC ./public/) -target_link_libraries(${PROJECT_NAME} PUBLIC Utils) +target_link_libraries(${PROJECT_NAME} PUBLIC Callstack) ### -------------------------- Tests -------------------------- ### enable_testing() file(GLOB TEST_SOURCES "./tests/*.cpp") -add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) -target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} UnitTest++) -add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests) \ No newline at end of file +add_executable(Tests${PROJECT_NAME} ${TEST_SOURCES}) +target_link_libraries(Tests${PROJECT_NAME} ${PROJECT_NAME} UnitTest++) +add_test(NAME Tests${PROJECT_NAME} COMMAND Tests${PROJECT_NAME}) \ No newline at end of file diff --git a/Allocators/private/Allocators.cpp b/Allocators/private/Allocators.cpp index 584e175..1b87345 100644 --- a/Allocators/private/Allocators.cpp +++ b/Allocators/private/Allocators.cpp @@ -13,9 +13,11 @@ static bool init(const tp::ModuleManifest* self) { return true; } -static void deinit(const tp::ModuleManifest* self) { tp::HeapAllocGlobal::checkLeaks(); } +static void deinit(const tp::ModuleManifest* self) { + tp::HeapAllocGlobal::checkLeaks(); +} -static tp::ModuleManifest* sModuleDependencies[] = { &tp::gModuleUtils, nullptr }; +static tp::ModuleManifest* sModuleDependencies[] = { nullptr }; tp::ModuleManifest tp::gModuleAllocators = ModuleManifest("Allocators", init, deinit, sModuleDependencies); void* operator new(size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); } diff --git a/Allocators/private/HeapAllocatorGlobal.cpp b/Allocators/private/HeapAllocatorGlobal.cpp index e330a60..98b1c53 100644 --- a/Allocators/private/HeapAllocatorGlobal.cpp +++ b/Allocators/private/HeapAllocatorGlobal.cpp @@ -3,7 +3,7 @@ #include "HeapAllocatorGlobal.hpp" #include "PrivateConfig.hpp" -#include "Debugging.hpp" +#include "Callstack.hpp" #include "Utils.hpp" #include @@ -33,7 +33,11 @@ tp::ualni tp::HeapAllocGlobal::mNumAllocations = 0; std::mutex tp::HeapAllocGlobal::mMutex; bool tp::HeapAllocGlobal::mIgnore = true; -// ----------------------- Debug Implementation ---------------------------- // +#ifdef MEM_STACK_TRACE +tp::CallStackCapture tp::HeapAllocGlobal::mCallstack; +#endif + + // ----------------------- Debug Implementation ---------------------------- // // |----------------| // | MemHead | // |----------------| @@ -105,8 +109,7 @@ ALLOCATE: // 3) Trace the stack #ifdef MEM_STACK_TRACE // check if somewhat decides to call new within static variable initialization - if (gCSCapture) head->mCallStack = gCSCapture->getSnapshot(); - else head->mCallStack = nullptr; + head->mCallStack = mCallstack.getSnapshot(); #endif mMutex.unlock(); @@ -146,12 +149,16 @@ void HeapAllocGlobal::deallocate(void* aPtr) { if (!head->mIgnored) { // 3) Check the wrap if (memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL)) { - CallStackCapture::printSnapshot(head->mCallStack); +#ifdef MEM_STACK_TRACE + mCallstack.printSnapshot(head->mCallStack); +#endif ASSERT(!"Allocated Block Wrap Corrupted!") } if (memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL)) { - CallStackCapture::printSnapshot(head->mCallStack); +#ifdef MEM_STACK_TRACE + mCallstack.printSnapshot(head->mCallStack); +#endif ASSERT(!"Allocated Block Wrap Corrupted!") } @@ -176,7 +183,7 @@ bool HeapAllocGlobal::checkLeaks() { #ifdef MEM_STACK_TRACE for (auto iter = mEntry; iter; iter = iter->mPrev) { - if (!iter->mIgnored) CallStackCapture::printSnapshot(iter->mCallStack); + if (!iter->mIgnored) mCallstack.printSnapshot(iter->mCallStack); } #endif diff --git a/Allocators/public/HeapAllocatorGlobal.hpp b/Allocators/public/HeapAllocatorGlobal.hpp index 86064d6..fa4d43c 100644 --- a/Allocators/public/HeapAllocatorGlobal.hpp +++ b/Allocators/public/HeapAllocatorGlobal.hpp @@ -1,6 +1,6 @@ #pragma once -#include "Module.hpp" +#include "Callstack.hpp" #include namespace tp { @@ -12,6 +12,9 @@ namespace tp { static struct MemHead* mEntry; static std::mutex mMutex; static bool mIgnore; +#ifdef MEM_STACK_TRACE // Save stack on allocation call + static CallStackCapture mCallstack; +#endif #endif public: diff --git a/Allocators/public/PrivateConfig.hpp b/Allocators/public/PrivateConfig.hpp index beacb7e..e8d735e 100644 --- a/Allocators/public/PrivateConfig.hpp +++ b/Allocators/public/PrivateConfig.hpp @@ -6,5 +6,4 @@ #define MEM_CLEAR_ON_DEALLOC // Clear data on free #define MEM_CLEAR_ON_DEALLOC_VAL 0xAA // Clear data on free #define MEM_CLEAR_ON_ALLOC_VAL 0xCC // Clear data on free -#define MEM_STACK_TRACE // Save stack on allocation call #define MEM_STACK_TRACE_MAX_DEPTH 32 // Call stack max depth \ No newline at end of file diff --git a/Allocators/tests/Test.cpp b/Allocators/tests/Test.cpp index 65d69eb..4b0563d 100644 --- a/Allocators/tests/Test.cpp +++ b/Allocators/tests/Test.cpp @@ -234,7 +234,7 @@ SUITE(Allocators) { int main() { - tp::ModuleManifest* deps[] = { &tp::gModuleAllocators, &tp::gModuleUtils, nullptr }; + tp::ModuleManifest* deps[] = { &tp::gModuleAllocators, nullptr }; tp::ModuleManifest testModule("AllocatorsTest", nullptr, nullptr, deps); if (!testModule.initialize()) { diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e35811..7cfe586 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ project(ModulesRoot) include(CMakeOptions.txt) add_subdirectory(Modules) -add_subdirectory(Utils) +add_subdirectory(Callstack) add_subdirectory(Containers) add_subdirectory(Math) add_subdirectory(Allocators) diff --git a/CMakeOptions.txt b/CMakeOptions.txt index 742e8ad..5768530 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -1,4 +1,5 @@ option(MODULES_MEMORY_DEBUG "Debug memory" ON) +option(MODULES_MEMORY_DEBUG_STACK_TRACE "Record stack info on memory debug" ON) set(WINDOWS_LIBRARIES "../../ModulesWindowsLibraries" CACHE STRING "Svn repository with windows libraries https://svn.riouxsvn.com/moduleswindowsl") @@ -6,4 +7,8 @@ if (MODULES_MEMORY_DEBUG) add_compile_definitions(MEM_DEBUG) endif () +if (MODULES_MEMORY_DEBUG_STACK_TRACE) + add_compile_definitions(MEM_STACK_TRACE) +endif () + enable_testing() \ No newline at end of file diff --git a/Utils/CMakeLists.txt b/Callstack/CMakeLists.txt similarity index 56% rename from Utils/CMakeLists.txt rename to Callstack/CMakeLists.txt index 09f7284..d6ce6cc 100644 --- a/Utils/CMakeLists.txt +++ b/Callstack/CMakeLists.txt @@ -1,16 +1,14 @@ -project(Utils) +project(Callstack) ### ---------------------- Static Library --------------------- ### file(GLOB SOURCES "./private/*.cpp") + add_library(${PROJECT_NAME} STATIC ${SOURCES}) target_include_directories(${PROJECT_NAME} PUBLIC ./public/) - -### ---------------------- Dependencies --------------------- ### target_link_libraries(${PROJECT_NAME} PUBLIC Containers) ### -------------------------- Tests -------------------------- ### -enable_testing() file(GLOB TEST_SOURCES "./tests/*.cpp") -add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) -target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} UnitTest++) -add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests) \ No newline at end of file +add_executable(Tests${PROJECT_NAME} ${TEST_SOURCES}) +target_link_libraries(Tests${PROJECT_NAME} ${PROJECT_NAME} UnitTest++) +add_test(NAME Tests${PROJECT_NAME} COMMAND Tests${PROJECT_NAME}) \ No newline at end of file diff --git a/Utils/private/Debugging.cpp b/Callstack/private/Callstack.cpp similarity index 61% rename from Utils/private/Debugging.cpp rename to Callstack/private/Callstack.cpp index cc1d63e..93df3cd 100644 --- a/Utils/private/Debugging.cpp +++ b/Callstack/private/Callstack.cpp @@ -1,19 +1,15 @@ -#include "Debugging.hpp" -#include "Utils.hpp" +#include "Callstack.hpp" #include using namespace tp; -CallStackCapture* tp::gCSCapture = nullptr; - -void initializeCallStackCapture() { gCSCapture = new (malloc(sizeof(CallStackCapture))) CallStackCapture(); } - -void deinitializeCallStackCapture() { - gCSCapture->~CallStackCapture(); - free(gCSCapture); - gCSCapture = nullptr; +// frame to reference on no sapce left +static void errorNoSpaceLeft() { + // to disable optimization of function + static int dummy; + dummy = 10; } ualni CallStackCapture::CallStack::getDepth() const { @@ -24,14 +20,7 @@ ualni CallStackCapture::CallStack::getDepth() const { } len++; } - ualni stripedLen = 0; - for (auto i = FRAMES_TO_SKIP_START; i < len - FRAMES_TO_SKIP_END; i++) { - if (!frames[i]) { - break; - } - stripedLen++; - } - return stripedLen; + return len++; } ualni CallStackCapture::hashCallStack(CallStackKey key) { @@ -44,7 +33,7 @@ ualni CallStackCapture::hashCallStack(CallStackKey key) { } bool CallStackCapture::CallStackKey::operator==(const CallStackCapture::CallStackKey& in) const { - for (auto i : Range(MAX_CALL_DEPTH_CAPTURE)) { + for (ualni i = 0; i < MAX_CALL_DEPTH_CAPTURE; i++) { if (cs->frames[i] != in.cs->frames[i]) { return false; } @@ -60,26 +49,26 @@ CallStackCapture::CallStackCapture() { static_assert(MAX_CALL_DEPTH_CAPTURE >= 1); static_assert(MAX_CALL_CAPTURES_MEM_SIZE_MB > 0); static_assert(MAX_DEBUG_INFO_LEN > sizeof("unresolved")); - static_assert(FRAMES_TO_SKIP_END >= 0 && FRAMES_TO_SKIP_START >= 0); - static_assert(MAX_CALL_DEPTH_CAPTURE > FRAMES_TO_SKIP_START + FRAMES_TO_SKIP_END); static_assert(MAX_CALL_CAPTURES_MEM_SIZE_MB * 1024 * 1024 > sizeof(CallStack)); - MODULE_SANITY_CHECK(gModuleUtils) mBuffLoad = 0; - mBuffLen = (MAX_CALL_CAPTURES_MEM_SIZE_MB * 1024 * 1024) / sizeof(CallStack); + mBuffLen = STACKS_LENGTH; mBuff = (CallStack*) malloc(mBuffLen * sizeof(CallStack)); + + mErrorSnapshot.frames[0] = (alni) & errorNoSpaceLeft; + + + platformInit(); } const CallStackCapture::CallStack* CallStackCapture::getSnapshot() { - MODULE_SANITY_CHECK(gModuleUtils) if (mBuffLoad > mBuffLen) { - static CallStack cs; - cs.frames[0] = 0; - return &cs; + return &mErrorSnapshot; } CallStack* cs = &mBuff[mBuffLoad]; + platformWriteStackTrace(cs); auto idx = mSnapshots.presents({ cs }); @@ -213,7 +202,7 @@ void CallStackCapture::printSnapshot(const CallStack* snapshot) { printf("CallStack: \n"); if (snapshot) { for (auto frame : *snapshot) { - auto symbols = gCSCapture->getSymbols(frame.getFrame()); + auto symbols = getSymbols(frame.getFrame()); printf(" %s ----- %s:%llu\n", symbols->getFunc(), symbols->getFile(), symbols->getLine()); } } @@ -227,15 +216,112 @@ void CallStackCapture::logAll() { } #else -void CallStackCapture::platformWriteStackTrace(CallStack* stack) { stack->frames[0] = 0; } -void CallStackCapture::platformWriteDebugSymbols(FramePointer frame, DebugSymbols* out) { - std::strcpy(out->file, "unresolved"); - std::strcpy(out->function, "unresolved"); +#include +#include +#include + +#pragma comment(lib, "dbghelp.lib") + +void CallStackCapture::platformInit() { + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); } + +void CallStackCapture::platformDeinit() { + HANDLE process = GetCurrentProcess(); + SymCleanup(process); +} + +void CallStackCapture::platformWriteStackTrace(CallStack* stack) { + DWORD hash; + CONTEXT context; + memset(&context, 0, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_FULL; + RtlCaptureContext(&context); + + STACKFRAME64 stackFrame; + memset(&stackFrame, 0, sizeof(STACKFRAME64)); +#ifdef _M_IX86 + hash = IMAGE_FILE_MACHINE_I386; + stackFrame.AddrPC.Offset = context.Eip; + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = context.Ebp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = context.Esp; + stackFrame.AddrStack.Mode = AddrModeFlat; +#elif _M_X64 + hash = IMAGE_FILE_MACHINE_AMD64; + stackFrame.AddrPC.Offset = context.Rip; + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = context.Rbp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = context.Rsp; + stackFrame.AddrStack.Mode = AddrModeFlat; +#endif + + for (int frameIndex = 0; frameIndex < MAX_CALL_DEPTH_CAPTURE; ++frameIndex) { + if (!StackWalk64( + hash, + GetCurrentProcess(), + GetCurrentThread(), + &stackFrame, + &context, + NULL, + SymFunctionTableAccess64, + SymGetModuleBase64, + NULL + )) { + + stack->frames[frameIndex] = 0; + break; + } + stack->frames[frameIndex] = (alni) (void*) stackFrame.AddrPC.Offset; + } + stack->frames[MAX_CALL_DEPTH_CAPTURE - 1] = 0; +} + +void CallStackCapture::platformWriteDebugSymbols(FramePointer frame, DebugSymbols* out) { + HANDLE process = GetCurrentProcess(); + + IMAGEHLP_LINE64 lineInfo; + DWORD displacement; + lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + if (SymGetLineFromAddr64(process, (DWORD64) frame, &displacement, &lineInfo)) { + strcpy(out->file, lineInfo.FileName); + out->line = lineInfo.LineNumber; + } else { + strcpy(out->file, "unresolved"); + out->line = 0; + } + + DWORD64 displacementSym = 0; + char symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH] = { 0 }; + IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*) symbolBuffer; + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + symbol->MaxNameLength = MAX_PATH; + + if (SymGetSymFromAddr64(process, (DWORD64) frame, &displacementSym, symbol)) { + strcpy(out->function, symbol->Name); + } else { + strcpy(out->function, "unresolved"); + } +} + void CallStackCapture::printSnapshot(const CallStack* snapshot) { printf("CallStack: \n"); - printf("Call stack debugging is not supported on this platform"); + if (snapshot) { + for (int i = 0; i < snapshot->getDepth(); ++i) { + DebugSymbols symbols; + platformWriteDebugSymbols(snapshot->frames[i], &symbols); + printf(" %s ----- %s:%lu\n", symbols.function, symbols.file, symbols.line); + } + } printf("\n"); } -void CallStackCapture::logAll() { printf("Call stack debugging is not supported on this platform"); } + +void CallStackCapture::logAll() { + for (auto cs : *this) { + printSnapshot(cs.getCallStack()); + } +} #endif \ No newline at end of file diff --git a/Utils/public/Debugging.hpp b/Callstack/public/Callstack.hpp similarity index 67% rename from Utils/public/Debugging.hpp rename to Callstack/public/Callstack.hpp index 7722138..fd0406d 100644 --- a/Utils/public/Debugging.hpp +++ b/Callstack/public/Callstack.hpp @@ -3,18 +3,18 @@ #include "Environment.hpp" #include "Map.hpp" -#define MAX_CALL_DEPTH_CAPTURE 128 -#define MAX_CALL_CAPTURES_MEM_SIZE_MB 16 -#define MAX_DEBUG_INFO_LEN 63 -#define FRAMES_TO_SKIP_START 2 -#define FRAMES_TO_SKIP_END 3 - namespace tp { class CallStackCapture { public: typedef tp::alni FramePointer; + enum { + MAX_CALL_DEPTH_CAPTURE = 16, + MAX_CALL_CAPTURES_MEM_SIZE_MB = 32, + MAX_DEBUG_INFO_LEN = 64, + }; + class CallStack { friend CallStackCapture; FramePointer frames[MAX_CALL_DEPTH_CAPTURE]; @@ -26,18 +26,19 @@ namespace tp { const FramePointer* mFrame; public: - explicit Iterator(const FramePointer* frame) : - mFrame(frame){}; + explicit Iterator(const FramePointer* frame) : mFrame(frame){}; FramePointer getFrame() { return *mFrame; } bool operator==(const Iterator& in) const { return in.mFrame == mFrame; } void operator++() { mFrame++; } const Iterator& operator*() const { return *this; } }; - [[nodiscard]] Iterator begin() const { return Iterator(frames + FRAMES_TO_SKIP_START); } - [[nodiscard]] Iterator end() const { return Iterator(frames + FRAMES_TO_SKIP_START + getDepth()); } + [[nodiscard]] Iterator begin() const { return Iterator(frames); } + [[nodiscard]] Iterator end() const { return Iterator(frames + getDepth()); } }; + enum { STACKS_LENGTH = (MAX_CALL_CAPTURES_MEM_SIZE_MB * 1024 * 1024) / sizeof(CallStack) }; + class DebugSymbols { friend CallStackCapture; char function[MAX_DEBUG_INFO_LEN + 1] = { 0 }; @@ -57,44 +58,15 @@ namespace tp { [[nodiscard]] const CallStack* getSnapshot(); const DebugSymbols* getSymbols(FramePointer fp); - static void printSnapshot(const CallStack* snapshot); + void printSnapshot(const CallStack* snapshot); void logAll(); - public: - template - void write(Saver& file) { - file.write(mBuffLoad); - for (auto cs : *this) { - file.write(cs.getCallStack()->getDepth()); - for (auto frame : *cs.getCallStack()) { - file.write((ualni) frame.getFrame()); - } - } - file.write(mSymbols); - } - - // independent of the configuration - template - void read(Loader& file) { - clear(); - ualni loadLen; - file.read(loadLen); - for (auto cs = loadLen; cs; cs--) { - ualni callStackLen; - file.read(callStackLen); - for (auto fp = callStackLen; fp; fp--) { - // -- - } - } - } - public: class Iterator { const CallStack* mSnapshot; public: - explicit Iterator(const CallStack* start) : - mSnapshot(start){}; + explicit Iterator(const CallStack* start) : mSnapshot(start) {}; const CallStack* getCallStack() { return mSnapshot; } bool operator==(const Iterator& in) const { return in.mSnapshot == mSnapshot; } void operator++() { mSnapshot++; } @@ -113,16 +85,19 @@ namespace tp { static void platformWriteStackTrace(CallStack* stack); static void platformWriteDebugSymbols(FramePointer frame, DebugSymbols* out); [[nodiscard]] static ualni hashCallStack(CallStackKey key); + void platformInit(); + void platformDeinit(); void clear(); private: + CallStack mErrorSnapshot; + ualni mBuffLen; ualni mBuffLoad; CallStack* mBuff; + Map mSnapshots; Map mSymbols; }; - - extern CallStackCapture* gCSCapture; } diff --git a/Callstack/tests/Test.cpp b/Callstack/tests/Test.cpp new file mode 100644 index 0000000..e5ed3b7 --- /dev/null +++ b/Callstack/tests/Test.cpp @@ -0,0 +1,44 @@ + +#include "UnitTest++/UnitTest++.h" + +#include "Callstack.hpp" + +#include + +using namespace tp; + +void common(CallStackCapture& cs) { auto tmp = cs.getSnapshot(); } + +void first(CallStackCapture& cs) { + common(cs); + common(cs); + common(cs); +} + +void second(CallStackCapture& cs) { + common(cs); + common(cs); + common(cs); + common(cs); +} + +void third(CallStackCapture& cs) { + common(cs); + common(cs); +} + +void root(CallStackCapture& cs) { + first(cs); + second(cs); + third(cs); +} + +SUITE(Utils) { + TEST(CallStackCapture) { + CallStackCapture callstack; + root(callstack); + callstack.logAll(); + } +} + +int main() { return UnitTest::RunAllTests(); } \ No newline at end of file diff --git a/Containers/CMakeLists.txt b/Containers/CMakeLists.txt index d1ebd2a..bb9bb34 100644 --- a/Containers/CMakeLists.txt +++ b/Containers/CMakeLists.txt @@ -8,8 +8,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ./public/) target_link_libraries(${PROJECT_NAME} PUBLIC Modules) ### -------------------------- Tests -------------------------- ### -enable_testing() file(GLOB TEST_SOURCES "./tests/*.cpp") -add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) -target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Allocators UnitTest++) -add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests) \ No newline at end of file +add_executable(Tests${PROJECT_NAME} ${TEST_SOURCES}) +target_link_libraries(Tests${PROJECT_NAME} ${PROJECT_NAME} UnitTest++) +add_test(NAME Tests${PROJECT_NAME} COMMAND Tests${PROJECT_NAME}) \ No newline at end of file diff --git a/Containers/private/Containers.cpp b/Containers/private/Containers.cpp index 4aef4db..20ed850 100644 --- a/Containers/private/Containers.cpp +++ b/Containers/private/Containers.cpp @@ -5,9 +5,6 @@ namespace tp { - static ModuleManifest* sModuleDependencies[] = { &gModuleBase, nullptr }; - ModuleManifest gModuleContainers = ModuleManifest("Containers", nullptr, nullptr, sModuleDependencies); - void* DefaultAllocator::allocate(ualni size) { return malloc(size); } void DefaultAllocator::deallocate(void* p) { free(p); } diff --git a/Containers/public/Buffer2D.hpp b/Containers/public/Buffer2D.hpp index 097d651..cb34689 100644 --- a/Containers/public/Buffer2D.hpp +++ b/Containers/public/Buffer2D.hpp @@ -13,7 +13,12 @@ namespace tp { class Buffer2D { public: typedef ualni Index; - typedef Pair Index2D; + + struct Index2D { + Index x = 0; + Index y = 0; + }; + typedef SelectValueOrReference tTypeArg; private: diff --git a/Containers/public/ContainersCommon.hpp b/Containers/public/ContainersCommon.hpp index f3ac219..4021041 100644 --- a/Containers/public/ContainersCommon.hpp +++ b/Containers/public/ContainersCommon.hpp @@ -4,7 +4,6 @@ #include "Module.hpp" namespace tp { - extern ModuleManifest gModuleContainers; class DefaultAllocator { public: diff --git a/Containers/public/Map.hpp b/Containers/public/Map.hpp index 454e794..405ca9d 100644 --- a/Containers/public/Map.hpp +++ b/Containers/public/Map.hpp @@ -164,7 +164,6 @@ namespace tp { public: Map() { - MODULE_SANITY_CHECK(gModuleContainers) mNSlots = next2pow(uhalni(tTableInitialSize - 1)); mTable = newTable(mNSlots); } @@ -243,7 +242,13 @@ namespace tp { if (this == &in) { return *this; } - removeAll(); + + for (ualni i = 0; i < mNSlots; i++) { + if (mTable[i] && !isDeletedNode(mTable[i])) { + deleteNode(mTable[i]); + } + } + mNEntries = 0; mNSlots = in.mNSlots; deleteTable(mTable); mTable = newTable(mNSlots); diff --git a/Containers/public/Tree.hpp b/Containers/public/Tree.hpp index 389495c..3b84fe8 100644 --- a/Containers/public/Tree.hpp +++ b/Containers/public/Tree.hpp @@ -62,7 +62,7 @@ namespace tp { }; public: - AvlTree() { MODULE_SANITY_CHECK(gModuleContainers) } + AvlTree() {} ~AvlTree() { removeAll(); } [[nodiscard]] ualni size() const { return mSize; } diff --git a/Containers/tests/Buffer2DTest.cpp b/Containers/tests/Buffer2DTest.cpp index 6723e68..202f731 100644 --- a/Containers/tests/Buffer2DTest.cpp +++ b/Containers/tests/Buffer2DTest.cpp @@ -1,15 +1,13 @@ #include "Buffer2D.hpp" #include "Tests.hpp" -#include "HeapAllocator.hpp" - using namespace tp; const ualni size = 1000; SUITE(Buffer2D) { TEST(Simple) { - Buffer2D buff; + Buffer2D buff; buff.reserve({ 4, 4 }); buff.set({ 2, 2 }, 5); CHECK(buff.get({ 2, 2 }) == 5); diff --git a/Containers/tests/BufferTest.cpp b/Containers/tests/BufferTest.cpp index 3dfd9ee..685f285 100644 --- a/Containers/tests/BufferTest.cpp +++ b/Containers/tests/BufferTest.cpp @@ -7,7 +7,7 @@ const ualni size = 1000; SUITE(Buffer) { TEST(Simple1) { - Buffer buff; + Buffer buff; CHECK(buff.size() == 0); for (auto i : Range(size * 10)) { buff.append(TestClass(i)); @@ -19,7 +19,7 @@ SUITE(Buffer) { } TEST(Simple2) { - Buffer buff(size); + Buffer buff(size); CHECK(buff.size() == size); for (auto i : Range(size * 10)) buff.append(TestClass(i)); diff --git a/Containers/tests/IntervalTreeTests.cpp b/Containers/tests/IntervalTreeTests.cpp index 7c1bf56..c139787 100644 --- a/Containers/tests/IntervalTreeTests.cpp +++ b/Containers/tests/IntervalTreeTests.cpp @@ -224,7 +224,7 @@ SUITE(IntervalTree) { ualni numFound = 0; ualni lastDataFound = 0; - [[nodiscard]] bool isSingleData(ualni aData) const { return numFound == 1 & lastDataFound == aData; } + [[nodiscard]] bool isSingleData(ualni aData) const { return numFound == 1 && lastDataFound == aData; } [[nodiscard]] bool notFound() const { return numFound == 0; } [[nodiscard]] bool found(ualni num) const { return numFound == num; } }; diff --git a/Containers/tests/ListTest.cpp b/Containers/tests/ListTest.cpp index 2ed5dfa..b12869b 100644 --- a/Containers/tests/ListTest.cpp +++ b/Containers/tests/ListTest.cpp @@ -7,7 +7,7 @@ using namespace tp; SUITE(DoubleLinkedList) { TEST(SimpleReference) { - tp::List list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) }; + tp::List list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) }; list.pushBack(TestClass(5)); list.pushFront(TestClass(0)); @@ -24,7 +24,9 @@ SUITE(DoubleLinkedList) { } TEST(SimplePointer) { - tp::List list = { new TestClass(1), new TestClass(2), new TestClass(3), new TestClass(4) }; + tp::List list = { + new TestClass(1), new TestClass(2), new TestClass(3), new TestClass(4) + }; list.pushBack(new TestClass(5)); list.pushFront(new TestClass(0)); @@ -45,8 +47,8 @@ SUITE(DoubleLinkedList) { } TEST(Copy) { - tp::List list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) }; - tp::List list2 = list; + tp::List list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) }; + tp::List list2 = list; CHECK(list == list2); @@ -55,7 +57,7 @@ SUITE(DoubleLinkedList) { } TEST(Serialization) { - tp::List list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) }; + tp::List list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) }; ArchiverExample<1024, false> write; ArchiverExample<1024, true> read; diff --git a/Containers/tests/MapTest.cpp b/Containers/tests/MapTest.cpp index 222ab71..3fb8ef6 100644 --- a/Containers/tests/MapTest.cpp +++ b/Containers/tests/MapTest.cpp @@ -6,7 +6,7 @@ using namespace tp; SUITE(HashTable) { TEST(SimpleReference) { - tp::Map map; + tp::Map map; for (auto i : Range(1000, 100000)) { map.put(i, TestClass(i)); @@ -40,7 +40,7 @@ SUITE(HashTable) { } TEST(SimplePointer) { - tp::Map map; + tp::Map map; for (auto i : Range(1000)) { map.put(i, new TestClass(i)); @@ -78,13 +78,13 @@ SUITE(HashTable) { } TEST(Copy) { - tp::Map map; + tp::Map map; for (auto i : Range(10)) { map.put(i, TestClass(i)); } - tp::Map map2 = map; + tp::Map map2 = map; CHECK(map == map2); @@ -93,7 +93,7 @@ SUITE(HashTable) { } TEST(SaveLoad) { - tp::Map map; + tp::Map map; for (auto i : Range(10)) { map.put(i, TestClass(i)); diff --git a/Containers/tests/Tests.cpp b/Containers/tests/Tests.cpp index 132814c..6769444 100644 --- a/Containers/tests/Tests.cpp +++ b/Containers/tests/Tests.cpp @@ -2,18 +2,23 @@ #include "Tests.hpp" #include "UnitTest++/UnitTest++.h" -int main() { - - tp::ModuleManifest* deps[] = { &tp::gModuleUtils, &tp::gModuleAllocators, nullptr }; - tp::ModuleManifest testModule("ContainersTest", nullptr, nullptr, deps); - - if (!testModule.initialize()) { - return 1; - } - - bool res = UnitTest::RunAllTests(); - - testModule.deinitialize(); - - return res; +void* TestAllocator::allocate(tp::ualni size) { + count++; + return malloc(size); +} + +void TestAllocator::deallocate(void* p) { + if (p) { + free(p); + count--; + } +} + + +TestAllocator::~TestAllocator() { + ASSERT(!count); +} + +int main() { + return UnitTest::RunAllTests(); } diff --git a/Containers/tests/Tests.hpp b/Containers/tests/Tests.hpp index d3504cc..a517eb0 100644 --- a/Containers/tests/Tests.hpp +++ b/Containers/tests/Tests.hpp @@ -2,9 +2,20 @@ #include "UnitTest++/UnitTest++.h" -#include "Allocators.hpp" #include "Utils.hpp" +// counting number of allocations and deallocations +struct TestAllocator { + TestAllocator() { count = 0; }; + + tp::ualni count = 0; + + void* allocate(tp::ualni size); + void deallocate(void*); + + ~TestAllocator(); +}; + class TestClass { tp::ualni val2 = 0; tp::ualni val1; diff --git a/Containers/tests/TreeTest.cpp b/Containers/tests/TreeTest.cpp index e5fbff4..9a571fc 100644 --- a/Containers/tests/TreeTest.cpp +++ b/Containers/tests/TreeTest.cpp @@ -5,7 +5,7 @@ using namespace tp; SUITE(AvlTree) { TEST(Simple) { - AvlTree, TestClass, tp::HeapAlloc> tree; + AvlTree, TestClass, TestAllocator> tree; CHECK(tree.size() == 0); CHECK(tree.head() == nullptr); @@ -22,7 +22,7 @@ SUITE(AvlTree) { } TEST(Persistance) { - AvlTree, TestClass, tp::HeapAlloc> tree; + AvlTree, TestClass, TestAllocator> tree; const auto size = 1000; diff --git a/Modules/private/Module.cpp b/Modules/private/Module.cpp index 54bf334..178f330 100644 --- a/Modules/private/Module.cpp +++ b/Modules/private/Module.cpp @@ -5,14 +5,6 @@ using namespace tp; -static bool init(const ModuleManifest* self) { - gEnvironment.log(); - return true; -} - -static ModuleManifest* deps[] = { nullptr }; -ModuleManifest tp::gModuleBase = ModuleManifest("Common", init, nullptr, deps); - ModuleManifest::ModuleManifest(const char* aModuleName, ModuleInit aInit, ModuleDeinit aDeinit, ModuleManifest** aDependencies) { mInit = aInit; mDeinit = aDeinit; diff --git a/Utils/private/Timing.cpp b/Modules/private/Timing.cpp similarity index 98% rename from Utils/private/Timing.cpp rename to Modules/private/Timing.cpp index ae37422..45bc56d 100644 --- a/Utils/private/Timing.cpp +++ b/Modules/private/Timing.cpp @@ -47,6 +47,7 @@ namespace tp { } } + // TODO remove float Timer::easeIn(time_ms pDuration) { if (!pDuration) { pDuration = mDuration; @@ -55,6 +56,7 @@ namespace tp { return clamp((1.1f * x) / (x + 0.1f), 0.f, 1.f); } + // TODO remove float Timer::easeOut(time_ms pDuration) { if (!pDuration) { pDuration = mDuration; diff --git a/Utils/private/Utils.cpp b/Modules/private/Utils.cpp similarity index 89% rename from Utils/private/Utils.cpp rename to Modules/private/Utils.cpp index ab41db3..1649628 100644 --- a/Utils/private/Utils.cpp +++ b/Modules/private/Utils.cpp @@ -1,8 +1,6 @@ #include "Utils.hpp" -#include "ContainersCommon.hpp" - #include #include @@ -21,12 +19,7 @@ static void deinitialize(const tp::ModuleManifest*) { namespace tp { - static ModuleManifest* sModuleUtilsDeps[] = { &gModuleContainers, nullptr }; - ModuleManifest gModuleUtils = ModuleManifest("Utils", initialize, deinitialize, sModuleUtilsDeps); - void memSetVal(void* p, uhalni byteSize, uint1 val) { - // MODULE_SANITY_CHECK(gModuleBase) - alni alignedVal = val; alignedVal = (alignedVal << 8) | alignedVal; alignedVal = (alignedVal << 16) | alignedVal; @@ -44,8 +37,6 @@ namespace tp { } void memCopy(void* left, const void* right, uhalni len) { - MODULE_SANITY_CHECK(gModuleBase) - ualni alignedLen = len / sizeof(alni); for (ualni idx = 0; idx < alignedLen; idx++) { ((alni*) left)[idx] = ((alni*) right)[idx]; @@ -58,7 +49,6 @@ namespace tp { } int1 memCompare(const void* left, const void* right, uhalni len) { - MODULE_SANITY_CHECK(gModuleBase) if (!len) return 0; ualni alignedLength = len / sizeof(alni); @@ -88,7 +78,6 @@ namespace tp { bool memEqual(const void* left, const void* right, uhalni len) { return memCompare(left, right, len) == 0; } int1 memCompareVal(const void* left, uhalni len, uint1 val) { - MODULE_SANITY_CHECK(gModuleBase) if (!len) return 0; alni valAligned = val; diff --git a/Modules/public/Module.hpp b/Modules/public/Module.hpp index ef11973..06d29a7 100644 --- a/Modules/public/Module.hpp +++ b/Modules/public/Module.hpp @@ -30,6 +30,4 @@ namespace tp { uhalni mInitCount = 0; void* mCustomData = nullptr; }; - - extern ModuleManifest gModuleBase; }; diff --git a/Utils/public/Sorting.hpp b/Modules/public/Sorting.hpp similarity index 100% rename from Utils/public/Sorting.hpp rename to Modules/public/Sorting.hpp diff --git a/Utils/public/Timing.hpp b/Modules/public/Timing.hpp similarity index 100% rename from Utils/public/Timing.hpp rename to Modules/public/Timing.hpp diff --git a/Utils/public/Utils.hpp b/Modules/public/Utils.hpp similarity index 79% rename from Utils/public/Utils.hpp rename to Modules/public/Utils.hpp index 8d22934..eaa1c37 100644 --- a/Utils/public/Utils.hpp +++ b/Modules/public/Utils.hpp @@ -6,9 +6,6 @@ #define MEMBER_OFFSET(s, m) (alni(&(((s*) 0)->m))) namespace tp { - - extern ModuleManifest gModuleUtils; - void memSetVal(void* p, uhalni byteSize, uint1 val); void memCopy(void* left, const void* right, uhalni len); int1 memCompare(const void* left, const void* right, uhalni len); @@ -22,35 +19,6 @@ namespace tp { namespace tp { - template - class Pair { - public: - Pair() = default; - - template - Pair(U1 t1, U2 t2) : - head(static_cast(t1)), - tail(static_cast(t2)) {} - - union { - T1 t1; - T1 head; - T1 x; - T1 first; - }; - - union { - T2 t2; - T2 tail; - T2 y; - T2 second; - }; - - bool operator==(const Pair& in) const { return in.t1 == t1 && in.t2 == t2; } - - bool operator!=(const Pair& in) const { return !this->operator==(in); } - }; - template class Bits { Type mFlags = 0; diff --git a/Utils/tests/Tests.cpp b/Utils/tests/Tests.cpp deleted file mode 100644 index 540a478..0000000 --- a/Utils/tests/Tests.cpp +++ /dev/null @@ -1,65 +0,0 @@ - -#include "UnitTest++/UnitTest++.h" - -#include "Debugging.hpp" -#include "Utils.hpp" - -#include - -using namespace tp; - -void printSnapshot(const tp::CallStackCapture::CallStack* snapshot) { - printf("CallStack: \n"); - for (auto frame : *snapshot) { - auto symbols = gCSCapture->getSymbols(frame.getFrame()); - printf(" %s ----- %s:%llu\n", symbols->getFunc(), symbols->getFile(), symbols->getLine()); - } - printf("\n"); -} - -void common() { auto tmp = gCSCapture->getSnapshot(); } - -void first() { - common(); - common(); - common(); -} - -void second() { - common(); - common(); - common(); - common(); -} - -void third() { - common(); - common(); -} - -void root() { - first(); - second(); - third(); -} - -SUITE(Utils) { - TEST(CallStackCapture) { - tp::ModuleManifest* deps[] = { &tp::gModuleUtils, nullptr }; - tp::ModuleManifest testModule("UtilsTest", nullptr, nullptr, deps); - - REQUIRE CHECK(testModule.initialize()); - - root(); - - gCSCapture->logAll(); - - testModule.deinitialize(); - } - - TEST(CAllStackCaptureContent) { - CHECK(false); - } -} - -int main() { return UnitTest::RunAllTests(); } \ No newline at end of file