From 3536becb819731f0c24a0b00f8c33d4136b257c5 Mon Sep 17 00:00:00 2001 From: Eugene Gershnik Date: Thu, 18 Jan 2024 13:19:18 -0800 Subject: [PATCH] XCTestUtil: using `__builtin_dump_struct` as a fallback to print object description --- include/objc-helpers/XCTestUtil.h | 32 +++++++++++++++++++++---------- test/XCTestUtilTests.mm | 2 +- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/objc-helpers/XCTestUtil.h b/include/objc-helpers/XCTestUtil.h index 38e1bad..9c18027 100644 --- a/include/objc-helpers/XCTestUtil.h +++ b/include/objc-helpers/XCTestUtil.h @@ -18,7 +18,8 @@ #import #include -#include +#include +#include namespace TestUtil { using std::to_string; @@ -40,14 +41,23 @@ namespace TestUtil { { str << obj }; }; - inline auto demangle(const char * name) -> std::string { - - int status = 0; - std::unique_ptr res { - abi::__cxa_demangle(name, nullptr, nullptr, &status), - std::free - }; - return (status==0) ? res.get() : name ; + auto sprintf(std::string & res, const char * format, ...) -> int { + va_list vl; + va_start(vl, format); + const int size = vsnprintf(0, 0, format, vl); + va_end(vl); + if (size <= 0) + return size; + size_t appendPos = res.size(); + size_t appendSize = size_t(size) + 1; + res.resize(appendPos + appendSize); + va_start(vl, format); + const int ret = vsnprintf(&res[appendPos], appendSize, format, vl); + va_end(vl); + if (ret <= 0) + return ret; + res.resize(appendPos + size_t(ret)); + return ret; } template @@ -64,7 +74,9 @@ namespace TestUtil { str << val; return @(str.str().c_str()); } else { - return [NSString stringWithFormat:@"%s object", demangle(typeid(T).name()).c_str()]; + std::string res; + __builtin_dump_struct(&val, sprintf, res); + return @(res.c_str()); } } } diff --git a/test/XCTestUtilTests.mm b/test/XCTestUtilTests.mm index fc56dbb..dc65de4 100644 --- a/test/XCTestUtilTests.mm +++ b/test/XCTestUtilTests.mm @@ -173,7 +173,7 @@ void _XCTFailureHandler(XCTestCase * _Nullable test, BOOL expected, const char * TEST_CASE( "Generic" ) { failures.clear(); XCTAssertCppEqual(bar{1}, bar{2}); - CHECK_FAILURE(__LINE__ - 1, true, "((bar{1}) equal to (bar{2})) failed: (\"(anonymous namespace)::bar object\") is not equal to (\"(anonymous namespace)::bar object\")", ""); + CHECK_FAILURE(__LINE__ - 1, true, "((bar{1}) equal to (bar{2})) failed: (\"(anonymous namespace)::bar {\n int i = 1\n}\n\") is not equal to (\"(anonymous namespace)::bar {\n int i = 2\n}\n\")", ""); } namespace {