Trace.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 <AzCore/UnitTest/TestTypes.h>
  9. #include <AzCore/Console/Console.h>
  10. #include <AzCore/Console/IConsole.h>
  11. #include <AzCore/Interface/Interface.h>
  12. #include <AzCore/IO/SystemFile.h>
  13. namespace UnitTest
  14. {
  15. struct TraceTests
  16. : LeakDetectionFixture
  17. , AZ::Debug::TraceMessageBus::Handler
  18. {
  19. bool OnPreAssert(const char*, int, const char*, const char*) override
  20. {
  21. m_assert = true;
  22. return true;
  23. }
  24. bool OnPreError(const char*, const char*, int, const char*, const char*) override
  25. {
  26. m_error = true;
  27. return true;
  28. }
  29. bool OnPreWarning(const char*, const char*, int, const char*, const char*) override
  30. {
  31. m_warning = true;
  32. return true;
  33. }
  34. bool OnPrintf(const char*, const char*) override
  35. {
  36. m_printf = true;
  37. return true;
  38. }
  39. void SetUp() override
  40. {
  41. BusConnect();
  42. if (!AZ::Interface<AZ::IConsole>::Get())
  43. {
  44. m_console = aznew AZ::Console();
  45. m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
  46. AZ::Interface<AZ::IConsole>::Register(m_console);
  47. }
  48. AZ_TEST_START_TRACE_SUPPRESSION;
  49. }
  50. void TearDown() override
  51. {
  52. if (m_console)
  53. {
  54. AZ::Interface<AZ::IConsole>::Unregister(m_console);
  55. delete m_console;
  56. m_console = nullptr;
  57. }
  58. AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
  59. BusDisconnect();
  60. }
  61. bool m_assert = false;
  62. bool m_error = false;
  63. bool m_warning = false;
  64. bool m_printf = false;
  65. AZ::Console* m_console{ nullptr };
  66. };
  67. TEST_F(TraceTests, Level0)
  68. {
  69. AZ::Interface<AZ::IConsole>::Get()->PerformCommand("bg_traceLogLevel 0");
  70. AZ_Assert(false, "test");
  71. AZ_Error("UnitTest", false, "test");
  72. AZ_Warning("UnitTest", false, "test");
  73. AZ_TracePrintf("UnitTest", "test");
  74. ASSERT_TRUE(m_assert);
  75. ASSERT_FALSE(m_error);
  76. ASSERT_FALSE(m_warning);
  77. ASSERT_FALSE(m_printf);
  78. }
  79. TEST_F(TraceTests, Level1)
  80. {
  81. AZ::Interface<AZ::IConsole>::Get()->PerformCommand("bg_traceLogLevel 1");
  82. AZ_Assert(false, "test");
  83. AZ_Error("UnitTest", false, "test");
  84. AZ_Warning("UnitTest", false, "test");
  85. AZ_TracePrintf("UnitTest", "test");
  86. ASSERT_TRUE(m_assert);
  87. ASSERT_TRUE(m_error);
  88. ASSERT_FALSE(m_warning);
  89. ASSERT_FALSE(m_printf);
  90. }
  91. TEST_F(TraceTests, Level2)
  92. {
  93. AZ::Interface<AZ::IConsole>::Get()->PerformCommand("bg_traceLogLevel 2");
  94. AZ_Assert(false, "test");
  95. AZ_Error("UnitTest", false, "test");
  96. AZ_Warning("UnitTest", false, "test");
  97. AZ_TracePrintf("UnitTest", "test");
  98. ASSERT_TRUE(m_assert);
  99. ASSERT_TRUE(m_error);
  100. ASSERT_TRUE(m_warning);
  101. ASSERT_FALSE(m_printf);
  102. }
  103. TEST_F(TraceTests, Level3)
  104. {
  105. AZ::Interface<AZ::IConsole>::Get()->PerformCommand("bg_traceLogLevel 3");
  106. AZ_Assert(false, "test");
  107. AZ_Error("UnitTest", false, "test");
  108. AZ_Warning("UnitTest", false, "test");
  109. AZ_TracePrintf("UnitTest", "test");
  110. ASSERT_TRUE(m_assert);
  111. ASSERT_TRUE(m_error);
  112. ASSERT_TRUE(m_warning);
  113. ASSERT_TRUE(m_printf);
  114. }
  115. TEST_F(TraceTests, RedirectRawOutputToStderr_DoesNotOutputToStdout)
  116. {
  117. // Invoke the Trace::Init() function to create AZ environment variables
  118. auto& traceInstance = AZ::Debug::Trace::Instance();
  119. traceInstance.Init();
  120. constexpr const char* errorMessage = "Test Error\n";
  121. bool testErrorMessageFound{};
  122. auto GetStdout = [&testErrorMessageFound, expectedMessage = errorMessage](AZStd::span<const AZStd::byte> capturedBytes)
  123. {
  124. if (AZStd::string_view capturedStrView(reinterpret_cast<const char*>(capturedBytes.data()), capturedBytes.size());
  125. capturedStrView.contains(expectedMessage))
  126. {
  127. testErrorMessageFound = true;
  128. }
  129. };
  130. // file descriptor 1 is stdout
  131. constexpr int StdoutDescriptor = 1;
  132. AZ::IO::FileDescriptorCapturer capturer(StdoutDescriptor);
  133. capturer.Start(GetStdout);
  134. // This message should get captured
  135. AZ::Debug::Trace::Instance().RawOutput("UnitTest", errorMessage);
  136. fflush(stdout);
  137. capturer.Stop();
  138. // The message should be found
  139. EXPECT_TRUE(testErrorMessageFound);
  140. // Reset the error message found boolean back to false
  141. testErrorMessageFound = false;
  142. // Redirect the Trace output to stderr
  143. AZ::Interface<AZ::IConsole>::Get()->PerformCommand({ "bg_redirectrawoutput", "1" });
  144. AZ::Debug::Trace::Instance().RawOutput("UnitTest", errorMessage);
  145. fflush(stdout);
  146. // The message should not be found since trace output should be going to stderr
  147. EXPECT_FALSE(testErrorMessageFound);
  148. // Redirect the Trace output back to stdout
  149. AZ::Interface<AZ::IConsole>::Get()->PerformCommand({ "bg_redirectrawoutput", "0" });
  150. // Destroy created AZ Environment Variables for the Trace system
  151. traceInstance.Destroy();
  152. }
  153. TEST_F(TraceTests, RedirectRawOutputToDevNull_DoesNotOutputToStdout_NorStderr)
  154. {
  155. // Invoke the Trace::Init() function to create AZ environment variables
  156. auto& traceInstance = AZ::Debug::Trace::Instance();
  157. traceInstance.Init();
  158. constexpr const char* errorMessage = "Test Error\n";
  159. bool testErrorMessageFound{};
  160. auto GetOutput = [&testErrorMessageFound, expectedMessage = errorMessage](AZStd::span<const AZStd::byte> capturedBytes)
  161. {
  162. if (AZStd::string_view capturedStrView(reinterpret_cast<const char*>(capturedBytes.data()), capturedBytes.size());
  163. capturedStrView.contains(expectedMessage))
  164. {
  165. testErrorMessageFound = true;
  166. }
  167. };
  168. // file descriptor 1 is stdout
  169. constexpr int StdoutDescriptor = 1;
  170. // file descriptor 2 is stderr
  171. constexpr int StderrDescriptor = 2;
  172. AZ::IO::FileDescriptorCapturer stdoutCapturer(StdoutDescriptor);
  173. AZ::IO::FileDescriptorCapturer stderrCapturer(StderrDescriptor);
  174. stdoutCapturer.Start(GetOutput);
  175. stderrCapturer.Start(GetOutput);
  176. // This message should get captured
  177. AZ::Debug::Trace::Instance().RawOutput("UnitTest", errorMessage);
  178. // flush both stdout and stderr to make sure it capturer is able to get the data
  179. fflush(stdout);
  180. fflush(stderr);
  181. stdoutCapturer.Stop();
  182. stderrCapturer.Stop();
  183. // The message should be found
  184. EXPECT_TRUE(testErrorMessageFound);
  185. // Reset the error message found boolean back to false
  186. testErrorMessageFound = false;
  187. // Redirect the Trace output to None
  188. AZ::Interface<AZ::IConsole>::Get()->PerformCommand({ "bg_redirectrawoutput", "2" });
  189. // Restart the capture of stdout and stderr
  190. stdoutCapturer.Start(GetOutput);
  191. stderrCapturer.Start(GetOutput);
  192. AZ::Debug::Trace::Instance().RawOutput("UnitTest", errorMessage);
  193. fflush(stdout);
  194. fflush(stderr);
  195. stdoutCapturer.Stop();
  196. stderrCapturer.Stop();
  197. // The message should not be found since trace output should be output to the /dev/null or NUL device
  198. EXPECT_FALSE(testErrorMessageFound);
  199. // Redirect the Trace output back to stdout
  200. AZ::Interface<AZ::IConsole>::Get()->PerformCommand({ "bg_redirectrawoutput", "0" });
  201. traceInstance.Destroy();
  202. }
  203. }