GoogleTest: Drop newlines from test names

It is possible to have trailing ( and maybe leading ) newlines in a test name. This causes problems with ctest
features like `tests-from-file` since they will never
be an exact match.

So now we sanitize names by removing these newlines
This commit is contained in:
Robert Maynard
2026-07-09 15:45:30 -04:00
parent b464920acc
commit 2c181bd60a
6 changed files with 86 additions and 0 deletions

View File

@@ -84,6 +84,8 @@ macro(get_json_member_with_default json_variable member_name out_variable)
if(error_param)
# Member not present
set(${out_variable} "")
else()
string(STRIP "${${out_variable}}" "${out_variable}")
endif()
endmacro()
@@ -111,6 +113,7 @@ macro(parse_tests_from_json json_file per_test_callback)
# before accounting for pretty names. This may be used to construct the
# name of XML output results files.
string(JSON current_test_suite GET "${test_suite_json}" "name")
string(STRIP "${current_test_suite}" current_test_suite)
string(JSON tests_json GET "${test_suite_json}" "testsuite")
# Skip test suites without tests

View File

@@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 4.2)
include("${CMAKE_CURRENT_LIST_DIR}/GoogleTest/ParseTestList.cmake")
macro(write_test_to_file)
# Store the gtest test name before messing with these strings
set(gtest_name ${current_test_suite}.${current_test_name})

View File

@@ -0,0 +1,15 @@
Test project .*
*Start +[0-9]+: TEST:newline/test\.case/a!9
*[0-9]+/[0-9]+ +Test.*TEST:newline/test\.case/a!9 .+ +Passed +[0-9\.]+ sec
*Start +[0-9]+: TEST:newline/test\.case/b!9
*[0-9]+/[0-9]+ +Test.*TEST:newline/test\.case/b!9 .+ +Passed +[0-9\.]+ sec
*Start +[0-9]+: TEST:newline/test\.case/c!9
*[0-9]+/[0-9]+ +Test.*TEST:newline/test\.case/c!9 .+ +Passed +[0-9\.]+ sec
*Start +[0-9]+: TEST:newline_name/suite\.case/trailing_param!9
*[0-9]+/[0-9]+ +Test.*TEST:newline_name/suite\.case/trailing_param!9 .+ +Passed +[0-9\.]+ sec
*Start +[0-9]+: TEST:newline_name/suite\.case/leading_param!9
*[0-9]+/[0-9]+ +Test.*TEST:newline_name/suite\.case/leading_param!9 .+ +Passed +[0-9\.]+ sec
100% tests passed out of [0-9]+
Total Test time \(real\) = +[0-9\.]+ sec

View File

@@ -83,6 +83,15 @@ gtest_discover_tests(
PROPERTIES LABELS TEST8
)
gtest_discover_tests(
fake_gtest
TEST_PREFIX TEST:
TEST_SUFFIX !9
TEST_FILTER newline*
EXTRA_ARGS how now "\"brown\" cow"
PROPERTIES LABELS TEST9
)
add_executable(no_tests_defined no_tests_defined.cpp)
xcode_sign_adhoc(no_tests_defined)

View File

@@ -93,6 +93,23 @@ function(run_GoogleTest DISCOVERY_MODE)
--no-label-summary
)
run_cmake_command(GoogleTest-test9
${CMAKE_CTEST_COMMAND}
-C Debug
-L TEST9
--no-label-summary
)
file(WRITE "${RunCMake_TEST_BINARY_DIR}/test9-names.txt"
"TEST:newline_name/suite.case/trailing_param!9\n"
)
run_cmake_command(GoogleTest-test9-from-file
${CMAKE_CTEST_COMMAND}
-C Debug
--tests-from-file "${RunCMake_TEST_BINARY_DIR}/test9-names.txt"
--no-label-summary
)
run_cmake_command(GoogleTest-test-missing
${CMAKE_CTEST_COMMAND}
-C Debug

View File

@@ -29,6 +29,8 @@ int main(int argc, char** argv)
!is_filtered || (std::string(argv[3]).find("value*") != std::string::npos);
bool add_dynamic_tests = !is_filtered ||
(std::string(argv[3]).find("dynamic*") != std::string::npos);
bool add_newline_tests = !is_filtered ||
(std::string(argv[3]).find("newline*") != std::string::npos);
if (argc > 2 && std::string(argv[1]) == "--gtest_list_tests" &&
std::string(argv[2]).find("--gtest_output=json:") != std::string::npos) {
@@ -239,6 +241,45 @@ int main(int argc, char** argv)
tests += 8;
}
}
if (add_newline_tests) {
std::cout << "newline/test." << std::endl;
std::cout << " case/0 # GetParam() = wrapped_value" << std::endl;
std::cout << " case/1 # GetParam() = wrapped_value" << std::endl;
std::cout << " case/2 # GetParam() = wrapped_value" << std::endl;
std::cout << "newline_name/suite." << std::endl;
std::cout << " case/trailing_param" << std::endl;
std::cout << " case/leading_param" << std::endl;
if (tests)
ostrm << ",";
ostrm << "\n"
" {\n"
" \"name\": \"newline/test\",\n"
" \"tests\": 3,\n"
" \"testsuite\": [\n"
" { \"name\": \"case/a\", \"value_param\": "
"\"wrapped_value\\n\", \"file\": \"file4.cpp\", \"line\": 1 "
"},\n"
" { \"name\": \"case/b\", \"value_param\": "
"\"\\nwrapped_value\", \"file\": \"file4.cpp\", \"line\": 2 "
"},\n"
" { \"name\": \"case/c\", \"value_param\": "
"\"\\nwrapped_value\\n\", \"file\": \"file4.cpp\", \"line\": 3 "
"}\n"
" ]\n"
" },\n"
" {\n"
" \"name\": \"newline_name/suite\",\n"
" \"tests\": 2,\n"
" \"testsuite\": [\n"
" { \"name\": \"case/trailing_param\\n\", "
"\"file\": \"file5.cpp\", \"line\": 1 },\n"
" { \"name\": \"\\ncase/leading_param\", "
"\"file\": \"file5.cpp\", \"line\": 2 }\n"
" ]\n"
" }";
tests += 5;
}
if (add_value_tests || add_typed_tests || add_dynamic_tests) {
char const* both_suite_names[] = { "both_suite", "both/suite",
"ns.both/suite",