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 
11 namespace benchmark {
12 namespace internal {
13 
14 typedef void(AbortHandlerT)();
15 
GetAbortHandler()16 inline AbortHandlerT*& GetAbortHandler() {
17   static AbortHandlerT* handler = &std::abort;
18   return handler;
19 }
20 
CallAbortHandler()21 BENCHMARK_NORETURN inline void CallAbortHandler() {
22   GetAbortHandler()();
23   std::abort();  // fallback to enforce noreturn
24 }
25 
26 // CheckHandler is the class constructed by failing CHECK macros. CheckHandler
27 // will log information about the failures and abort when it is destructed.
28 class CheckHandler {
29  public:
CheckHandler(const char * check,const char * file,const char * func,int line)30   CheckHandler(const char* check, const char* file, const char* func, int line)
31       : log_(GetErrorLogInstance()) {
32     log_ << file << ":" << line << ": " << func << ": Check `" << check
33          << "' failed. ";
34   }
35 
GetLog()36   LogType& GetLog() { return log_; }
37 
~CheckHandler()38   BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
39     log_ << std::endl;
40     CallAbortHandler();
41   }
42 
43   CheckHandler& operator=(const CheckHandler&) = delete;
44   CheckHandler(const CheckHandler&) = delete;
45   CheckHandler() = delete;
46 
47  private:
48   LogType& log_;
49 };
50 
51 }  // end namespace internal
52 }  // end namespace benchmark
53 
54 // The CHECK macro returns a std::ostream object that can have extra information
55 // written to it.
56 #ifndef NDEBUG
57 #define CHECK(b)                                                             \
58   (b ? ::benchmark::internal::GetNullLogInstance()                           \
59      : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
60            .GetLog())
61 #else
62 #define CHECK(b) ::benchmark::internal::GetNullLogInstance()
63 #endif
64 
65 // clang-format off
66 // preserve whitespacing between operators for alignment
67 #define CHECK_EQ(a, b) CHECK((a) == (b))
68 #define CHECK_NE(a, b) CHECK((a) != (b))
69 #define CHECK_GE(a, b) CHECK((a) >= (b))
70 #define CHECK_LE(a, b) CHECK((a) <= (b))
71 #define CHECK_GT(a, b) CHECK((a) > (b))
72 #define CHECK_LT(a, b) CHECK((a) < (b))
73 
74 #define CHECK_FLOAT_EQ(a, b, eps) CHECK(std::fabs((a) - (b)) <  (eps))
75 #define CHECK_FLOAT_NE(a, b, eps) CHECK(std::fabs((a) - (b)) >= (eps))
76 #define CHECK_FLOAT_GE(a, b, eps) CHECK((a) - (b) > -(eps))
77 #define CHECK_FLOAT_LE(a, b, eps) CHECK((b) - (a) > -(eps))
78 #define CHECK_FLOAT_GT(a, b, eps) CHECK((a) - (b) >  (eps))
79 #define CHECK_FLOAT_LT(a, b, eps) CHECK((b) - (a) >  (eps))
80 //clang-format on
81 
82 #endif  // CHECK_H_
83