From 7aff0910a05535ab73e8505180ce711ff4eff752 Mon Sep 17 00:00:00 2001 From: Geoffrey M Gunter Date: Tue, 31 Oct 2023 13:20:19 -0700 Subject: [PATCH 1/3] Escape special characters in test names --- src/pytest_cpp/catch2.py | 25 +++++++++++++++++-------- tests/SConstruct | 5 +++++ tests/catch2_special_chars.cpp | 26 ++++++++++++++++++++++++++ tests/test_pytest_cpp.py | 18 ++++++++++++++++++ 4 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 tests/catch2_special_chars.cpp diff --git a/src/pytest_cpp/catch2.py b/src/pytest_cpp/catch2.py index 5af50b6..5f6cfac 100644 --- a/src/pytest_cpp/catch2.py +++ b/src/pytest_cpp/catch2.py @@ -16,6 +16,15 @@ from pytest_cpp.helpers import make_cmdline +# Map each special character's Unicode ordinal to the escaped character. +_special_chars_map: dict[int, str] = {i: "\\" + chr(i) for i in b'[]*,~\\"'} + + +def escape(test_id: str) -> str: + """Escape special characters in test names.""" + return test_id.translate(_special_chars_map) + + class Catch2Version(enum.Enum): V2 = "v2" V3 = "v3" @@ -115,14 +124,14 @@ def run_test( xml_filename = os.path.join(os.path.relpath(temp_dir), "cpp-report.xml") except ValueError: xml_filename = os.path.join(temp_dir, "cpp-report.xml") - args = list( - make_cmdline( - harness, - executable, - [test_id, "--success", "--reporter=xml", f"--out {xml_filename}"], - ) - ) - args.extend(test_args) + exec_args = [ + escape(test_id), + "--success", + "--reporter=xml", + f"--out={xml_filename}", + ] + exec_args.extend(test_args) + args = make_cmdline(harness, executable, exec_args) try: output = subprocess.check_output( diff --git a/tests/SConstruct b/tests/SConstruct index d5603ad..526cf77 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -47,10 +47,15 @@ for env, label in [(c3env, "_v3"), (c2env, "")]: catch2_success = env.Object(f'catch2_success{label}', 'catch2_success.cpp') catch2_failure = env.Object(f'catch2_failure{label}', 'catch2_failure.cpp') catch2_error = env.Object(f'catch2_error{label}', 'catch2_error.cpp') + catch2_special_chars = env.Object( + f'catch2_special_chars{label}', + 'catch2_special_chars.cpp' + ) env.Program(catch2_success) env.Program(catch2_failure) env.Program(catch2_error) + env.Program(catch2_special_chars) SConscript('acceptance/googletest-samples/SConscript') SConscript('acceptance/boosttest-samples/SConscript') diff --git a/tests/catch2_special_chars.cpp b/tests/catch2_special_chars.cpp new file mode 100644 index 0000000..4c61f52 --- /dev/null +++ b/tests/catch2_special_chars.cpp @@ -0,0 +1,26 @@ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include "catch.hpp" + +TEST_CASE( "Brackets in [test] name" ) { + REQUIRE( true ); +} + +TEST_CASE( "**Star in test name**" ) { + REQUIRE( true ); +} + +TEST_CASE( "~Tilde in test name" ) { + REQUIRE( true ); +} + +TEST_CASE( "Comma, in, test, name" ) { + REQUIRE( true ); +} + +TEST_CASE( R"(Backslash\ in\ test\ name)" ) { + REQUIRE( true ); +} + +TEST_CASE( "\"Quotes\" in test name" ) { + REQUIRE( true ); +} diff --git a/tests/test_pytest_cpp.py b/tests/test_pytest_cpp.py index a13b784..a2d5f5c 100644 --- a/tests/test_pytest_cpp.py +++ b/tests/test_pytest_cpp.py @@ -635,6 +635,24 @@ def test_catch2_failure(exes): assert_catch2_failure(fail1.get_lines()[1], "a runtime error", colors) +@pytest.mark.parametrize("suffix", ["", "_v3"]) +@pytest.mark.parametrize( + "test_id", + [ + "Brackets in [test] name", + "**Star in test name**", + "~Tilde in test name", + "Comma, in, test, name", + r"Backslash\ in\ test\ name", + '"Quotes" in test name', + ], +) +def test_catch2_special_chars(suffix, test_id, exes): + facade = Catch2Facade() + exe = exes.get("catch2_special_chars" + suffix) + assert facade.run_test(exe, test_id)[0] is None + + class TestError: def test_get_whitespace(self): assert error.get_left_whitespace(" foo") == " " From 1ac0fb005ce62f104e9917a5d478bc1bf5883fdc Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 1 Nov 2023 11:03:44 -0300 Subject: [PATCH 2/3] Update src/pytest_cpp/catch2.py --- src/pytest_cpp/catch2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest_cpp/catch2.py b/src/pytest_cpp/catch2.py index 5f6cfac..ec65768 100644 --- a/src/pytest_cpp/catch2.py +++ b/src/pytest_cpp/catch2.py @@ -21,7 +21,7 @@ def escape(test_id: str) -> str: - """Escape special characters in test names.""" + """Escape special characters in test names (see #123).""" return test_id.translate(_special_chars_map) From cfead3b4de0ec5c0cafcf34fe0bbc79d2a3db3ae Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 1 Nov 2023 11:22:36 -0300 Subject: [PATCH 3/3] Update CHANGELOG --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27ac6e1..167eb80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # UNRELEASED -- Catch2: add support for catch version 3 ([#115](https://github.com/pytest-dev/pytest-cpp/pull/115)) -- Catch2: support exception handling ([#117](https://github.com/pytest-dev/pytest-cpp/pull/117)) +- Catch2: add support for catch version 3 ([#115](https://github.com/pytest-dev/pytest-cpp/pull/115)). +- Catch2: support exception handling ([#117](https://github.com/pytest-dev/pytest-cpp/pull/117)). +- Catch2: Correctly handle test names that contain special characters ([#123](https://github.com/pytest-dev/pytest-cpp/issues/123)). - Added support for Python 3.12. # 2.4.0 (2023-09-08)