Commit 83989dbc authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

logging: update XCHECK_EQ() to use objectToString()

Summary:
Update the `XCHECK_EQ()` macros to use `folly::logging::objectToString()` to
format the message on failure.

This ensures that `XCHECK_EQ()` will successfully compile and work with any
arguments.  Previously it would fail to compile if called with arguments that
did not work with `folly::to<std::string>()`

Reviewed By: chadaustin

Differential Revision: D14545301

fbshipit-source-id: 442657a1770f30cbf01462ad62d32301e60490e5
parent cc3025b7
...@@ -18,6 +18,7 @@ import os ...@@ -18,6 +18,7 @@ import os
import re import re
import signal import signal
import subprocess import subprocess
import sys
import unittest import unittest
...@@ -209,6 +210,23 @@ class FatalTests(unittest.TestCase): ...@@ -209,6 +210,23 @@ class FatalTests(unittest.TestCase):
expected_msg = "Check failed: ++x == 7 (6 vs. 7)" expected_msg = "Check failed: ++x == 7 (6 vs. 7)"
self.assertRegex(err, self.get_crash_regex(expected_msg.encode("utf-8"))) self.assertRegex(err, self.get_crash_regex(expected_msg.encode("utf-8")))
def test_xcheck_custom_object(self):
err = self.run_helper("--xcheck_eq_custom_struct")
if sys.byteorder == "little":
obj1_hexdump = "01 00 00 00 02 00 00 00"
obj2_hexdump = "01 00 00 00 ef cd ab 12"
else:
obj1_hexdump = "00 00 00 01 00 00 00 02"
obj2_hexdump = "00 00 00 01 12 ab cd ef"
expected_msg = (
"Check failed: MyStruct(1, 2) == m ("
f"[MyStruct of size 8: {obj1_hexdump}] vs. "
f"[MyStruct of size 8: {obj2_hexdump}]"
")"
)
self.assertRegex(err, self.get_crash_regex(expected_msg.encode("utf-8")))
def _test_xcheck_cmp( def _test_xcheck_cmp(
self, flag, value, op, extra_msg=" extra user args", expect_failure=True self, flag, value, op, extra_msg=" extra user args", expect_failure=True
): ):
......
...@@ -56,6 +56,15 @@ DEFINE_bool( ...@@ -56,6 +56,15 @@ DEFINE_bool(
test_xcheck_eq_evalutates_once, test_xcheck_eq_evalutates_once,
false, false,
"Test an XCHECK_EQ() statement where the arguments have side effects"); "Test an XCHECK_EQ() statement where the arguments have side effects");
DEFINE_bool(
xcheck_eq_custom_struct,
false,
"Test an XCHECK_EQ() statement with a custom structure, "
"to test log message formatting");
DEFINE_bool(
xcheck_eq_pointers,
false,
"Test an XCHECK_EQ() statement with pointer arguments");
using folly::LogLevel; using folly::LogLevel;
...@@ -111,6 +120,18 @@ std::string fbLogFatalCheck() { ...@@ -111,6 +120,18 @@ std::string fbLogFatalCheck() {
// about a missing return statement here. // about a missing return statement here.
} }
struct MyStruct {
MyStruct(uint32_t a, uint32_t b) : a(a), b(b) {}
uint32_t a;
uint32_t b;
};
bool operator==(const MyStruct& s1, const MyStruct& s2) {
return (s1.a == s2.a) && (s1.b == s2.b);
}
bool operator<=(const MyStruct& s1, const MyStruct& s2) {
return !(s1 == s2);
}
/* /*
* This is a simple helper program to exercise the LOG(FATAL) functionality. * This is a simple helper program to exercise the LOG(FATAL) functionality.
*/ */
...@@ -148,6 +169,14 @@ int main(int argc, char* argv[]) { ...@@ -148,6 +169,14 @@ int main(int argc, char* argv[]) {
int x = 5; int x = 5;
XCHECK_EQ(++x, 7); XCHECK_EQ(++x, 7);
} }
if (FLAGS_xcheck_eq_custom_struct) {
auto m = MyStruct(1, 0x12abcdef);
XCHECK_EQ(MyStruct(1, 2), m);
}
if (FLAGS_xcheck_eq_pointers) {
int localInt = 5;
XCHECK_EQ(&argc, &localInt);
}
// Do the remainder of the work in a separate helper function. // Do the remainder of the work in a separate helper function.
// //
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <folly/logging/LogStream.h> #include <folly/logging/LogStream.h>
#include <folly/logging/Logger.h> #include <folly/logging/Logger.h>
#include <folly/logging/LoggerDB.h> #include <folly/logging/LoggerDB.h>
#include <folly/logging/ObjectToString.h>
#include <folly/logging/RateLimiter.h> #include <folly/logging/RateLimiter.h>
#include <cstdlib> #include <cstdlib>
...@@ -370,7 +371,13 @@ std::unique_ptr<std::string> XCheckOpImpl( ...@@ -370,7 +371,13 @@ std::unique_ptr<std::string> XCheckOpImpl(
return nullptr; return nullptr;
} }
return std::make_unique<std::string>(folly::to<std::string>( return std::make_unique<std::string>(folly::to<std::string>(
"Check failed: ", checkStr, " (", arg1, " vs. ", arg2, ")")); "Check failed: ",
checkStr,
" (",
::folly::logging::objectToString(arg1),
" vs. ",
folly::logging::objectToString(arg2),
")"));
} }
} // namespace detail } // namespace detail
} // namespace folly } // namespace folly
......
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