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
import re
import signal
import subprocess
import sys
import unittest
......@@ -209,6 +210,23 @@ class FatalTests(unittest.TestCase):
expected_msg = "Check failed: ++x == 7 (6 vs. 7)"
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(
self, flag, value, op, extra_msg=" extra user args", expect_failure=True
):
......
......@@ -56,6 +56,15 @@ DEFINE_bool(
test_xcheck_eq_evalutates_once,
false,
"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;
......@@ -111,6 +120,18 @@ std::string fbLogFatalCheck() {
// 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.
*/
......@@ -148,6 +169,14 @@ int main(int argc, char* argv[]) {
int x = 5;
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.
//
......
......@@ -21,6 +21,7 @@
#include <folly/logging/LogStream.h>
#include <folly/logging/Logger.h>
#include <folly/logging/LoggerDB.h>
#include <folly/logging/ObjectToString.h>
#include <folly/logging/RateLimiter.h>
#include <cstdlib>
......@@ -370,7 +371,13 @@ std::unique_ptr<std::string> XCheckOpImpl(
return nullptr;
}
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 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