diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16efa3fe..b52122fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -120,6 +120,7 @@ set(INTERNAL_HEADERS ${SOURCES_DIR}/internal/catch_random_seed_generation.hpp ${SOURCES_DIR}/reporters/catch_reporter_registrars.hpp ${SOURCES_DIR}/internal/catch_reporter_registry.hpp + ${SOURCES_DIR}/internal/catch_reporter_spec_parser.hpp ${SOURCES_DIR}/internal/catch_result_type.hpp ${SOURCES_DIR}/internal/catch_run_context.hpp ${SOURCES_DIR}/internal/catch_section.hpp @@ -192,6 +193,7 @@ set(IMPL_SOURCES ${SOURCES_DIR}/internal/catch_random_number_generator.cpp ${SOURCES_DIR}/internal/catch_random_seed_generation.cpp ${SOURCES_DIR}/internal/catch_reporter_registry.cpp + ${SOURCES_DIR}/internal/catch_reporter_spec_parser.cpp ${SOURCES_DIR}/internal/catch_result_type.cpp ${SOURCES_DIR}/internal/catch_run_context.cpp ${SOURCES_DIR}/internal/catch_section.cpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index 656417f4..b082b766 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -82,6 +82,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/internal/catch_reporter_spec_parser.cpp b/src/catch2/internal/catch_reporter_spec_parser.cpp new file mode 100644 index 00000000..28e3c19b --- /dev/null +++ b/src/catch2/internal/catch_reporter_spec_parser.cpp @@ -0,0 +1,64 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#include + +namespace Catch { + + namespace Detail { + std::vector splitReporterSpec( StringRef reporterSpec ) { + static constexpr auto separator = "::"; + static constexpr size_t separatorSize = 2; + + size_t separatorPos = 0; + auto findNextSeparator = [&reporterSpec]( size_t startPos ) { + static_assert( + separatorSize == 2, + "The code below currently assumes 2 char separator" ); + + auto currentPos = startPos; + do { + while ( currentPos < reporterSpec.size() && + reporterSpec[currentPos] != separator[0] ) { + ++currentPos; + } + if ( currentPos + 1 < reporterSpec.size() && + reporterSpec[currentPos + 1] == separator[1] ) { + return currentPos; + } + ++currentPos; + } while ( currentPos < reporterSpec.size() ); + + return static_cast( -1 ); + }; + + std::vector parts; + + while ( separatorPos < reporterSpec.size() ) { + const auto nextSeparator = findNextSeparator( separatorPos ); + parts.push_back( static_cast( reporterSpec.substr( + separatorPos, nextSeparator - separatorPos ) ) ); + + if ( nextSeparator == static_cast( -1 ) ) { + break; + } + separatorPos = nextSeparator + separatorSize; + } + + // Handle a separator at the end. + // This is not a valid spec, but we want to do validation in a + // centralized place + if ( separatorPos == reporterSpec.size() ) { + parts.emplace_back(); + } + + return parts; + } + } + +} // namespace Catch diff --git a/src/catch2/internal/catch_reporter_spec_parser.hpp b/src/catch2/internal/catch_reporter_spec_parser.hpp new file mode 100644 index 00000000..74632f25 --- /dev/null +++ b/src/catch2/internal/catch_reporter_spec_parser.hpp @@ -0,0 +1,25 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED +#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED + +#include + +#include +#include + +namespace Catch { + + namespace Detail { + //! Splits the reporter spec into reporter name and kv-pair options + std::vector splitReporterSpec( StringRef reporterSpec ); + } + +} + +#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1c520120..a4d01dc9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -79,6 +79,7 @@ set(TEST_SOURCES ${SELF_TEST_DIR}/TestRegistrations.cpp ${SELF_TEST_DIR}/IntrospectiveTests/Clara.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp + ${SELF_TEST_DIR}/IntrospectiveTests/CmdLineHelpers.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/ColourImpl.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/Details.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/FloatingPoint.tests.cpp diff --git a/tests/SelfTest/IntrospectiveTests/CmdLineHelpers.tests.cpp b/tests/SelfTest/IntrospectiveTests/CmdLineHelpers.tests.cpp new file mode 100644 index 00000000..b79dcca2 --- /dev/null +++ b/tests/SelfTest/IntrospectiveTests/CmdLineHelpers.tests.cpp @@ -0,0 +1,46 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#include +#include +#include + +TEST_CASE("Reporter spec splitting", "[reporter-spec][cli][approvals]") { + using Catch::Detail::splitReporterSpec; + using Catch::Matchers::Equals; + using namespace std::string_literals; + + SECTION("Various edge cases") { + REQUIRE_THAT( splitReporterSpec( "" ), + Equals( std::vector{ ""s } ) ); + REQUIRE_THAT( splitReporterSpec( "::" ), + Equals( std::vector{ "", "" } ) ); + REQUIRE_THAT( splitReporterSpec( "::rep" ), + Equals( std::vector{ "", "rep" } ) ); + REQUIRE_THAT( splitReporterSpec( "rep::" ), + Equals( std::vector{ "rep", "" } ) ); + + } + + SECTION("Validish specs") { + REQUIRE_THAT( splitReporterSpec( "newReporter" ), + Equals( std::vector{ "newReporter"s } ) ); + REQUIRE_THAT( + splitReporterSpec( "foo-reporter::key1=value1::key2=value with " + "space::key with space=some-value" ), + Equals( + std::vector{ "foo-reporter"s, + "key1=value1"s, + "key2=value with space"s, + "key with space=some-value"s } ) ); + REQUIRE_THAT( + splitReporterSpec( "spaced reporter name::key:key=value:value" ), + Equals( std::vector{ "spaced reporter name"s, + "key:key=value:value"s } ) ); + } +}