3
0

ErrorMessageFinder.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "ErrorMessageFinder.h"
  9. #include <gtest/gtest.h>
  10. #include <AzCore/UnitTest/UnitTest.h>
  11. #include <AzFramework/StringFunc/StringFunc.h>
  12. namespace UnitTest
  13. {
  14. ErrorMessageFinder::ErrorMessageFinder()
  15. {
  16. m_reportFailure = &ErrorMessageFinder::ReportFailure;
  17. AZ::Debug::TraceMessageBus::Handler::BusConnect();
  18. UnitTest::TestRunner::Instance().StartAssertTests();
  19. }
  20. ErrorMessageFinder::ErrorMessageFinder(AZStd::string_view message, uint32_t expectedCount)
  21. : ErrorMessageFinder()
  22. {
  23. AddExpectedErrorMessage(message, expectedCount);
  24. }
  25. ErrorMessageFinder::~ErrorMessageFinder()
  26. {
  27. if (!m_disabled)
  28. {
  29. Disable();
  30. }
  31. }
  32. void ErrorMessageFinder::Disable()
  33. {
  34. AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
  35. UnitTest::TestRunner::Instance().StopAssertTests();
  36. if (!m_checked)
  37. {
  38. CheckExpectedErrorsFound();
  39. }
  40. m_disabled = true;
  41. }
  42. void ErrorMessageFinder::AddExpectedErrorMessage(AZStd::string_view message, uint32_t expectedCount)
  43. {
  44. EXPECT_FALSE(m_disabled);
  45. if (expectedCount > 0)
  46. {
  47. ExpectedError expectedError;
  48. expectedError.m_message = message;
  49. expectedError.m_expectedCount = expectedCount;
  50. m_expectedErrors.push_back(expectedError);
  51. m_checked = false;
  52. }
  53. }
  54. void ErrorMessageFinder::AddIgnoredErrorMessage(AZStd::string_view message, bool matchSubstring)
  55. {
  56. EXPECT_FALSE(m_disabled);
  57. OptionalError optionalError;
  58. optionalError.m_message = message;
  59. optionalError.m_allowSubstring = matchSubstring;
  60. m_optionalErrors.push_back(optionalError);
  61. }
  62. void ErrorMessageFinder::CheckExpectedErrorsFound()
  63. {
  64. EXPECT_FALSE(m_disabled);
  65. for (auto expectedError : m_expectedErrors)
  66. {
  67. if (expectedError.m_expectedCount != expectedError.m_gotCount)
  68. {
  69. AZStd::string message = AZStd::string::format("Expected error %d time(s) but got %d time(s): '%s'", expectedError.m_expectedCount, expectedError.m_gotCount, expectedError.m_message.c_str());
  70. m_reportFailure(message);
  71. }
  72. }
  73. m_checked = true;
  74. }
  75. void ErrorMessageFinder::ReportFailure(const AZStd::string& failureMessage)
  76. {
  77. FAIL() << failureMessage.c_str();
  78. }
  79. void ErrorMessageFinder::Reset()
  80. {
  81. EXPECT_FALSE(m_disabled);
  82. m_expectedErrors.clear();
  83. m_optionalErrors.clear();
  84. m_checked = false;
  85. }
  86. void ErrorMessageFinder::ResetCounts()
  87. {
  88. EXPECT_FALSE(m_disabled);
  89. AZStd::for_each(m_expectedErrors.begin(), m_expectedErrors.end(), [](ExpectedError& expectedError) { expectedError.m_gotCount = 0; });
  90. m_checked = false;
  91. }
  92. bool ErrorMessageFinder::OnPreAssert(const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message)
  93. {
  94. return OnTrace(message);
  95. }
  96. bool ErrorMessageFinder::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message)
  97. {
  98. return OnTrace(message);
  99. }
  100. bool ErrorMessageFinder::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message)
  101. {
  102. return OnTrace(message);
  103. }
  104. bool ErrorMessageFinder::OnTrace(AZStd::string_view message)
  105. {
  106. bool found = false;
  107. for (auto expectedErrorIter = m_expectedErrors.begin(); expectedErrorIter != m_expectedErrors.end(); ++expectedErrorIter)
  108. {
  109. if (AzFramework::StringFunc::Find(message, expectedErrorIter->m_message) != AZStd::string::npos)
  110. {
  111. found = true;
  112. ++expectedErrorIter->m_gotCount;
  113. }
  114. }
  115. if (!found)
  116. {
  117. for (auto& optionalError : m_optionalErrors)
  118. {
  119. if (optionalError.m_message == message)
  120. {
  121. found = true;
  122. break;
  123. }
  124. else if (optionalError.m_allowSubstring && message.find(optionalError.m_message) != AZStd::string::npos)
  125. {
  126. found = true;
  127. break;
  128. }
  129. }
  130. }
  131. if (!found)
  132. {
  133. // We will return false below, but there are been times in the past when that did not trigger gtest failures
  134. // as expected, so we report the failure directly here. It might get reported again by another trace hander.
  135. AZStd::string fullMessage = AZStd::string::format("Detected unexpected error message: '%.*s'", AZ_STRING_ARG(message));
  136. m_reportFailure(fullMessage);
  137. }
  138. m_checked = false;
  139. return found;
  140. }
  141. }