From 5fbb2ad99d670c3c9d336c0222f64823d471edb6 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Fri, 16 Aug 2024 09:57:47 +0200 Subject: [PATCH] fix(utils_test): u8string triggers linker error with non-C++20 gtest This is a long standing issue and it's not going to go away, as package manager prefer that stuff isn't fetched at build time. So we just check if certain gtest features work with the system-installed version and work around missing features downstream. Out of the box, with the custom built ctest, we'll still get all the good stuff. If the system-installed version is preferred, we probably have some degradation in test output. --- README.md | 7 +--- cmake/checks/gtest-u8string.cpp | 7 ++++ cmake/need_gtest.cmake | 13 +++++-- test/utils_test.cpp | 61 ++++++++++++++++++--------------- 4 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 cmake/checks/gtest-u8string.cpp diff --git a/README.md b/README.md index f6471e76..25b90b40 100644 --- a/README.md +++ b/README.md @@ -208,12 +208,7 @@ There are some things to be aware of: of GoogleTest. GoogleTest itself recommends that it is being downloaded as part of the build. However, you can use the system installed version by passing `-DPREFER_SYSTEM_GTEST=ON` to the - `cmake` call. Use at your own risk. One known issues with using - system-installed versions of GoogleTest is that `utils_test` can - fail to compile because it uses C++20 features and GoogleTest is - built without `-std=c++20`. The release page has a patch - (`dwarfs-system-gtest.patch`) that can be applied to work around - this issue. + `cmake` call. Use at your own risk. - For other bundled libraries (namely `fmt`, `parallel-hashmap`, `range-v3`), the system installed version is used as long as it diff --git a/cmake/checks/gtest-u8string.cpp b/cmake/checks/gtest-u8string.cpp new file mode 100644 index 00000000..12efe5d1 --- /dev/null +++ b/cmake/checks/gtest-u8string.cpp @@ -0,0 +1,7 @@ +#include + +#include + +TEST(u8string, compare) { + EXPECT_EQ(u8"我", u8"我"); +} diff --git a/cmake/need_gtest.cmake b/cmake/need_gtest.cmake index fbe74db2..76945824 100644 --- a/cmake/need_gtest.cmake +++ b/cmake/need_gtest.cmake @@ -24,9 +24,18 @@ if(PREFER_SYSTEM_GTEST) add_library(gtest_main ALIAS GTest::gtest_main) add_library(gmock ALIAS GTest::gmock) add_library(gmock_main ALIAS GTest::gmock_main) -endif() -if(NOT GTest_FOUND) + try_compile( + GTEST_SUPPORTS_U8STRING + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/checks/gtest-u8string.cpp + CXX_STANDARD 20 + ) + + if(NOT GTEST_SUPPORTS_U8STRING) + message(WARNING "GTest does not support u8string.") + target_compile_definitions(GTest::gtest INTERFACE GTEST_NO_U8STRING=1) + endif() +else() FetchContent_Declare( googletest GIT_REPOSITORY ${GOOGLETEST_GIT_REPO} diff --git a/test/utils_test.cpp b/test/utils_test.cpp index 9148b73e..7584205d 100644 --- a/test/utils_test.cpp +++ b/test/utils_test.cpp @@ -34,18 +34,25 @@ using namespace dwarfs; +#ifdef GTEST_NO_U8STRING +#define EXPECT_EQ_U8STR(a, b) EXPECT_TRUE((a) == (b)) +#else +#define EXPECT_EQ_U8STR(a, b) EXPECT_EQ(a, b) +#endif + TEST(utils, utf8_display_width) { - EXPECT_EQ(0, utf8_display_width("")); - EXPECT_EQ(1, utf8_display_width(u8string_to_string(u8"a"))); - EXPECT_EQ(5, utf8_display_width(u8string_to_string(u8"abcde"))); - EXPECT_EQ(2, utf8_display_width(u8string_to_string(u8"你"))); - EXPECT_EQ(4, utf8_display_width(u8string_to_string(u8"我你"))); - EXPECT_EQ(6, utf8_display_width(u8string_to_string(u8"我爱你"))); - EXPECT_EQ(5, utf8_display_width(u8string_to_string(u8"☀️ Sun"))); - EXPECT_EQ(2, utf8_display_width(u8string_to_string(u8"⚽️"))); - EXPECT_EQ(5, utf8_display_width(u8string_to_string(u8"مرحبًا"))); - EXPECT_EQ(50, utf8_display_width(u8string_to_string( - u8"unicode/我爱你/☀️ Sun/Γειά σας/مرحبًا/⚽️/Карибського"))); + EXPECT_EQ_U8STR(0, utf8_display_width("")); + EXPECT_EQ_U8STR(1, utf8_display_width(u8string_to_string(u8"a"))); + EXPECT_EQ_U8STR(5, utf8_display_width(u8string_to_string(u8"abcde"))); + EXPECT_EQ_U8STR(2, utf8_display_width(u8string_to_string(u8"你"))); + EXPECT_EQ_U8STR(4, utf8_display_width(u8string_to_string(u8"我你"))); + EXPECT_EQ_U8STR(6, utf8_display_width(u8string_to_string(u8"我爱你"))); + EXPECT_EQ_U8STR(5, utf8_display_width(u8string_to_string(u8"☀️ Sun"))); + EXPECT_EQ_U8STR(2, utf8_display_width(u8string_to_string(u8"⚽️"))); + EXPECT_EQ_U8STR(5, utf8_display_width(u8string_to_string(u8"مرحبًا"))); + EXPECT_EQ_U8STR(50, + utf8_display_width(u8string_to_string( + u8"unicode/我爱你/☀️ Sun/Γειά σας/مرحبًا/⚽️/Карибського"))); } TEST(utils, uft8_truncate) { @@ -58,22 +65,22 @@ TEST(utils, uft8_truncate) { // -----------------123456789012345-- auto const str = u8"我爱你/مرحبًا/⚽️"; - EXPECT_EQ(str, u8trunc(str, 15)); + EXPECT_EQ_U8STR(str, u8trunc(str, 15)); // ----------123456789012345-- - EXPECT_EQ(u8"我爱你/مرحبًا/", u8trunc(str, 14)); - EXPECT_EQ(u8"我爱你/مرحبًا/", u8trunc(str, 13)); - EXPECT_EQ(u8"我爱你/مرحبًا", u8trunc(str, 12)); - EXPECT_EQ(u8"我爱你/مرحبً", u8trunc(str, 11)); - EXPECT_EQ(u8"我爱你/مرح", u8trunc(str, 10)); - EXPECT_EQ(u8"我爱你/مر", u8trunc(str, 9)); - EXPECT_EQ(u8"我爱你/م", u8trunc(str, 8)); - EXPECT_EQ(u8"我爱你/", u8trunc(str, 7)); - EXPECT_EQ(u8"我爱你", u8trunc(str, 6)); - EXPECT_EQ(u8"我爱", u8trunc(str, 5)); - EXPECT_EQ(u8"我爱", u8trunc(str, 4)); - EXPECT_EQ(u8"我", u8trunc(str, 3)); - EXPECT_EQ(u8"我", u8trunc(str, 2)); - EXPECT_EQ(u8"", u8trunc(str, 1)); + EXPECT_EQ_U8STR(u8"我爱你/مرحبًا/", u8trunc(str, 14)); + EXPECT_EQ_U8STR(u8"我爱你/مرحبًا/", u8trunc(str, 13)); + EXPECT_EQ_U8STR(u8"我爱你/مرحبًا", u8trunc(str, 12)); + EXPECT_EQ_U8STR(u8"我爱你/مرحبً", u8trunc(str, 11)); + EXPECT_EQ_U8STR(u8"我爱你/مرح", u8trunc(str, 10)); + EXPECT_EQ_U8STR(u8"我爱你/مر", u8trunc(str, 9)); + EXPECT_EQ_U8STR(u8"我爱你/م", u8trunc(str, 8)); + EXPECT_EQ_U8STR(u8"我爱你/", u8trunc(str, 7)); + EXPECT_EQ_U8STR(u8"我爱你", u8trunc(str, 6)); + EXPECT_EQ_U8STR(u8"我爱", u8trunc(str, 5)); + EXPECT_EQ_U8STR(u8"我爱", u8trunc(str, 4)); + EXPECT_EQ_U8STR(u8"我", u8trunc(str, 3)); + EXPECT_EQ_U8STR(u8"我", u8trunc(str, 2)); + EXPECT_EQ_U8STR(u8"", u8trunc(str, 1)); } TEST(utils, shorten_path_ascii) { @@ -183,7 +190,7 @@ TEST(utils, shorten_path_utf8) { for (size_t max_len = 0; max_len < expected.size(); ++max_len) { std::string path = u8string_to_string(path_u8); shorten_path_string(path, '/', max_len); - EXPECT_EQ(u8string_to_string(expected[max_len]), path); + EXPECT_EQ_U8STR(u8string_to_string(expected[max_len]), path); } } }