Macros.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Andrew Kaster <akaster@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Assertions.h>
  9. #include <AK/CheckedFormatString.h>
  10. #include <AK/Math.h>
  11. #include <AK/SourceLocation.h>
  12. #include <LibTest/CrashTest.h>
  13. #include <LibTest/Randomized/RandomnessSource.h>
  14. #include <LibTest/TestResult.h>
  15. namespace Test {
  16. // Declare helpers so that we can call them from VERIFY in included headers
  17. // the setter for TestResult is already declared in TestResult.h
  18. TestResult current_test_result();
  19. Randomized::RandomnessSource& randomness_source();
  20. void set_randomness_source(Randomized::RandomnessSource);
  21. bool is_reporting_enabled();
  22. void enable_reporting();
  23. void disable_reporting();
  24. u64 randomized_runs();
  25. template<typename T>
  26. void expect(T const& expression, StringView expression_string, SourceLocation location = SourceLocation::current())
  27. {
  28. if (!static_cast<bool>(expression)) {
  29. if (is_reporting_enabled())
  30. warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT({}) failed", location.filename(), location.line_number(), expression_string);
  31. set_current_test_result(TestResult::Failed);
  32. }
  33. }
  34. template<typename LHS, typename RHS>
  35. void expect_equality(LHS const& lhs, RHS const& rhs, StringView lhs_string, StringView rhs_string, SourceLocation location = SourceLocation::current())
  36. {
  37. if (lhs != rhs) {
  38. if (is_reporting_enabled()) {
  39. warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={}",
  40. location.filename(), location.line_number(), lhs_string, rhs_string,
  41. FormatIfSupported { lhs }, FormatIfSupported { rhs });
  42. }
  43. set_current_test_result(TestResult::Failed);
  44. }
  45. }
  46. template<typename LHS, typename RHS>
  47. void expect_truthy_equality(LHS const& lhs, RHS const& rhs, StringView lhs_string, StringView rhs_string, SourceLocation location = SourceLocation::current())
  48. {
  49. if (static_cast<bool>(lhs) != static_cast<bool>(rhs)) {
  50. if (is_reporting_enabled()) {
  51. warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ_TRUTH({}, {}) failed with lhs={} ({}) and rhs={} ({})",
  52. location.filename(), location.line_number(), lhs_string, rhs_string,
  53. FormatIfSupported { lhs }, static_cast<bool>(lhs),
  54. FormatIfSupported { rhs }, static_cast<bool>(rhs));
  55. }
  56. set_current_test_result(TestResult::Failed);
  57. }
  58. }
  59. template<typename LHS, typename RHS>
  60. void expect_equality_with_forced_logging(LHS const& lhs, RHS const& rhs, StringView lhs_string, StringView rhs_string, SourceLocation location = SourceLocation::current())
  61. {
  62. if (lhs != rhs) {
  63. if (is_reporting_enabled()) {
  64. warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={}",
  65. location.filename(), location.line_number(), lhs_string, rhs_string,
  66. lhs, rhs);
  67. }
  68. set_current_test_result(TestResult::Failed);
  69. }
  70. }
  71. template<typename LHS, typename RHS>
  72. void expect_inequality(LHS const& lhs, RHS const& rhs, StringView lhs_string, StringView rhs_string, SourceLocation location = SourceLocation::current())
  73. {
  74. if (lhs == rhs) {
  75. if (is_reporting_enabled()) {
  76. warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_NE({}, {}) failed with lhs={} and rhs={}",
  77. location.filename(), location.line_number(), lhs_string, rhs_string,
  78. FormatIfSupported { lhs }, FormatIfSupported { rhs });
  79. }
  80. set_current_test_result(TestResult::Failed);
  81. }
  82. }
  83. template<FloatingPoint LHS, FloatingPoint RHS>
  84. void expect_approximate(LHS lhs, RHS rhs, StringView lhs_string, StringView rhs_string, double tolerance, SourceLocation location = SourceLocation::current())
  85. {
  86. auto diff = static_cast<double>(lhs) - static_cast<double>(rhs);
  87. if (AK::fabs(diff) > tolerance) {
  88. if (is_reporting_enabled()) {
  89. warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_APPROXIMATE({}, {}) failed with lhs={} and rhs={}, (lhs-rhs)={}",
  90. location.filename(), location.line_number(), lhs_string, rhs_string,
  91. lhs, rhs, diff);
  92. }
  93. set_current_test_result(TestResult::Failed);
  94. }
  95. }
  96. template<typename T>
  97. bool assume(T const& expression, StringView expression_string, SourceLocation location = SourceLocation::current())
  98. {
  99. if (!static_cast<bool>(expression)) {
  100. if (is_reporting_enabled()) {
  101. warnln("\033[31;1mREJECTED\033[0m: {}:{}: Couldn't generate random value satisfying ASSUME({})",
  102. location.filename(), location.line_number(), expression_string);
  103. }
  104. set_current_test_result(TestResult::Rejected);
  105. return false;
  106. }
  107. return true;
  108. }
  109. }
  110. #define EXPECT(x) \
  111. do { \
  112. ::Test::expect(x, #x##sv); \
  113. } while (false)
  114. #define EXPECT_EQ(a, b) \
  115. do { \
  116. ::Test::expect_equality(a, b, #a##sv, #b##sv); \
  117. } while (false)
  118. #define EXPECT_EQ_TRUTH(a, b) \
  119. do { \
  120. ::Test::expect_truthy_equality(a, b, #a##sv, #b##sv); \
  121. } while (false)
  122. // If you're stuck and `EXPECT_EQ` seems to refuse to print anything useful,
  123. // try this: It'll spit out a nice compiler error telling you why it doesn't print.
  124. #define EXPECT_EQ_FORCE(a, b) \
  125. do { \
  126. ::Test::expect_equality_with_forced_logging(a, b, #a##sv, #b##sv); \
  127. } while (false)
  128. #define EXPECT_NE(a, b) \
  129. do { \
  130. ::Test::expect_inequality(a, b, #a##sv, #b##sv); \
  131. } while (false)
  132. #define EXPECT_APPROXIMATE_WITH_ERROR(a, b, err) \
  133. do { \
  134. ::Test::expect_approximate(a, b, #a##sv, #b##sv, err); \
  135. } while (false)
  136. #define EXPECT_APPROXIMATE(a, b) EXPECT_APPROXIMATE_WITH_ERROR(a, b, 0.0000005)
  137. #define ASSUME(x) \
  138. do { \
  139. if (!::Test::assume(x, #x##sv)) \
  140. return; \
  141. } while (false)
  142. #define FAIL(message) \
  143. do { \
  144. if (::Test::is_reporting_enabled()) \
  145. ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: {}", __FILE__, __LINE__, message); \
  146. ::Test::set_current_test_result(::Test::TestResult::Failed); \
  147. } while (false)
  148. // To use, specify the lambda to execute in a sub process and verify it exits:
  149. // EXPECT_CRASH("This should fail", []{
  150. // return Test::Crash::Failure::DidNotCrash;
  151. // });
  152. #define EXPECT_CRASH(test_message, test_func) \
  153. do { \
  154. Test::Crash crash(test_message, test_func); \
  155. if (!crash.run()) \
  156. ::Test::set_current_test_result(::Test::TestResult::Failed); \
  157. } while (false)
  158. #define EXPECT_CRASH_WITH_SIGNAL(test_message, signal, test_func) \
  159. do { \
  160. Test::Crash crash(test_message, test_func, (signal)); \
  161. if (!crash.run()) \
  162. ::Test::set_current_test_result(::Test::TestResult::Failed); \
  163. } while (false)
  164. #define EXPECT_NO_CRASH(test_message, test_func) \
  165. do { \
  166. Test::Crash crash(test_message, test_func, 0); \
  167. if (!crash.run()) \
  168. ::Test::set_current_test_result(::Test::TestResult::Failed); \
  169. } while (false)
  170. #define TRY_OR_FAIL(expression) \
  171. ({ \
  172. /* Ignore -Wshadow to allow nesting the macro. */ \
  173. AK_IGNORE_DIAGNOSTIC("-Wshadow", \
  174. auto&& _temporary_result = (expression)); \
  175. static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
  176. "Do not return a reference from a fallible expression"); \
  177. if (_temporary_result.is_error()) [[unlikely]] { \
  178. FAIL(_temporary_result.release_error()); \
  179. return; \
  180. } \
  181. _temporary_result.release_value(); \
  182. })