Add interface to allow disabling global AZ Core test environment trace bus suppression (#5594)
* Add interface to allow disabling global AZ Core test environment trace bus suppression Update BaseAssetManagerTest class to disable the suppression by default Update specific asset manager tests that rely on the trace bus suppression to ReEnable it Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Remove nodiscard Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Remove unique_ptr for disable token Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix move operator Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Switch to having individual flags for suppression of each type of output Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add cvar to force stacktrace output. Clean up whitespace Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>
This commit is contained in:
@@ -78,6 +78,7 @@ namespace AZ::Debug
|
||||
constexpr LogLevel DefaultLogLevel = LogLevel::Info;
|
||||
|
||||
AZ_CVAR_SCOPED(int, bg_traceLogLevel, DefaultLogLevel, nullptr, ConsoleFunctorFlags::Null, "Enable trace message logging in release mode. 0=disabled, 1=errors, 2=warnings, 3=info.");
|
||||
AZ_CVAR_SCOPED(bool, bg_alwaysShowCallstack, false, nullptr, ConsoleFunctorFlags::Null, "Force stack trace output without allowing ebus interception.");
|
||||
|
||||
/**
|
||||
* If any listener returns true, store the result so we don't outputs detailed information.
|
||||
@@ -279,6 +280,13 @@ namespace AZ::Debug
|
||||
|
||||
TraceMessageResult result;
|
||||
EBUS_EVENT_RESULT(result, TraceMessageBus, OnPreAssert, fileName, line, funcName, message);
|
||||
|
||||
if (bg_alwaysShowCallstack)
|
||||
{
|
||||
// If we're always showing the callstack, print it now before there's any chance of an ebus handler interrupting
|
||||
PrintCallstack(g_dbgSystemWnd, 1);
|
||||
}
|
||||
|
||||
if (result.m_value)
|
||||
{
|
||||
g_alreadyHandlingAssertOrFatal = false;
|
||||
@@ -304,7 +312,10 @@ namespace AZ::Debug
|
||||
}
|
||||
|
||||
Output(g_dbgSystemWnd, "------------------------------------------------\n");
|
||||
PrintCallstack(g_dbgSystemWnd, 1);
|
||||
if (!bg_alwaysShowCallstack)
|
||||
{
|
||||
PrintCallstack(g_dbgSystemWnd, 1);
|
||||
}
|
||||
Output(g_dbgSystemWnd, "==================================================================\n");
|
||||
|
||||
char dialogBoxText[g_maxMessageLength];
|
||||
@@ -529,6 +540,16 @@ namespace AZ::Debug
|
||||
}
|
||||
}
|
||||
|
||||
RawOutput(window, message);
|
||||
}
|
||||
|
||||
void Trace::RawOutput(const char* window, const char* message)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
window = g_dbgSystemWnd;
|
||||
}
|
||||
|
||||
// printf on Windows platforms seem to have a buffer length limit of 4096 characters
|
||||
// Therefore fwrite is used directly to write the window and message to stdout
|
||||
AZStd::string_view windowView{ window };
|
||||
@@ -572,9 +593,19 @@ namespace AZ::Debug
|
||||
}
|
||||
|
||||
azstrcat(lines[i], AZ_ARRAY_SIZE(lines[i]), "\n");
|
||||
|
||||
// Use Output instead of AZ_Printf to be consistent with the exception output code and avoid
|
||||
// this accidentally being suppressed as a normal message
|
||||
Output(window, lines[i]);
|
||||
|
||||
if (bg_alwaysShowCallstack)
|
||||
{
|
||||
// Use Raw Output as this cannot be suppressed
|
||||
RawOutput(window, lines[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output(window, lines[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,9 @@ namespace AZ
|
||||
|
||||
static void Output(const char* window, const char* message);
|
||||
|
||||
/// Called by output to handle the actual output, does not interact with ebus or allow interception
|
||||
static void RawOutput(const char* window, const char* message);
|
||||
|
||||
static void PrintCallstack(const char* window, unsigned int suppressCount = 0, void* nativeContext = 0);
|
||||
|
||||
/// PEXCEPTION_POINTERS on Windows, always NULL on other platforms
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace UnitTest
|
||||
m_isAssertTest = true;
|
||||
m_numAssertsFailed = 0;
|
||||
}
|
||||
|
||||
int StopAssertTests()
|
||||
{
|
||||
m_isAssertTest = false;
|
||||
@@ -69,6 +70,11 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
bool m_isAssertTest;
|
||||
bool m_suppressErrors = true;
|
||||
bool m_suppressWarnings = true;
|
||||
bool m_suppressAsserts = true;
|
||||
bool m_suppressOutput = true;
|
||||
bool m_suppressPrintf = true;
|
||||
int m_numAssertsFailed;
|
||||
};
|
||||
|
||||
@@ -114,7 +120,7 @@ namespace UnitTest
|
||||
|
||||
// utility classes that you can derive from or contain, which suppress AZ_Asserts
|
||||
// and AZ_Errors to the below macros (processAssert, etc)
|
||||
// If TraceBusHook or TraceBusRedirector have been started in your unit tests,
|
||||
// If TraceBusHook or TraceBusRedirector have been started in your unit tests,
|
||||
// use AZ_TEST_START_TRACE_SUPPRESSION and AZ_TEST_STOP_TRACE_SUPPRESSION(numExpectedAsserts) macros to perform AZ_Assert and AZ_Error suppression
|
||||
class TraceBusRedirector
|
||||
: public AZ::Debug::TraceMessageBus::Handler
|
||||
@@ -124,16 +130,19 @@ namespace UnitTest
|
||||
if (UnitTest::TestRunner::Instance().m_isAssertTest)
|
||||
{
|
||||
UnitTest::TestRunner::Instance().ProcessAssert(message, file, line, false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
else if (UnitTest::TestRunner::Instance().m_suppressAsserts)
|
||||
{
|
||||
GTEST_MESSAGE_AT_(file, line, message, ::testing::TestPartResult::kNonFatalFailure);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
bool OnAssert(const char* /*message*/) override
|
||||
{
|
||||
return true; // stop processing
|
||||
return UnitTest::TestRunner::Instance().m_suppressAsserts; // stop processing
|
||||
}
|
||||
bool OnPreError(const char* /*window*/, const char* file, int line, const char* /*func*/, const char* message) override
|
||||
{
|
||||
@@ -142,6 +151,7 @@ namespace UnitTest
|
||||
UnitTest::TestRunner::Instance().ProcessAssert(message, file, line, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool OnError(const char* /*window*/, const char* message) override
|
||||
@@ -149,12 +159,15 @@ namespace UnitTest
|
||||
if (UnitTest::TestRunner::Instance().m_isAssertTest)
|
||||
{
|
||||
UnitTest::TestRunner::Instance().ProcessAssert(message, __FILE__, __LINE__, UnitTest::AssertionExpr(false));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
else if (UnitTest::TestRunner::Instance().m_suppressErrors)
|
||||
{
|
||||
GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure);
|
||||
return true;
|
||||
}
|
||||
return true; // stop processing
|
||||
|
||||
return false;
|
||||
}
|
||||
bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override
|
||||
{
|
||||
@@ -163,21 +176,21 @@ namespace UnitTest
|
||||
}
|
||||
bool OnWarning(const char* /*window*/, const char* /*message*/) override
|
||||
{
|
||||
return true;
|
||||
return UnitTest::TestRunner::Instance().m_suppressWarnings;
|
||||
}
|
||||
|
||||
bool OnOutput(const char* /*window*/, const char* /*message*/) override
|
||||
{
|
||||
return true;
|
||||
return UnitTest::TestRunner::Instance().m_suppressOutput;
|
||||
}
|
||||
|
||||
bool OnPrintf(const char* window, const char* message) override
|
||||
{
|
||||
if (AZStd::string_view(window) == "Memory") // We want to print out the memory leak's stack traces
|
||||
{
|
||||
ColoredPrintf(COLOR_RED, "[ MEMORY ] %s", message);
|
||||
ColoredPrintf(COLOR_RED, "[ MEMORY ] %s", message);
|
||||
}
|
||||
return true;
|
||||
return UnitTest::TestRunner::Instance().m_suppressPrintf;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -259,7 +272,6 @@ namespace UnitTest
|
||||
bool m_environmentSetup = false;
|
||||
bool m_createdAllocator = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -608,24 +608,9 @@ namespace UnitTest
|
||||
AZ::Data::AssetData::AssetStatus expected_base_status = AZ::Data::AssetData::AssetStatus::Ready;
|
||||
EXPECT_EQ(baseStatus, expected_base_status);
|
||||
}
|
||||
|
||||
struct DebugListener : AZ::Interface<IDebugAssetEvent>::Registrar
|
||||
{
|
||||
void AssetStatusUpdate(AZ::Data::AssetId id, AZ::Data::AssetData::AssetStatus status) override
|
||||
{
|
||||
AZ::Debug::Trace::Output(
|
||||
"", AZStd::string::format("Status %s - %d\n", id.ToString<AZStd::string>().c_str(), static_cast<int>(status)).c_str());
|
||||
}
|
||||
void ReleaseAsset(AZ::Data::AssetId id) override
|
||||
{
|
||||
AZ::Debug::Trace::Output(
|
||||
"", AZStd::string::format("Release %s\n", id.ToString<AZStd::string>().c_str()).c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_F(AssetJobsFloodTest, RapidAcquireAndRelease)
|
||||
{
|
||||
DebugListener listener;
|
||||
auto assetUuids = {
|
||||
MyAsset1Id,
|
||||
MyAsset2Id,
|
||||
|
||||
@@ -67,7 +67,10 @@ namespace UnitTest
|
||||
{
|
||||
SerializeContextFixture::SetUp();
|
||||
|
||||
SuppressTraceOutput(false);
|
||||
|
||||
AZ::JobManagerDesc jobDesc;
|
||||
|
||||
AZ::JobManagerThreadDesc threadDesc;
|
||||
for (size_t threadCount = 0; threadCount < GetNumJobManagerThreads(); threadCount++)
|
||||
{
|
||||
@@ -111,9 +114,21 @@ namespace UnitTest
|
||||
delete m_jobContext;
|
||||
delete m_jobManager;
|
||||
|
||||
// Reset back to default suppression settings to avoid affecting other tests
|
||||
SuppressTraceOutput(true);
|
||||
|
||||
SerializeContextFixture::TearDown();
|
||||
}
|
||||
|
||||
void BaseAssetManagerTest::SuppressTraceOutput(bool suppress)
|
||||
{
|
||||
UnitTest::TestRunner::Instance().m_suppressAsserts = suppress;
|
||||
UnitTest::TestRunner::Instance().m_suppressErrors = suppress;
|
||||
UnitTest::TestRunner::Instance().m_suppressWarnings = suppress;
|
||||
UnitTest::TestRunner::Instance().m_suppressPrintf = suppress;
|
||||
UnitTest::TestRunner::Instance().m_suppressOutput = suppress;
|
||||
}
|
||||
|
||||
void BaseAssetManagerTest::WriteAssetToDisk(const AZStd::string& assetName, [[maybe_unused]] const AZStd::string& assetIdGuid)
|
||||
{
|
||||
AZStd::string assetFileName = GetTestFolderPath() + assetName;
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace UnitTest
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
static void SuppressTraceOutput(bool suppress);
|
||||
|
||||
// Helper methods to create and destroy actual assets on the disk for true end-to-end asset loading.
|
||||
void WriteAssetToDisk(const AZStd::string& assetName, const AZStd::string& assetIdGuid);
|
||||
void DeleteAssetFromDisk(const AZStd::string& assetName);
|
||||
|
||||
Reference in New Issue
Block a user