1#ifndef CHECK_H_
2#define CHECK_H_
3
4#include <cmath>
5#include <cstdlib>
6#include <ostream>
7
8#include "internal_macros.h"
9#include "log.h"
10
11namespace benchmark {
12namespace internal {
13
14typedef void(AbortHandlerT)();
15
16inline AbortHandlerT*& GetAbortHandler() {
17 static AbortHandlerT* handler = &std::abort;
18 return handler;
19}
20
21BENCHMARK_NORETURN inline void CallAbortHandler() {
22 GetAbortHandler()();
23 std::abort(); // fallback to enforce noreturn
24}
25
26// CheckHandler is the class constructed by failing BM_CHECK macros.
27// CheckHandler will log information about the failures and abort when it is
28// destructed.
29class CheckHandler {
30 public:
31 CheckHandler(const char* check, const char* file, const char* func, int line)
32 : log_(GetErrorLogInstance()) {
33 log_ << file << ":" << line << ": " << func << ": Check `" << check
34 << "' failed. ";
35 }
36
37 LogType& GetLog() { return log_; }
38
39#if defined(COMPILER_MSVC)
40#pragma warning(push)
41#pragma warning(disable : 4722)
42#endif
43 BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
44 log_ << std::endl;
45 CallAbortHandler();
46 }
47#if defined(COMPILER_MSVC)
48#pragma warning(pop)
49#endif
50
51 CheckHandler& operator=(const CheckHandler&) = delete;
52 CheckHandler(const CheckHandler&) = delete;
53 CheckHandler() = delete;
54
55 private:
56 LogType& log_;
57};
58
59} // end namespace internal
60} // end namespace benchmark
61
62// The BM_CHECK macro returns a std::ostream object that can have extra
63// information written to it.
64#ifndef NDEBUG
65#define BM_CHECK(b) \
66 (b ? ::benchmark::internal::GetNullLogInstance() \
67 : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
68 .GetLog())
69#else
70#define BM_CHECK(b) ::benchmark::internal::GetNullLogInstance()
71#endif
72
73// clang-format off
74// preserve whitespacing between operators for alignment
75#define BM_CHECK_EQ(a, b) BM_CHECK((a) == (b))
76#define BM_CHECK_NE(a, b) BM_CHECK((a) != (b))
77#define BM_CHECK_GE(a, b) BM_CHECK((a) >= (b))
78#define BM_CHECK_LE(a, b) BM_CHECK((a) <= (b))
79#define BM_CHECK_GT(a, b) BM_CHECK((a) > (b))
80#define BM_CHECK_LT(a, b) BM_CHECK((a) < (b))
81
82#define BM_CHECK_FLOAT_EQ(a, b, eps) BM_CHECK(std::fabs((a) - (b)) < (eps))
83#define BM_CHECK_FLOAT_NE(a, b, eps) BM_CHECK(std::fabs((a) - (b)) >= (eps))
84#define BM_CHECK_FLOAT_GE(a, b, eps) BM_CHECK((a) - (b) > -(eps))
85#define BM_CHECK_FLOAT_LE(a, b, eps) BM_CHECK((b) - (a) > -(eps))
86#define BM_CHECK_FLOAT_GT(a, b, eps) BM_CHECK((a) - (b) > (eps))
87#define BM_CHECK_FLOAT_LT(a, b, eps) BM_CHECK((b) - (a) > (eps))
88//clang-format on
89
90#endif // CHECK_H_
91