Commit 5c438fac authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

logging: add XCHECK() and XDCHECK() macros

Summary:
This adds `XCHECK()` and `XDCHECK()` macros to the folly logging library.
These are similar to glog's `CHECK()` and `DCHECK()` macros, and should make
it easier for users to convert from glog to folly logging.

`XCHECK(condition)` is basically an alias for `XLOG_IF(FATAL, condition)`

`XDCHECK(condition)` is like `XCHECK(condition)` in non-debug builds, but is
compiled out entirely in debug builds.  Note that this is *not* like
`XLOG_IF(DFATAL, condition)`, which still evaluates the condition but avoids
crashing (logging the message only) in release builds.

Reviewed By: mnv104

Differential Revision: D8817270

fbshipit-source-id: 86c4575e11af37219b30eda4e7e30273e1e32ab1
parent e8c31188
...@@ -31,6 +31,12 @@ DEFINE_bool( ...@@ -31,6 +31,12 @@ DEFINE_bool(
DEFINE_bool(fail_fatal_xlog_if, false, "Fail an XLOG_IF(FATAL) check."); DEFINE_bool(fail_fatal_xlog_if, false, "Fail an XLOG_IF(FATAL) check.");
DEFINE_bool(fail_dfatal_xlog_if, false, "Fail an XLOG_IF(DFATAL) check."); DEFINE_bool(fail_dfatal_xlog_if, false, "Fail an XLOG_IF(DFATAL) check.");
DEFINE_bool(fail_xcheck, false, "Fail an XCHECK() test.");
DEFINE_bool(
fail_xcheck_nomsg,
false,
"Fail an XCHECK() test with no additional message.");
DEFINE_bool(fail_xdcheck, false, "Fail an XDCHECK() test.");
using folly::LogLevel; using folly::LogLevel;
...@@ -100,6 +106,9 @@ int main(int argc, char* argv[]) { ...@@ -100,6 +106,9 @@ int main(int argc, char* argv[]) {
XLOG_IF(FATAL, FLAGS_fail_fatal_xlog_if) << "--fail_fatal_xlog_if specified!"; XLOG_IF(FATAL, FLAGS_fail_fatal_xlog_if) << "--fail_fatal_xlog_if specified!";
XLOG_IF(DFATAL, FLAGS_fail_dfatal_xlog_if) XLOG_IF(DFATAL, FLAGS_fail_dfatal_xlog_if)
<< "--fail_dfatal_xlog_if specified!"; << "--fail_dfatal_xlog_if specified!";
XCHECK(!FLAGS_fail_xcheck) << ": --fail_xcheck specified!";
XCHECK(!FLAGS_fail_xcheck_nomsg);
XDCHECK(!FLAGS_fail_xdcheck) << ": --fail_xdcheck specified!";
// Do most of the work in a separate helper function. // Do most of the work in a separate helper function.
// //
......
...@@ -148,3 +148,35 @@ class FatalTests(unittest.TestCase): ...@@ -148,3 +148,35 @@ class FatalTests(unittest.TestCase):
self.assertEqual(-signal.SIGABRT, returncode) self.assertEqual(-signal.SIGABRT, returncode)
else: else:
self.assertEqual(0, returncode) self.assertEqual(0, returncode)
def test_xcheck(self):
# Specify --crash=no to ensure that the XCHECK() is actually what triggers the
# crash.
err = self.run_helper("--fail_xcheck", "--crash=no")
self.assertRegex(
err,
self.get_crash_regex(
b"Check failed: !FLAGS_fail_xcheck : --fail_xcheck specified!"
),
)
def test_xcheck_nomsg(self):
err = self.run_helper("--fail_xcheck_nomsg", "--crash=no")
self.assertRegex(
err, self.get_crash_regex(b"Check failed: !FLAGS_fail_xcheck_nomsg ")
)
def test_xdcheck(self):
returncode, out, err = self.run_helper_nochecks("--fail_xdcheck", "--crash=no")
self.assertEqual(b"", out)
if self.is_debug_build():
self.assertRegex(
err,
self.get_crash_regex(
b"Check failed: !FLAGS_fail_xdcheck : --fail_xdcheck specified!"
),
)
self.assertEqual(-signal.SIGABRT, returncode)
else:
self.assertEqual(b"", err)
self.assertEqual(0, returncode)
...@@ -321,6 +321,30 @@ ...@@ -321,6 +321,30 @@
} \ } \
} }
/**
* Assert that a condition is true.
*
* This crashes the program with an XLOG(FATAL) message if the condition is
* false. Unlike assert() CHECK statements are always enabled, regardless of
* the setting of NDEBUG.
*/
#define XCHECK(cond, ...) \
XLOG_IF(FATAL, UNLIKELY(!(cond)), "Check failed: " #cond " ", ##__VA_ARGS__)
/**
* Assert that a condition is true in non-debug builds.
*
* When NDEBUG is set this behaves like XDCHECK()
* When NDEBUG is not defined XDCHECK statements are not evaluated and will
* never log.
*
* You can use `XLOG_IF(DFATAL, condition)` instead if you want the condition to
* be evaluated in release builds but log a message without crashing the
* program.
*/
#define XDCHECK(cond, ...) \
(!::folly::kIsDebug) ? static_cast<void>(0) : XCHECK(cond, ##__VA_ARGS__)
/** /**
* XLOG_IS_IN_HEADER_FILE evaluates to false if we can definitively tell if we * XLOG_IS_IN_HEADER_FILE evaluates to false if we can definitively tell if we
* are not in a header file. Otherwise, it evaluates to true. * are not in a header file. Otherwise, it evaluates to true.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment