blob: f5f8253f8040d5a5c0490b8d6ce3cfa1badb04b9 [file] [log] [blame]
Eric Fiselierb08d8b12016-07-19 23:07:03 +00001#ifndef CHECK_H_
2#define CHECK_H_
3
Eric Fiselierfcafd3e2018-07-10 04:02:00 +00004#include <cmath>
Eric Fiselierb08d8b12016-07-19 23:07:03 +00005#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() {
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000017 static AbortHandlerT* handler = &std::abort;
18 return handler;
Eric Fiselierb08d8b12016-07-19 23:07:03 +000019}
20
21BENCHMARK_NORETURN inline void CallAbortHandler() {
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000022 GetAbortHandler()();
23 std::abort(); // fallback to enforce noreturn
Eric Fiselierb08d8b12016-07-19 23:07:03 +000024}
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.
28class CheckHandler {
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000029 public:
Eric Fiselierb08d8b12016-07-19 23:07:03 +000030 CheckHandler(const char* check, const char* file, const char* func, int line)
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000031 : log_(GetErrorLogInstance()) {
32 log_ << file << ":" << line << ": " << func << ": Check `" << check
33 << "' failed. ";
Eric Fiselierb08d8b12016-07-19 23:07:03 +000034 }
35
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000036 LogType& GetLog() { return log_; }
Eric Fiselierb08d8b12016-07-19 23:07:03 +000037
38 BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000039 log_ << std::endl;
40 CallAbortHandler();
Eric Fiselierb08d8b12016-07-19 23:07:03 +000041 }
42
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000043 CheckHandler& operator=(const CheckHandler&) = delete;
Eric Fiselierb08d8b12016-07-19 23:07:03 +000044 CheckHandler(const CheckHandler&) = delete;
45 CheckHandler() = delete;
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000046
47 private:
48 LogType& log_;
Eric Fiselierb08d8b12016-07-19 23:07:03 +000049};
50
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000051} // end namespace internal
52} // end namespace benchmark
Eric Fiselierb08d8b12016-07-19 23:07:03 +000053
54// The CHECK macro returns a std::ostream object that can have extra information
55// written to it.
56#ifndef NDEBUG
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000057#define CHECK(b) \
58 (b ? ::benchmark::internal::GetNullLogInstance() \
59 : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
60 .GetLog())
Eric Fiselierb08d8b12016-07-19 23:07:03 +000061#else
Eric Fiselierfbc9ff22016-11-05 00:30:27 +000062#define CHECK(b) ::benchmark::internal::GetNullLogInstance()
Eric Fiselierb08d8b12016-07-19 23:07:03 +000063#endif
64
Eric Fiselierfcafd3e2018-07-10 04:02:00 +000065// clang-format off
66// preserve whitespacing between operators for alignment
Eric Fiselierb08d8b12016-07-19 23:07:03 +000067#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
Eric Fiselier19039762018-01-18 04:23:01 +000074#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))
Eric Fiselierfcafd3e2018-07-10 04:02:00 +000080//clang-format on
Eric Fiselier19039762018-01-18 04:23:01 +000081
Eric Fiselierb08d8b12016-07-19 23:07:03 +000082#endif // CHECK_H_