diff --git a/BUILD.bazel b/BUILD.bazel index 9b7d608d..604c5fb8 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -8,9 +8,7 @@ expand_template( out = "catch2/catch_user_config.hpp", substitutions = { "#cmakedefine CATCH_CONFIG_ANDROID_LOGWRITE": "", - "#cmakedefine CATCH_CONFIG_COLOUR_ANSI": "", - "#cmakedefine CATCH_CONFIG_COLOUR_NONE": "", - "#cmakedefine CATCH_CONFIG_COLOUR_WINDOWS": "", + "#cmakedefine CATCH_CONFIG_COLOUR_WIN32": "", "#cmakedefine CATCH_CONFIG_COUNTER": "", "#cmakedefine CATCH_CONFIG_CPP11_TO_STRING": "", "#cmakedefine CATCH_CONFIG_CPP17_BYTE": "", diff --git a/CMake/CatchConfigOptions.cmake b/CMake/CatchConfigOptions.cmake index 54cf0ab9..78491525 100644 --- a/CMake/CatchConfigOptions.cmake +++ b/CMake/CatchConfigOptions.cmake @@ -26,6 +26,7 @@ endmacro() set(_OverridableOptions "ANDROID_LOGWRITE" + "COLOUR_WIN32" "COUNTER" "CPP11_TO_STRING" "CPP17_BYTE" @@ -45,9 +46,6 @@ foreach(OptionName ${_OverridableOptions}) endforeach() set(_OtherConfigOptions - "COLOUR_ANSI" - "COLOUR_NONE" - "COLOUR_WINDOWS" "DISABLE_EXCEPTIONS" "DISABLE_EXCEPTIONS_CUSTOM_HANDLER" "DISABLE" diff --git a/docs/command-line.md b/docs/command-line.md index 7ace0530..29e6a365 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -67,7 +67,7 @@ Click one of the following links to take you straight to that option - or scroll ` --benchmark-confidence-interval`
` --benchmark-no-analysis`
` --benchmark-warmup-time`
- ` --use-colour`
+ ` --colour-mode`
` --shard-count`
` --shard-index`
` --allow-running-no-tests`
@@ -457,16 +457,26 @@ filename it is found in, with any extension stripped, prefixed with the `#` char So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`. - + ## Override output colouring -
--use-colour <yes|no|auto>
+
--colour-mode <ansi|win32|none|default>
-Catch colours output for terminals, but omits colouring when it detects that -output is being sent to a pipe. This is done to avoid interfering with automated -processing of output. +Catch2 support two different ways of colouring terminal output, and by +default it attempts to make a good guess on which implementation to use +(and whether to even use it, e.g. Catch2 tries to avoid writing colour +codes when writing the results into a file). + +`--colour-mode` allows the user to explicitly select what happens. + +* `--colour-mode ansi` tells Catch2 to always use ANSI colour codes, even +when writing to a file +* `--colour-mode win32` tells Catch2 to use colour implementation based + on Win32 terminal API +* `--colour-mode none` tells Catch2 to disable colours completely +* `--colour-mode default` lets Catch2 decide + +`--colour-mode default` is the default setting. -`--use-colour yes` forces coloured output, `--use-colour no` disables coloured -output. The default behaviour is `--use-colour auto`. ## Test Sharding diff --git a/docs/configuration.md b/docs/configuration.md index a7db4b13..5105f6d9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -31,19 +31,18 @@ To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TE ## Terminal colour - CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring - CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used - CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used + CATCH_CONFIG_COLOUR_WIN32 // Force enables compiling colouring impl based on Win32 console API + CATCH_CONFIG_NO_COLOUR_WIN32 // Force disables ... -Yes, I am English, so I will continue to spell "colour" with a 'u'. +Yes, Catch2 uses the british spelling of colour. -When sending output to the terminal, if it detects that it can, Catch will use colourised text. On Windows the Win32 API, ```SetConsoleTextAttribute```, is used. On POSIX systems ANSI colour escape codes are inserted into the stream. +Catch2 attempts to autodetect whether the Win32 console colouring API, +`SetConsoleTextAttribute`, is available, and if it is available it compiles +in a console colouring implementation that uses it. -For finer control you can define one of the above identifiers (these are mutually exclusive - but that is not checked so may behave unexpectedly if you mix them): +This option can be used to override Catch2's autodetection and force the +compilation either ON or OFF. -Note that when ANSI colour codes are used "unistd.h" must be includable - along with a definition of ```isatty()``` - -Typically you should place the ```#define``` before #including "catch.hpp" in your main source file - but if you prefer you can define it for your whole project by whatever your IDE or build system provides for you to do so. ## Console width diff --git a/docs/release-notes.md b/docs/release-notes.md index 60f38b77..ca64106e 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -179,6 +179,13 @@ v3 releases. * To support this, the `-r`, `--reporter` flag now also accepts optional output destination * For full overview of the semantics of using multiple reporters, look into the reporter documentation * To enable the new syntax, reporter names can no longer contain `::`. +* Console colour support has been rewritten and significantly improved + * The colour implementation based on ANSI colour codes is always available + * Colour implementations respect their associated stream + * previously e.g. Win32 impl would change console colour even if Catch2 was writing to a file + * The colour API is resilient against changing evaluation order of expressions + * The associated CLI flag and compile-time configuration options have changed + * For details see the docs for command-line and compile-time Catch2 configuration ### Fixes diff --git a/src/catch2/catch_config.cpp b/src/catch2/catch_config.cpp index 8541d223..4c8b3319 100644 --- a/src/catch2/catch_config.cpp +++ b/src/catch2/catch_config.cpp @@ -138,7 +138,7 @@ namespace Catch { uint32_t Config::rngSeed() const { return m_data.rngSeed; } unsigned int Config::shardCount() const { return m_data.shardCount; } unsigned int Config::shardIndex() const { return m_data.shardIndex; } - UseColour Config::useColour() const { return m_data.useColour; } + ColourMode Config::colourMode() const { return m_data.colourMode; } bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } int Config::abortAfter() const { return m_data.abortAfter; } bool Config::showInvisibles() const { return m_data.showInvisibles; } diff --git a/src/catch2/catch_config.hpp b/src/catch2/catch_config.hpp index 2a71537d..91ce4e64 100644 --- a/src/catch2/catch_config.hpp +++ b/src/catch2/catch_config.hpp @@ -66,7 +66,7 @@ namespace Catch { ShowDurations showDurations = ShowDurations::DefaultForReporter; double minDuration = -1; TestRunOrder runOrder = TestRunOrder::Declared; - UseColour useColour = UseColour::Auto; + ColourMode colourMode = ColourMode::PlatformDefault; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; std::string defaultOutputFilename; @@ -114,7 +114,7 @@ namespace Catch { uint32_t rngSeed() const override; unsigned int shardCount() const override; unsigned int shardIndex() const override; - UseColour useColour() const override; + ColourMode colourMode() const override; bool shouldDebugBreak() const override; int abortAfter() const override; bool showInvisibles() const override; diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index c685e48b..6af52685 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -152,7 +152,8 @@ namespace Catch { m_startupExceptions = true; auto errStream = makeStream( "%stderr" ); - auto colourImpl = makeColourImpl( &config(), errStream.get() ); + auto colourImpl = makeColourImpl( + ColourMode::PlatformDefault, errStream.get() ); auto guard = colourImpl->guardColour( Colour::Red ); errStream->stream() << "Errors occurred during startup!" << '\n'; // iterate over all exceptions and notify user @@ -197,7 +198,7 @@ namespace Catch { config(); getCurrentMutableContext().setConfig(m_config.get()); auto errStream = makeStream( "%stderr" ); - auto colour = makeColourImpl( &config(), errStream.get() ); + auto colour = makeColourImpl( ColourMode::PlatformDefault, errStream.get() ); errStream->stream() << colour->guardColour( Colour::Red ) diff --git a/src/catch2/catch_user_config.hpp.in b/src/catch2/catch_user_config.hpp.in index b3a518f9..911e2dc4 100644 --- a/src/catch2/catch_user_config.hpp.in +++ b/src/catch2/catch_user_config.hpp.in @@ -32,7 +32,13 @@ # error Cannot force ANDROID_LOGWRITE to both ON and OFF #endif +#cmakedefine CATCH_CONFIG_COLOUR_WIN32 +#cmakedefine CATCH_CONFIG_NO_COLOUR_WIN32 +#if defined( CATCH_CONFIG_COLOUR_WIN32 ) && \ + defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) +# error Cannot force COLOUR_WIN32 to be ON and OFF +#endif #cmakedefine CATCH_CONFIG_COUNTER #cmakedefine CATCH_CONFIG_NO_COUNTER @@ -159,9 +165,6 @@ // ------ -#cmakedefine CATCH_CONFIG_COLOUR_ANSI -#cmakedefine CATCH_CONFIG_COLOUR_NONE -#cmakedefine CATCH_CONFIG_COLOUR_WINDOWS #cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS #cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER #cmakedefine CATCH_CONFIG_DISABLE diff --git a/src/catch2/interfaces/catch_interfaces_config.hpp b/src/catch2/interfaces/catch_interfaces_config.hpp index d98f7b44..fb3b2977 100644 --- a/src/catch2/interfaces/catch_interfaces_config.hpp +++ b/src/catch2/interfaces/catch_interfaces_config.hpp @@ -42,10 +42,15 @@ namespace Catch { LexicographicallySorted, Randomized }; - enum class UseColour { - Auto, - Yes, - No + enum class ColourMode : std::uint8_t { + //! Let Catch2 pick implementation based on platform detection + PlatformDefault, + //! Use ANSI colour code escapes + ANSI, + //! Use Win32 console colour API + Win32, + //! Don't use any colour + None }; struct WaitForKeypress { enum When { Never, @@ -79,7 +84,7 @@ namespace Catch { virtual uint32_t rngSeed() const = 0; virtual unsigned int shardCount() const = 0; virtual unsigned int shardIndex() const = 0; - virtual UseColour useColour() const = 0; + virtual ColourMode colourMode() const = 0; virtual std::vector const& getSectionsToRun() const = 0; virtual Verbosity verbosity() const = 0; diff --git a/src/catch2/internal/catch_commandline.cpp b/src/catch2/internal/catch_commandline.cpp index 540adc55..6363e47a 100644 --- a/src/catch2/internal/catch_commandline.cpp +++ b/src/catch2/internal/catch_commandline.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -95,19 +96,44 @@ namespace Catch { return ParserResult::runtimeError("Could not parse '" + seed + "' as seed"); } }; - auto const setColourUsage = [&]( std::string const& useColour ) { - auto mode = toLower( useColour ); + auto const setColourMode = [&]( std::string const& + colourMode ) { + auto mode = toLower( colourMode ); - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); - return ParserResult::ok( ParseResultType::Matched ); - }; + if ( mode == "default" ) { + if ( !isColourImplAvailable( ColourMode::PlatformDefault ) ) { + return ParserResult::runtimeError( + "colour mode 'default' is not supported in this " + "binary" ); + } + config.colourMode = ColourMode::PlatformDefault; + } else if ( mode == "ansi" ) { + if ( !isColourImplAvailable( ColourMode::ANSI ) ) { + return ParserResult::runtimeError( + "colour mode 'ansi' is not supported in this binary" ); + } + config.colourMode = ColourMode::ANSI; + } else if ( mode == "win32" ) { + if ( !isColourImplAvailable( ColourMode::Win32 ) ) { + return ParserResult::runtimeError( + "colour mode 'win32' is not supported in this " + "binary" ); + } + config.colourMode = ColourMode::Win32; + } else if ( mode == "none" ) { + if ( !isColourImplAvailable( ColourMode::None ) ) { + return ParserResult::runtimeError( + "colour mode 'none' is not supported in this binary" ); + } + config.colourMode = ColourMode::None; + } else { + return ParserResult::runtimeError( + "colour mode must be one of: default, ansi, win32, " + "or none. '" + + colourMode + "' not recognised" ); + } + return ParserResult::ok( ParseResultType::Matched ); + }; auto const setWaitForKeypress = [&]( std::string const& keypress ) { auto keypressLc = toLower( keypress ); if (keypressLc == "never") @@ -298,8 +324,8 @@ namespace Catch { | Opt( setRngSeed, "'time'|'random-device'|number" ) ["--rng-seed"] ( "set a specific seed for random numbers" ) - | Opt( setColourUsage, "yes|no|auto" ) - ["--use-colour"] + | Opt( setColourMode, "ansi|win32|none|default" ) + ["--colour-mode"] ( "should output be colourised" ) | Opt( config.libIdentify ) ["--libidentify"] diff --git a/src/catch2/internal/catch_compiler_capabilities.hpp b/src/catch2/internal/catch_compiler_capabilities.hpp index a72bc0b2..5c5c8f64 100644 --- a/src/catch2/internal/catch_compiler_capabilities.hpp +++ b/src/catch2/internal/catch_compiler_capabilities.hpp @@ -116,7 +116,6 @@ #ifdef __OS400__ # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE #endif //////////////////////////////////////////////////////////////////////////////// @@ -164,7 +163,7 @@ // Universal Windows platform does not support SEH // Or console colours (or console at all...) # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE +# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 # else # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # endif @@ -206,7 +205,7 @@ #if defined(UNDER_RTSS) || defined(RTX64_BUILD) #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH #define CATCH_INTERNAL_CONFIG_NO_ASYNC - #define CATCH_CONFIG_COLOUR_NONE + #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 #endif #if !defined(_GLIBCXX_USE_C99_MATH_TR1) @@ -358,4 +357,12 @@ #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #endif +#if defined( CATCH_PLATFORM_WINDOWS ) && \ + !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \ + !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \ + !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 ) +# define CATCH_CONFIG_COLOUR_WIN32 +#endif + + #endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED diff --git a/src/catch2/internal/catch_console_colour.cpp b/src/catch2/internal/catch_console_colour.cpp index b7b4b4fb..67f0d98a 100644 --- a/src/catch2/internal/catch_console_colour.cpp +++ b/src/catch2/internal/catch_console_colour.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -31,20 +32,6 @@ namespace Catch { return ColourGuard(colourCode, this ); } - namespace { - //! A do-nothing implementation of colour, used as fallback for unknown - //! platforms, and when the user asks to deactivate all colours. - class NoColourImpl : public ColourImpl { - public: - NoColourImpl( IStream const* stream ): ColourImpl( stream ) {} - static bool useColourOnPlatform() { return true; } - - private: - void use( Colour::Code ) const override {} - }; - - } // namespace - void ColourImpl::ColourGuard::engageImpl( std::ostream& stream ) { assert( &stream == &m_colourImpl->m_stream->stream() && "Engaging colour guard for different stream than used by the " @@ -92,18 +79,24 @@ namespace Catch { return CATCH_MOVE(*this); } + namespace { + //! A do-nothing implementation of colour, used as fallback for unknown + //! platforms, and when the user asks to deactivate all colours. + class NoColourImpl : public ColourImpl { + public: + NoColourImpl( IStream const* stream ): ColourImpl( stream ) {} + static bool useColourOnPlatform() { return true; } + + private: + void use( Colour::Code ) const override {} + }; + } // namespace + + } // namespace Catch -#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) -# ifdef CATCH_PLATFORM_WINDOWS -# define CATCH_CONFIG_COLOUR_WINDOWS -# else -# define CATCH_CONFIG_COLOUR_ANSI -# endif -#endif - -#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// +#if defined ( CATCH_CONFIG_COLOUR_WIN32 ) ///////////////////////////////////////// namespace Catch { namespace { @@ -174,13 +167,9 @@ namespace { namespace Catch { namespace { - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public ColourImpl { + class ANSIColourImpl : public ColourImpl { public: - PosixColourImpl( IStream const* stream ): ColourImpl( stream ) {} + ANSIColourImpl( IStream const* stream ): ColourImpl( stream ) {} static bool useColourOnPlatform(IStream const& stream) { // This is kinda messy due to trying to support a bunch of @@ -239,41 +228,50 @@ namespace { namespace Catch { - Detail::unique_ptr makeColourImpl(IConfig const* config, IStream const* stream) { - UseColour colourMode = config ? config->useColour() : UseColour::Auto; - - bool createPlatformInstance = false; - if ( colourMode == UseColour::No ) { - createPlatformInstance = false; + Detail::unique_ptr makeColourImpl( ColourMode implSelection, + IStream const* stream ) { + if ( implSelection == ColourMode::None ) { + return Detail::make_unique( stream ); } - - if ( colourMode == UseColour::Yes ) { - createPlatformInstance = true; + if ( implSelection == ColourMode::ANSI ) { + return Detail::make_unique( stream ); + } +#if defined( CATCH_CONFIG_COLOUR_WIN32 ) + if ( implSelection == ColourMode::Win32 ) { + return Detail::make_unique( stream ); } - - if ( colourMode == UseColour::Auto ) { - createPlatformInstance = -#if defined( CATCH_CONFIG_COLOUR_ANSI ) - PosixColourImpl::useColourOnPlatform( *stream ) -#elif defined( CATCH_CONFIG_COLOUR_WINDOWS ) - Win32ColourImpl::useColourOnPlatform( *stream ) -#else - false #endif - ; + + // todo: check win32 eligibility under ifdef, otherwise ansi + if ( implSelection == ColourMode::PlatformDefault) { +#if defined (CATCH_CONFIG_COLOUR_WIN32) + if ( Win32ColourImpl::useColourOnPlatform( *stream ) ) { + return Detail::make_unique( stream ); + } else { + return Detail::make_unique( stream ); + } +#endif + if ( ANSIColourImpl::useColourOnPlatform( *stream ) ) { + return Detail::make_unique( stream ); + } + return Detail::make_unique( stream ); } - if ( createPlatformInstance ) { - return -#if defined( CATCH_CONFIG_COLOUR_ANSI ) - Detail::make_unique(stream); -#elif defined( CATCH_CONFIG_COLOUR_WINDOWS ) - Detail::make_unique(stream); -#else - Detail::make_unique(stream); + CATCH_ERROR( "Could not create colour impl for selection " << static_cast(implSelection) ); + } + + bool isColourImplAvailable( ColourMode colourSelection ) { + switch ( colourSelection ) { +#if defined( CATCH_CONFIG_COLOUR_WIN32 ) + case ColourMode::Win32: #endif + case ColourMode::ANSI: + case ColourMode::None: + case ColourMode::PlatformDefault: + return true; + default: + return false; } - return Detail::make_unique(stream); } diff --git a/src/catch2/internal/catch_console_colour.hpp b/src/catch2/internal/catch_console_colour.hpp index 7b8f5b7a..7f91a5fc 100644 --- a/src/catch2/internal/catch_console_colour.hpp +++ b/src/catch2/internal/catch_console_colour.hpp @@ -11,9 +11,11 @@ #include #include +#include namespace Catch { + enum class ColourMode : std::uint8_t; struct IConfig; class IStream; @@ -128,7 +130,11 @@ namespace Catch { }; //! Provides ColourImpl based on global config and target compilation platform - Detail::unique_ptr makeColourImpl( IConfig const* config, IStream const* stream ); + Detail::unique_ptr makeColourImpl( ColourMode colourSelection, + IStream const* stream ); + + //! Checks if specific colour impl has been compiled into the binary + bool isColourImplAvailable( ColourMode colourSelection ); } // end namespace Catch diff --git a/src/catch2/reporters/catch_reporter_common_base.cpp b/src/catch2/reporters/catch_reporter_common_base.cpp index d49c2edb..85092db8 100644 --- a/src/catch2/reporters/catch_reporter_common_base.cpp +++ b/src/catch2/reporters/catch_reporter_common_base.cpp @@ -9,10 +9,21 @@ #include #include +#include +#include + namespace Catch { + ReporterBase::ReporterBase( ReporterConfig const& config ): + IEventListener( config.fullConfig() ), + m_wrapped_stream( config.stream() ), + m_stream( m_wrapped_stream->stream() ), + m_colour( makeColourImpl( m_config->colourMode(), m_wrapped_stream ) ) {} - void ReporterBase::listReporters(std::vector const& descriptions) { + ReporterBase::~ReporterBase() = default; + + void ReporterBase::listReporters( + std::vector const& descriptions ) { defaultListReporters(m_stream, descriptions, m_config->verbosity()); } diff --git a/src/catch2/reporters/catch_reporter_common_base.hpp b/src/catch2/reporters/catch_reporter_common_base.hpp index b69e5311..ba7ab116 100644 --- a/src/catch2/reporters/catch_reporter_common_base.hpp +++ b/src/catch2/reporters/catch_reporter_common_base.hpp @@ -9,10 +9,10 @@ #define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED #include -#include -#include namespace Catch { + class ColourImpl; + /** * This is the base class for all reporters. * @@ -33,12 +33,8 @@ namespace Catch { Detail::unique_ptr m_colour; public: - ReporterBase( ReporterConfig const& config ): - IEventListener( config.fullConfig() ), - m_wrapped_stream( config.stream() ), - m_stream( m_wrapped_stream->stream() ), - m_colour( makeColourImpl( config.fullConfig(), m_wrapped_stream ) ) {} - + ReporterBase( ReporterConfig const& config ); + ~ReporterBase() override; // = default; /** * Provides a simple default listing of reporters. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7ff57b9f..ef1b13ea 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -473,6 +473,17 @@ set_tests_properties("Reporters::DashAsLocationInReporterSpecSendsOutputToStdout PASS_REGULAR_EXPRESSION "All tests passed \\(5 assertions in 1 test case\\)" ) +add_test(NAME "Colours::ColourModeCanBeExplicitlySetToAnsi" + COMMAND + $ "Factorials are computed" + --reporter console + --colour-mode ansi +) +set_tests_properties("Colours::ColourModeCanBeExplicitlySetToAnsi" + PROPERTIES + PASS_REGULAR_EXPRESSION "\\[1\;32mAll tests passed" +) + if (CATCH_ENABLE_CONFIGURE_TESTS) add_test(NAME "CMakeConfig::DefaultReporter" COMMAND diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index c4425048..4688a228 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -1381,15 +1381,15 @@ CmdLine.tests.cpp:: passed: config.abortAfter == 1 for: 1 == 1 CmdLine.tests.cpp:: passed: config.shouldDebugBreak for: true CmdLine.tests.cpp:: passed: config.noThrow == true for: true == true CmdLine.tests.cpp:: passed: cli.parse({"test"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::Auto for: 0 == 0 -CmdLine.tests.cpp:: passed: cli.parse({"test", "--use-colour", "auto"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::Auto for: 0 == 0 -CmdLine.tests.cpp:: passed: cli.parse({"test", "--use-colour", "yes"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::Yes for: 1 == 1 -CmdLine.tests.cpp:: passed: cli.parse({"test", "--use-colour", "no"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::No for: 2 == 2 +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::PlatformDefault for: 0 == 0 +CmdLine.tests.cpp:: passed: cli.parse( { "test", "--colour-mode", "default" } ) for: {?} +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::PlatformDefault for: 0 == 0 +CmdLine.tests.cpp:: passed: cli.parse({"test", "--colour-mode", "ansi"}) for: {?} +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::ANSI for: 1 == 1 +CmdLine.tests.cpp:: passed: cli.parse({"test", "--colour-mode", "none"}) for: {?} +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::None for: 3 == 3 CmdLine.tests.cpp:: passed: !result for: true -CmdLine.tests.cpp:: passed: result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" +CmdLine.tests.cpp:: passed: result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: default, ansi, win32, or none. 'wrong' not recognised" contains: "colour mode must be one of" CmdLine.tests.cpp:: passed: cli.parse({ "test", "--benchmark-samples=200" }) for: {?} CmdLine.tests.cpp:: passed: config.benchmarkSamples == 200 for: 200 == 200 CmdLine.tests.cpp:: passed: cli.parse({ "test", "--benchmark-resamples=20000" }) for: {?} diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 55d2cf6a..c571b0c9 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -1379,15 +1379,15 @@ CmdLine.tests.cpp:: passed: config.abortAfter == 1 for: 1 == 1 CmdLine.tests.cpp:: passed: config.shouldDebugBreak for: true CmdLine.tests.cpp:: passed: config.noThrow == true for: true == true CmdLine.tests.cpp:: passed: cli.parse({"test"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::Auto for: 0 == 0 -CmdLine.tests.cpp:: passed: cli.parse({"test", "--use-colour", "auto"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::Auto for: 0 == 0 -CmdLine.tests.cpp:: passed: cli.parse({"test", "--use-colour", "yes"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::Yes for: 1 == 1 -CmdLine.tests.cpp:: passed: cli.parse({"test", "--use-colour", "no"}) for: {?} -CmdLine.tests.cpp:: passed: config.useColour == UseColour::No for: 2 == 2 +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::PlatformDefault for: 0 == 0 +CmdLine.tests.cpp:: passed: cli.parse( { "test", "--colour-mode", "default" } ) for: {?} +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::PlatformDefault for: 0 == 0 +CmdLine.tests.cpp:: passed: cli.parse({"test", "--colour-mode", "ansi"}) for: {?} +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::ANSI for: 1 == 1 +CmdLine.tests.cpp:: passed: cli.parse({"test", "--colour-mode", "none"}) for: {?} +CmdLine.tests.cpp:: passed: config.colourMode == ColourMode::None for: 3 == 3 CmdLine.tests.cpp:: passed: !result for: true -CmdLine.tests.cpp:: passed: result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" +CmdLine.tests.cpp:: passed: result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: default, ansi, win32, or none. 'wrong' not recognised" contains: "colour mode must be one of" CmdLine.tests.cpp:: passed: cli.parse({ "test", "--benchmark-samples=200" }) for: {?} CmdLine.tests.cpp:: passed: config.benchmarkSamples == 200 for: 200 == 200 CmdLine.tests.cpp:: passed: cli.parse({ "test", "--benchmark-resamples=20000" }) for: {?} diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 9da51362..5655f50a 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -9969,7 +9969,7 @@ with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::Auto ) + REQUIRE( config.colourMode == ColourMode::PlatformDefault ) with expansion: 0 == 0 @@ -9982,12 +9982,12 @@ CmdLine.tests.cpp: ............................................................................... CmdLine.tests.cpp:: PASSED: - CHECK( cli.parse({"test", "--use-colour", "auto"}) ) + CHECK( cli.parse( { "test", "--colour-mode", "default" } ) ) with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::Auto ) + REQUIRE( config.colourMode == ColourMode::PlatformDefault ) with expansion: 0 == 0 @@ -10000,12 +10000,12 @@ CmdLine.tests.cpp: ............................................................................... CmdLine.tests.cpp:: PASSED: - CHECK( cli.parse({"test", "--use-colour", "yes"}) ) + CHECK( cli.parse({"test", "--colour-mode", "ansi"}) ) with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::Yes ) + REQUIRE( config.colourMode == ColourMode::ANSI ) with expansion: 1 == 1 @@ -10018,14 +10018,14 @@ CmdLine.tests.cpp: ............................................................................... CmdLine.tests.cpp:: PASSED: - CHECK( cli.parse({"test", "--use-colour", "no"}) ) + CHECK( cli.parse({"test", "--colour-mode", "none"}) ) with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::No ) + REQUIRE( config.colourMode == ColourMode::None ) with expansion: - 2 == 2 + 3 == 3 ------------------------------------------------------------------------------- Process can be configured on command line @@ -10043,8 +10043,8 @@ with expansion: CmdLine.tests.cpp:: PASSED: CHECK_THAT( result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) ) with expansion: - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" - contains: "colour mode must be one of" + "colour mode must be one of: default, ansi, win32, or none. 'wrong' not + recognised" contains: "colour mode must be one of" ------------------------------------------------------------------------------- Process can be configured on command line diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 4738113a..32fa0689 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -9967,7 +9967,7 @@ with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::Auto ) + REQUIRE( config.colourMode == ColourMode::PlatformDefault ) with expansion: 0 == 0 @@ -9980,12 +9980,12 @@ CmdLine.tests.cpp: ............................................................................... CmdLine.tests.cpp:: PASSED: - CHECK( cli.parse({"test", "--use-colour", "auto"}) ) + CHECK( cli.parse( { "test", "--colour-mode", "default" } ) ) with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::Auto ) + REQUIRE( config.colourMode == ColourMode::PlatformDefault ) with expansion: 0 == 0 @@ -9998,12 +9998,12 @@ CmdLine.tests.cpp: ............................................................................... CmdLine.tests.cpp:: PASSED: - CHECK( cli.parse({"test", "--use-colour", "yes"}) ) + CHECK( cli.parse({"test", "--colour-mode", "ansi"}) ) with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::Yes ) + REQUIRE( config.colourMode == ColourMode::ANSI ) with expansion: 1 == 1 @@ -10016,14 +10016,14 @@ CmdLine.tests.cpp: ............................................................................... CmdLine.tests.cpp:: PASSED: - CHECK( cli.parse({"test", "--use-colour", "no"}) ) + CHECK( cli.parse({"test", "--colour-mode", "none"}) ) with expansion: {?} CmdLine.tests.cpp:: PASSED: - REQUIRE( config.useColour == UseColour::No ) + REQUIRE( config.colourMode == ColourMode::None ) with expansion: - 2 == 2 + 3 == 3 ------------------------------------------------------------------------------- Process can be configured on command line @@ -10041,8 +10041,8 @@ with expansion: CmdLine.tests.cpp:: PASSED: CHECK_THAT( result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) ) with expansion: - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" - contains: "colour mode must be one of" + "colour mode must be one of: default, ansi, win32, or none. 'wrong' not + recognised" contains: "colour mode must be one of" ------------------------------------------------------------------------------- Process can be configured on command line diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 5da402f2..456e80ee 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -2601,23 +2601,23 @@ ok {test-number} - config.noThrow == true for: true == true # Process can be configured on command line ok {test-number} - cli.parse({"test"}) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::Auto for: 0 == 0 +ok {test-number} - config.colourMode == ColourMode::PlatformDefault for: 0 == 0 # Process can be configured on command line -ok {test-number} - cli.parse({"test", "--use-colour", "auto"}) for: {?} +ok {test-number} - cli.parse( { "test", "--colour-mode", "default" } ) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::Auto for: 0 == 0 +ok {test-number} - config.colourMode == ColourMode::PlatformDefault for: 0 == 0 # Process can be configured on command line -ok {test-number} - cli.parse({"test", "--use-colour", "yes"}) for: {?} +ok {test-number} - cli.parse({"test", "--colour-mode", "ansi"}) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::Yes for: 1 == 1 +ok {test-number} - config.colourMode == ColourMode::ANSI for: 1 == 1 # Process can be configured on command line -ok {test-number} - cli.parse({"test", "--use-colour", "no"}) for: {?} +ok {test-number} - cli.parse({"test", "--colour-mode", "none"}) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::No for: 2 == 2 +ok {test-number} - config.colourMode == ColourMode::None for: 3 == 3 # Process can be configured on command line ok {test-number} - !result for: true # Process can be configured on command line -ok {test-number} - result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" +ok {test-number} - result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: default, ansi, win32, or none. 'wrong' not recognised" contains: "colour mode must be one of" # Process can be configured on command line ok {test-number} - cli.parse({ "test", "--benchmark-samples=200" }) for: {?} # Process can be configured on command line diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 1e637a17..534005df 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -2599,23 +2599,23 @@ ok {test-number} - config.noThrow == true for: true == true # Process can be configured on command line ok {test-number} - cli.parse({"test"}) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::Auto for: 0 == 0 +ok {test-number} - config.colourMode == ColourMode::PlatformDefault for: 0 == 0 # Process can be configured on command line -ok {test-number} - cli.parse({"test", "--use-colour", "auto"}) for: {?} +ok {test-number} - cli.parse( { "test", "--colour-mode", "default" } ) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::Auto for: 0 == 0 +ok {test-number} - config.colourMode == ColourMode::PlatformDefault for: 0 == 0 # Process can be configured on command line -ok {test-number} - cli.parse({"test", "--use-colour", "yes"}) for: {?} +ok {test-number} - cli.parse({"test", "--colour-mode", "ansi"}) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::Yes for: 1 == 1 +ok {test-number} - config.colourMode == ColourMode::ANSI for: 1 == 1 # Process can be configured on command line -ok {test-number} - cli.parse({"test", "--use-colour", "no"}) for: {?} +ok {test-number} - cli.parse({"test", "--colour-mode", "none"}) for: {?} # Process can be configured on command line -ok {test-number} - config.useColour == UseColour::No for: 2 == 2 +ok {test-number} - config.colourMode == ColourMode::None for: 3 == 3 # Process can be configured on command line ok {test-number} - !result for: true # Process can be configured on command line -ok {test-number} - result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" +ok {test-number} - result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) for: "colour mode must be one of: default, ansi, win32, or none. 'wrong' not recognised" contains: "colour mode must be one of" # Process can be configured on command line ok {test-number} - cli.parse({ "test", "--benchmark-samples=200" }) for: {?} # Process can be configured on command line diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index fdd4c3b7..f9518c3d 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -12165,7 +12165,7 @@ C - config.useColour == UseColour::Auto + config.colourMode == ColourMode::PlatformDefault 0 == 0 @@ -12179,7 +12179,7 @@ C
- cli.parse({"test", "--use-colour", "auto"}) + cli.parse( { "test", "--colour-mode", "default" } ) {?} @@ -12187,7 +12187,7 @@ C - config.useColour == UseColour::Auto + config.colourMode == ColourMode::PlatformDefault 0 == 0 @@ -12201,7 +12201,7 @@ C
- cli.parse({"test", "--use-colour", "yes"}) + cli.parse({"test", "--colour-mode", "ansi"}) {?} @@ -12209,7 +12209,7 @@ C - config.useColour == UseColour::Yes + config.colourMode == ColourMode::ANSI 1 == 1 @@ -12223,7 +12223,7 @@ C
- cli.parse({"test", "--use-colour", "no"}) + cli.parse({"test", "--colour-mode", "none"}) {?} @@ -12231,10 +12231,10 @@ C - config.useColour == UseColour::No + config.colourMode == ColourMode::None - 2 == 2 + 3 == 3 @@ -12256,7 +12256,7 @@ C result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" + "colour mode must be one of: default, ansi, win32, or none. 'wrong' not recognised" contains: "colour mode must be one of" diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index 5d0f7951..6617afe3 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -12165,7 +12165,7 @@ C - config.useColour == UseColour::Auto + config.colourMode == ColourMode::PlatformDefault 0 == 0 @@ -12179,7 +12179,7 @@ C
- cli.parse({"test", "--use-colour", "auto"}) + cli.parse( { "test", "--colour-mode", "default" } ) {?} @@ -12187,7 +12187,7 @@ C - config.useColour == UseColour::Auto + config.colourMode == ColourMode::PlatformDefault 0 == 0 @@ -12201,7 +12201,7 @@ C
- cli.parse({"test", "--use-colour", "yes"}) + cli.parse({"test", "--colour-mode", "ansi"}) {?} @@ -12209,7 +12209,7 @@ C - config.useColour == UseColour::Yes + config.colourMode == ColourMode::ANSI 1 == 1 @@ -12223,7 +12223,7 @@ C
- cli.parse({"test", "--use-colour", "no"}) + cli.parse({"test", "--colour-mode", "none"}) {?} @@ -12231,10 +12231,10 @@ C - config.useColour == UseColour::No + config.colourMode == ColourMode::None - 2 == 2 + 3 == 3 @@ -12256,7 +12256,7 @@ C result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" + "colour mode must be one of: default, ansi, win32, or none. 'wrong' not recognised" contains: "colour mode must be one of" diff --git a/tests/SelfTest/IntrospectiveTests/CmdLine.tests.cpp b/tests/SelfTest/IntrospectiveTests/CmdLine.tests.cpp index 253b72e0..25d5fbd6 100644 --- a/tests/SelfTest/IntrospectiveTests/CmdLine.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/CmdLine.tests.cpp @@ -15,6 +15,8 @@ #include #include #include +#include + namespace { auto fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCaseInfo("", { name, desc }, CATCH_INTERNAL_LINEINFO); } @@ -556,34 +558,34 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" SECTION( "use-colour") { - using Catch::UseColour; + using Catch::ColourMode; SECTION( "without option" ) { CHECK(cli.parse({"test"})); - REQUIRE( config.useColour == UseColour::Auto ); + REQUIRE( config.colourMode == ColourMode::PlatformDefault ); } SECTION( "auto" ) { - CHECK(cli.parse({"test", "--use-colour", "auto"})); + CHECK( cli.parse( { "test", "--colour-mode", "default" } ) ); - REQUIRE( config.useColour == UseColour::Auto ); + REQUIRE( config.colourMode == ColourMode::PlatformDefault ); } SECTION( "yes" ) { - CHECK(cli.parse({"test", "--use-colour", "yes"})); + CHECK(cli.parse({"test", "--colour-mode", "ansi"})); - REQUIRE( config.useColour == UseColour::Yes ); + REQUIRE( config.colourMode == ColourMode::ANSI ); } SECTION( "no" ) { - CHECK(cli.parse({"test", "--use-colour", "no"})); + CHECK(cli.parse({"test", "--colour-mode", "none"})); - REQUIRE( config.useColour == UseColour::No ); + REQUIRE( config.colourMode == ColourMode::None ); } SECTION( "error" ) { - auto result = cli.parse({"test", "--use-colour", "wrong"}); + auto result = cli.parse({"test", "--colour-mode", "wrong"}); CHECK( !result ); CHECK_THAT( result.errorMessage(), ContainsSubstring( "colour mode must be one of" ) ); } @@ -712,3 +714,17 @@ TEST_CASE("Various suspicious reporter specs are rejected", auto result = cli.parse( { "test", "--reporter", spec } ); REQUIRE_FALSE( result ); } + +TEST_CASE("Win32 colour implementation is compile-time optional", + "[approvals][cli][colours]") { + Catch::ConfigData config; + auto cli = Catch::makeCommandLineParser( config ); + + auto result = cli.parse( { "test", "--colour-mode", "win32" } ); + +#if defined( CATCH_CONFIG_COLOUR_WIN32 ) + REQUIRE( result ); +#else + REQUIRE_FALSE( result ); +#endif +} diff --git a/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp b/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp index 34afc1a2..92367915 100644 --- a/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp @@ -64,10 +64,7 @@ TEST_CASE( "The default listing implementation write to provided stream", { "fake test name"_catch_sr, "[fakeTestTag]"_catch_sr }, { "fake-file.cpp", 123456789 } }; std::vector tests({ {&fakeInfo, nullptr} }); - Catch::ConfigData cd; - cd.useColour = Catch::UseColour::No; - Catch::Config conf(cd); - auto colour = Catch::makeColourImpl( &conf, &sstream); + auto colour = Catch::makeColourImpl( Catch::ColourMode::None, &sstream); Catch::defaultListTests(sstream.stream(), colour.get(), tests, false, Catch::Verbosity::Normal); auto listingString = sstream.str();