diff options
| author | EPICGAMES\thierry.begin <[email protected]> | 2024-04-08 10:43:16 -0400 |
|---|---|---|
| committer | EPICGAMES\thierry.begin <[email protected]> | 2024-04-08 10:43:16 -0400 |
| commit | b35e1258a043cab06950b2453f434861d99b918a (patch) | |
| tree | 695737774fa08ebaa0e32a9f95cb0247c34b3dc3 /src/zencore/zencore.cpp | |
| parent | Add docker support (diff) | |
| parent | Merge pull request #41 from ue-foundation/zs/import-oplog-clean (diff) | |
| download | zen-tb/docker.tar.xz zen-tb/docker.zip | |
Merge branch 'main' of https://github.ol.epicgames.net/ue-foundation/zen into tb/dockertb/docker
Diffstat (limited to 'src/zencore/zencore.cpp')
| -rw-r--r-- | src/zencore/zencore.cpp | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/src/zencore/zencore.cpp b/src/zencore/zencore.cpp index c97f5e5ca..c4fcc89de 100644 --- a/src/zencore/zencore.cpp +++ b/src/zencore/zencore.cpp @@ -6,12 +6,9 @@ # include <zencore/windows.h> #endif -#if ZEN_PLATFORM_LINUX -# include <pthread.h> -#endif - #include <zencore/assertfmt.h> #include <zencore/blake3.h> +#include <zencore/callstack.h> #include <zencore/compactbinary.h> #include <zencore/compactbinarybuilder.h> #include <zencore/compactbinarypackage.h> @@ -55,10 +52,59 @@ ExecAssertFmt(const char* Filename, int LineNumber, const char* FunctionName, st namespace zen { +AssertException::AssertException(const AssertException& Rhs) noexcept : _Mybase(Rhs), _Callstack(CloneCallstack(Rhs._Callstack)) +{ +} + +AssertException::AssertException(AssertException&& Rhs) noexcept : _Mybase(Rhs), _Callstack(Rhs._Callstack) +{ + Rhs._Callstack = nullptr; +} + +AssertException::~AssertException() noexcept +{ + FreeCallstack(_Callstack); +} + +AssertException& +AssertException::operator=(const AssertException& Rhs) noexcept +{ + _Mybase::operator=(Rhs); + + CallstackFrames* Callstack = CloneCallstack(Rhs._Callstack); + std::swap(_Callstack, Callstack); + FreeCallstack(Callstack); + return *this; +} + +std::string +AssertException::FullDescription() const noexcept +{ + if (_Callstack) + { + return fmt::format("'{}'\n{}", what(), CallstackToString(_Callstack)); + } + return what(); +} + +void +AssertImpl::ThrowAssertException(const char* Filename, int LineNumber, const char* FunctionName, const char* Msg) +{ + ZEN_UNUSED(FunctionName); + fmt::basic_memory_buffer<char, 2048> Message; + auto Appender = fmt::appender(Message); + fmt::format_to(Appender, "{}({}): {}", Filename, LineNumber, Msg); + Message.push_back('\0'); + + void* Frames[8]; + uint32_t FrameCount = GetCallstack(3, 8, Frames); + throw AssertException(Message.data(), CreateCallstack(FrameCount, Frames)); +} + void refcount_forcelink(); +AssertImpl* AssertImpl::CurrentAssertImpl = nullptr; AssertImpl AssertImpl::DefaultAssertImpl; -AssertImpl* AssertImpl::CurrentAssertImpl = &AssertImpl::DefaultAssertImpl; ////////////////////////////////////////////////////////////////////////// @@ -138,6 +184,7 @@ void zencore_forcelinktests() { zen::blake3_forcelink(); + zen::callstack_forcelink(); zen::compositebuffer_forcelink(); zen::compress_forcelink(); zen::crypto_forcelink(); @@ -174,24 +221,24 @@ TEST_SUITE_BEGIN("core.assert"); TEST_CASE("Assert.Default") { - bool A = true; - bool B = false; - CHECK_THROWS_WITH(ZEN_ASSERT(A == B), "A == B"); + bool A = true; + bool B = false; + std::string Expected = fmt::format("{}({}): {}", __FILE__, __LINE__ + 1, "A == B"); + CHECK_THROWS_WITH(ZEN_ASSERT(A == B), Expected.c_str()); } TEST_CASE("Assert.Format") { - bool A = true; - bool B = false; - CHECK_THROWS_WITH(ZEN_ASSERT_FORMAT(A == B, "{} == {}", A, B), "assert(A == B) failed: true == false"); + bool A = true; + bool B = false; + std::string Expected = fmt::format("{}({}): {}", __FILE__, __LINE__ + 1, "assert(A == B) failed: true == false"); + CHECK_THROWS_WITH(ZEN_ASSERT_FORMAT(A == B, "{} == {}", A, B), Expected.c_str()); } TEST_CASE("Assert.Custom") { struct MyAssertImpl : AssertImpl { - ZEN_FORCENOINLINE ZEN_DEBUG_SECTION MyAssertImpl() : PrevAssertImpl(CurrentAssertImpl) { CurrentAssertImpl = this; } - virtual ZEN_FORCENOINLINE ZEN_DEBUG_SECTION ~MyAssertImpl() { CurrentAssertImpl = PrevAssertImpl; } virtual void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION OnAssert(const char* Filename, int LineNumber, const char* FunctionName, @@ -202,7 +249,7 @@ TEST_CASE("Assert.Custom") FuncName = FunctionName; Message = Msg; } - AssertImpl* PrevAssertImpl; + AssertImpl* PrevAssertImpl = nullptr; const char* AssertFileName = nullptr; int Line = -1; @@ -213,13 +260,47 @@ TEST_CASE("Assert.Custom") MyAssertImpl MyAssert; bool A = true; bool B = false; - CHECK_THROWS_WITH(ZEN_ASSERT(A == B), "A == B"); + CHECK_THROWS_WITH(ZEN_ASSERT(A == B), std::string(fmt::format("{}({}): {}", __FILE__, __LINE__, "A == B")).c_str()); CHECK(MyAssert.AssertFileName != nullptr); CHECK(MyAssert.Line != -1); CHECK(MyAssert.FuncName != nullptr); CHECK(strcmp(MyAssert.Message, "A == B") == 0); } +TEST_CASE("Assert.Callstack") +{ + try + { + ZEN_ASSERT(false); + } + catch (const AssertException& Assert) + { + ZEN_INFO("Assert failed: {}", Assert.what()); + CHECK(Assert._Callstack->FrameCount > 0); + CHECK(Assert._Callstack->Frames != nullptr); + ZEN_INFO("Callstack:\n{}", CallstackToString(Assert._Callstack)); + } + + WorkerThreadPool Pool(1); + auto Task = Pool.EnqueueTask(std::packaged_task<int()>{[] { + ZEN_ASSERT(false); + return 1; + }}); + + try + { + (void)Task.get(); + CHECK(false); + } + catch (const AssertException& Assert) + { + ZEN_INFO("Assert in future: {}", Assert.what()); + CHECK(Assert._Callstack->FrameCount > 0); + CHECK(Assert._Callstack->Frames != nullptr); + ZEN_INFO("Callstack:\n{}", CallstackToString(Assert._Callstack)); + } +} + TEST_SUITE_END(); #endif |