diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f50492c..ea35d24e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON)
endif()
-project(Catch2 LANGUAGES CXX VERSION 2.6.1)
+project(Catch2 LANGUAGES CXX VERSION 2.7.0)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
diff --git a/README.md b/README.md
index 4db6bc54..08095f1c 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,11 @@
[](https://travis-ci.org/catchorg/Catch2)
[](https://ci.appveyor.com/project/catchorg/catch2)
[](https://codecov.io/gh/catchorg/Catch2)
-[](https://wandbox.org/permlink/rJhfG8exsneDGleb)
+[](https://wandbox.org/permlink/byNJIivVphHo170P)
[](https://discord.gg/4CWS9zD)
-The latest version of the single header can be downloaded directly using this link
+The latest version of the single header can be downloaded directly using this link
## Catch2 is released!
diff --git a/docs/release-notes.md b/docs/release-notes.md
index df8a11b8..34278c38 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -2,6 +2,7 @@
# Release notes
**Contents**
+[2.7.0](#270)
[2.6.1](#261)
[2.6.0](#260)
[2.5.0](#250)
@@ -20,6 +21,39 @@
[Older versions](#older-versions)
[Even Older versions](#even-older-versions)
+## 2.7.0
+
+### Improvements
+* `TEMPLATE_PRODUCT_TEST_CASE` now uses the resulting type in the name, instead of the serial number (#1544)
+* Catch2's single header is now strictly ASCII (#1542)
+* Added generator for random integral/floating point types
+ * The types are inferred within the `random` helper
+* Added back RangeGenerator (#1526)
+ * RangeGenerator returns elements within a certain range
+* Added ChunkGenerator generic transform (#1538)
+ * A ChunkGenerator returns the elements from different generator in chunks of n elements
+* Added `UNSCOPED_INFO` (#415, #983, #1522)
+ * This is a variant of `INFO` that lives until next assertion/end of the test case.
+
+
+### Fixes
+* All calls to C stdlib functions are now `std::` qualified (#1541)
+ * Code brought in from Clara was also updated.
+* Running tests will no longer open the specified output file twice (#1545)
+ * This would cause trouble when the file was not a file, but rather a named pipe
+ * Fixes the CLion/Resharper integration with Catch
+* Fixed `-Wunreachable-code` occuring with (old) ccache+cmake+clang combination (#1540)
+* Fixed `-Wdefaulted-function-deleted` warning with Clang 8 (#1537)
+* Catch2's type traits and helpers are now properly namespaced inside `Catch::` (#1548)
+* Fixed std{out,err} redirection for failing test (#1514, #1525)
+ * Somehow, this bug has been present for well over a year before it was reported
+
+
+### Contrib
+* `ParseAndAddCatchTests` now properly escapes commas in the test name
+
+
+
## 2.6.1
### Improvements
diff --git a/include/catch.hpp b/include/catch.hpp
index 88a9abe6..e15588f0 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -10,8 +10,8 @@
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2
-#define CATCH_VERSION_MINOR 6
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_MINOR 7
+#define CATCH_VERSION_PATCH 0
#ifdef __clang__
# pragma clang system_header
diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp
index d6ae3c6e..a1d08b2c 100644
--- a/include/internal/catch_version.cpp
+++ b/include/internal/catch_version.cpp
@@ -37,7 +37,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 6, 1, "", 0 );
+ static Version version( 2, 7, 0, "", 0 );
return version;
}
diff --git a/single_include/catch2/catch.hpp b/single_include/catch2/catch.hpp
index 994de46a..1850fff1 100644
--- a/single_include/catch2/catch.hpp
+++ b/single_include/catch2/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v2.6.1
- * Generated: 2019-02-12 19:52:52.262497
+ * Catch v2.7.0
+ * Generated: 2019-03-07 21:34:30.252164
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@@ -14,8 +14,8 @@
#define CATCH_VERSION_MAJOR 2
-#define CATCH_VERSION_MINOR 6
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_MINOR 7
+#define CATCH_VERSION_PATCH 0
#ifdef __clang__
# pragma clang system_header
@@ -711,6 +711,16 @@ struct is_unique : std::integral_constant
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
+#else
+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
+#endif
#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
@@ -725,7 +735,7 @@ struct is_unique : std::integral_constant
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
#endif
-#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) TypeList
+#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList
#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
@@ -736,65 +746,59 @@ struct is_unique : std::integral_constant
#include
+namespace Catch {
template< typename... >
-struct TypeList{};
+struct TypeList {};
template< typename... >
struct append;
template< template class L1
- , typename...E1
- , template class L2
- , typename...E2
- >
-struct append< L1, L2 >
-{
- using type = L1;
+ , typename...E1
+ , template class L2
+ , typename...E2
+>
+struct append< L1, L2 > {
+ using type = L1;
};
template< template class L1
- , typename...E1
- , template class L2
- , typename...E2
- , typename...Rest
- >
-struct append< L1, L2, Rest...>
-{
- using type = typename append< L1, Rest... >::type;
+ , typename...E1
+ , template class L2
+ , typename...E2
+ , typename...Rest
+>
+struct append< L1, L2, Rest...> {
+ using type = typename append< L1, Rest... >::type;
};
template< template class
- , typename...
- >
+ , typename...
+>
struct rewrap;
template< template class Container
- , template class List
- , typename...elems
- >
-struct rewrap>
-{
+ , template class List
+ , typename...elems
+>
+struct rewrap> {
using type = TypeList< Container< elems... > >;
};
template< template class Container
- , template class List
- , class...Elems
- , typename...Elements>
-struct rewrap, Elements...>
-{
+ , template class List
+ , class...Elems
+ , typename...Elements>
+ struct rewrap, Elements...> {
using type = typename append>, typename rewrap::type>::type;
};
template< template class...Containers >
-struct combine
-{
+struct combine {
template< typename...Types >
- struct with_types
- {
+ struct with_types {
template< template class Final >
- struct into
- {
+ struct into {
using type = typename append, typename rewrap::type...>::type;
};
};
@@ -803,6 +807,8 @@ struct combine
template
struct always_false : std::false_type {};
+} // namespace Catch
+
// end catch_meta.hpp
namespace Catch {
@@ -949,11 +955,14 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \
int index = 0; \
using expander = int[]; \
- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + Catch::StringMaker::convert(index++), Tags } ), 0)... };/* NOLINT */ \
+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
} \
}; \
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
- using TestInit = combine \
+ using TestInit = Catch::combine \
::with_types::into::type; \
TestInit(); \
return 0; \
@@ -1014,11 +1023,14 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
int index = 0;\
using expander = int[];\
- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + Catch::StringMaker::convert(index++), Tags } ), 0)... };/* NOLINT */ \
+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- using TestInit = combine\
+ using TestInit = Catch::combine\
::with_types::into::type;\
TestInit();\
return 0;\
@@ -2062,6 +2074,7 @@ namespace Catch {
struct SectionInfo;
struct SectionEndInfo;
struct MessageInfo;
+ struct MessageBuilder;
struct Counts;
struct BenchmarkInfo;
struct BenchmarkStats;
@@ -2088,6 +2101,8 @@ namespace Catch {
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( MessageInfo const& message ) = 0;
+ virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
+
virtual void handleFatalErrorCondition( StringRef message ) = 0;
virtual void handleExpr
@@ -2251,9 +2266,12 @@ namespace Catch {
class ScopedMessage {
public:
explicit ScopedMessage( MessageBuilder const& builder );
+ ScopedMessage( ScopedMessage& duplicate ) = delete;
+ ScopedMessage( ScopedMessage&& old );
~ScopedMessage();
MessageInfo m_info;
+ bool m_moved;
};
class Capturer {
@@ -2316,7 +2334,7 @@ namespace Catch {
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
- } while( (void)0, false && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
+ } while( (void)0, (false) && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
///////////////////////////////////////////////////////////////////////////////
@@ -2397,6 +2415,10 @@ namespace Catch {
#define INTERNAL_CATCH_INFO( macroName, log ) \
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
+ Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
+
///////////////////////////////////////////////////////////////////////////////
// Although this is matcher-based, it can be used with just a string
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
@@ -3642,6 +3664,36 @@ namespace Generators {
return makeGenerators( value( T( std::forward( val ) ) ), std::forward( moreGenerators )... );
}
+ auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
+
+ template
+ // Note: The type after -> is weird, because VS2015 cannot parse
+ // the expression used in the typedef inside, when it is in
+ // return type. Yeah.
+ auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval().get()) {
+ using UnderlyingType = typename decltype(generatorExpression())::type;
+
+ IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
+ if (!tracker.hasGenerator()) {
+ tracker.setGenerator(pf::make_unique>(generatorExpression()));
+ }
+
+ auto const& generator = static_cast const&>( *tracker.getGenerator() );
+ return generator.get();
+ }
+
+} // namespace Generators
+} // namespace Catch
+
+#define GENERATE( ... ) \
+ Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
+
+// end catch_generators.hpp
+// start catch_generators_generic.hpp
+
+namespace Catch {
+namespace Generators {
+
template
class TakeGenerator : public IGenerator {
GeneratorWrapper m_generator;
@@ -3810,31 +3862,297 @@ namespace Generators {
);
}
- auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
-
- template
- // Note: The type after -> is weird, because VS2015 cannot parse
- // the expression used in the typedef inside, when it is in
- // return type. Yeah, ¯\_(ツ)_/¯
- auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval().get()) {
- using UnderlyingType = typename decltype(generatorExpression())::type;
-
- IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
- if (!tracker.hasGenerator()) {
- tracker.setGenerator(pf::make_unique>(generatorExpression()));
+ template
+ class ChunkGenerator final : public IGenerator> {
+ std::vector m_chunk;
+ size_t m_chunk_size;
+ GeneratorWrapper m_generator;
+ bool m_used_up = false;
+ public:
+ ChunkGenerator(size_t size, GeneratorWrapper generator) :
+ m_chunk_size(size), m_generator(std::move(generator))
+ {
+ m_chunk.reserve(m_chunk_size);
+ m_chunk.push_back(m_generator.get());
+ for (size_t i = 1; i < m_chunk_size; ++i) {
+ if (!m_generator.next()) {
+ Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
+ }
+ m_chunk.push_back(m_generator.get());
+ }
}
+ std::vector const& get() const override {
+ return m_chunk;
+ }
+ bool next() override {
+ m_chunk.clear();
+ for (size_t idx = 0; idx < m_chunk_size; ++idx) {
+ if (!m_generator.next()) {
+ return false;
+ }
+ m_chunk.push_back(m_generator.get());
+ }
+ return true;
+ }
+ };
- auto const& generator = static_cast const&>( *tracker.getGenerator() );
- return generator.get();
+ template
+ GeneratorWrapper> chunk(size_t size, GeneratorWrapper&& generator) {
+ return GeneratorWrapper>(
+ pf::make_unique>(size, std::move(generator))
+ );
}
} // namespace Generators
} // namespace Catch
-#define GENERATE( ... ) \
- Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
+// end catch_generators_generic.hpp
+// start catch_generators_specific.hpp
-// end catch_generators.hpp
+// start catch_context.h
+
+#include
+
+namespace Catch {
+
+ struct IResultCapture;
+ struct IRunner;
+ struct IConfig;
+ struct IMutableContext;
+
+ using IConfigPtr = std::shared_ptr;
+
+ struct IContext
+ {
+ virtual ~IContext();
+
+ virtual IResultCapture* getResultCapture() = 0;
+ virtual IRunner* getRunner() = 0;
+ virtual IConfigPtr const& getConfig() const = 0;
+ };
+
+ struct IMutableContext : IContext
+ {
+ virtual ~IMutableContext();
+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+ virtual void setRunner( IRunner* runner ) = 0;
+ virtual void setConfig( IConfigPtr const& config ) = 0;
+
+ private:
+ static IMutableContext *currentContext;
+ friend IMutableContext& getCurrentMutableContext();
+ friend void cleanUpContext();
+ static void createContext();
+ };
+
+ inline IMutableContext& getCurrentMutableContext()
+ {
+ if( !IMutableContext::currentContext )
+ IMutableContext::createContext();
+ return *IMutableContext::currentContext;
+ }
+
+ inline IContext& getCurrentContext()
+ {
+ return getCurrentMutableContext();
+ }
+
+ void cleanUpContext();
+}
+
+// end catch_context.h
+// start catch_interfaces_config.h
+
+#include
+#include
+#include
+#include
+
+namespace Catch {
+
+ enum class Verbosity {
+ Quiet = 0,
+ Normal,
+ High
+ };
+
+ struct WarnAbout { enum What {
+ Nothing = 0x00,
+ NoAssertions = 0x01,
+ NoTests = 0x02
+ }; };
+
+ struct ShowDurations { enum OrNot {
+ DefaultForReporter,
+ Always,
+ Never
+ }; };
+ struct RunTests { enum InWhatOrder {
+ InDeclarationOrder,
+ InLexicographicalOrder,
+ InRandomOrder
+ }; };
+ struct UseColour { enum YesOrNo {
+ Auto,
+ Yes,
+ No
+ }; };
+ struct WaitForKeypress { enum When {
+ Never,
+ BeforeStart = 1,
+ BeforeExit = 2,
+ BeforeStartAndExit = BeforeStart | BeforeExit
+ }; };
+
+ class TestSpec;
+
+ struct IConfig : NonCopyable {
+
+ virtual ~IConfig();
+
+ virtual bool allowThrows() const = 0;
+ virtual std::ostream& stream() const = 0;
+ virtual std::string name() const = 0;
+ virtual bool includeSuccessfulResults() const = 0;
+ virtual bool shouldDebugBreak() const = 0;
+ virtual bool warnAboutMissingAssertions() const = 0;
+ virtual bool warnAboutNoTests() const = 0;
+ virtual int abortAfter() const = 0;
+ virtual bool showInvisibles() const = 0;
+ virtual ShowDurations::OrNot showDurations() const = 0;
+ virtual TestSpec const& testSpec() const = 0;
+ virtual bool hasTestFilters() const = 0;
+ virtual RunTests::InWhatOrder runOrder() const = 0;
+ virtual unsigned int rngSeed() const = 0;
+ virtual int benchmarkResolutionMultiple() const = 0;
+ virtual UseColour::YesOrNo useColour() const = 0;
+ virtual std::vector const& getSectionsToRun() const = 0;
+ virtual Verbosity verbosity() const = 0;
+ };
+
+ using IConfigPtr = std::shared_ptr;
+}
+
+// end catch_interfaces_config.h
+#include
+
+namespace Catch {
+namespace Generators {
+
+template
+class RandomFloatingGenerator final : public IGenerator {
+ // FIXME: What is the right seed?
+ std::minstd_rand m_rand;
+ std::uniform_real_distribution m_dist;
+ Float m_current_number;
+public:
+
+ RandomFloatingGenerator(Float a, Float b):
+ m_rand(getCurrentContext().getConfig()->rngSeed()),
+ m_dist(a, b) {
+ static_cast(next());
+ }
+
+ Float const& get() const override {
+ return m_current_number;
+ }
+ bool next() override {
+ m_current_number = m_dist(m_rand);
+ return true;
+ }
+};
+
+template
+class RandomIntegerGenerator final : public IGenerator {
+ std::minstd_rand m_rand;
+ std::uniform_int_distribution m_dist;
+ Integer m_current_number;
+public:
+
+ RandomIntegerGenerator(Integer a, Integer b):
+ m_rand(getCurrentContext().getConfig()->rngSeed()),
+ m_dist(a, b) {
+ static_cast(next());
+ }
+
+ Integer const& get() const override {
+ return m_current_number;
+ }
+ bool next() override {
+ m_current_number = m_dist(m_rand);
+ return true;
+ }
+};
+
+// TODO: Ideally this would be also constrained against the various char types,
+// but I don't expect users to run into that in practice.
+template
+typename std::enable_if::value && !std::is_same::value,
+GeneratorWrapper>::type
+random(T a, T b) {
+ return GeneratorWrapper(
+ pf::make_unique>(a, b)
+ );
+}
+
+template
+typename std::enable_if::value,
+GeneratorWrapper>::type
+random(T a, T b) {
+ return GeneratorWrapper(
+ pf::make_unique>(a, b)
+ );
+}
+
+template
+class RangeGenerator final : public IGenerator {
+ T m_current;
+ T m_end;
+ T m_step;
+ bool m_positive;
+
+public:
+ RangeGenerator(T const& start, T const& end, T const& step):
+ m_current(start),
+ m_end(end),
+ m_step(step),
+ m_positive(m_step > T(0))
+ {
+ assert(m_current != m_end && "Range start and end cannot be equal");
+ assert(m_step != T(0) && "Step size cannot be zero");
+ assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
+ }
+
+ RangeGenerator(T const& start, T const& end):
+ RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
+ {}
+
+ T const& get() const override {
+ return m_current;
+ }
+
+ bool next() override {
+ m_current += m_step;
+ return (m_positive) ? (m_current < m_end) : (m_current > m_end);
+ }
+};
+
+template
+GeneratorWrapper range(T const& start, T const& end, T const& step) {
+ static_assert(std::is_integral::value && !std::is_same::value, "Type must be an integer");
+ return GeneratorWrapper(pf::make_unique>(start, end, step));
+}
+
+template
+GeneratorWrapper range(T const& start, T const& end) {
+ static_assert(std::is_integral::value && !std::is_same::value, "Type must be an integer");
+ return GeneratorWrapper(pf::make_unique>(start, end));
+}
+
+} // namespace Generators
+} // namespace Catch
+
+// end catch_generators_specific.hpp
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
@@ -4321,79 +4639,6 @@ namespace Catch {
#endif
// end catch_test_spec_parser.h
-// start catch_interfaces_config.h
-
-#include
-#include
-#include
-#include
-
-namespace Catch {
-
- enum class Verbosity {
- Quiet = 0,
- Normal,
- High
- };
-
- struct WarnAbout { enum What {
- Nothing = 0x00,
- NoAssertions = 0x01,
- NoTests = 0x02
- }; };
-
- struct ShowDurations { enum OrNot {
- DefaultForReporter,
- Always,
- Never
- }; };
- struct RunTests { enum InWhatOrder {
- InDeclarationOrder,
- InLexicographicalOrder,
- InRandomOrder
- }; };
- struct UseColour { enum YesOrNo {
- Auto,
- Yes,
- No
- }; };
- struct WaitForKeypress { enum When {
- Never,
- BeforeStart = 1,
- BeforeExit = 2,
- BeforeStartAndExit = BeforeStart | BeforeExit
- }; };
-
- class TestSpec;
-
- struct IConfig : NonCopyable {
-
- virtual ~IConfig();
-
- virtual bool allowThrows() const = 0;
- virtual std::ostream& stream() const = 0;
- virtual std::string name() const = 0;
- virtual bool includeSuccessfulResults() const = 0;
- virtual bool shouldDebugBreak() const = 0;
- virtual bool warnAboutMissingAssertions() const = 0;
- virtual bool warnAboutNoTests() const = 0;
- virtual int abortAfter() const = 0;
- virtual bool showInvisibles() const = 0;
- virtual ShowDurations::OrNot showDurations() const = 0;
- virtual TestSpec const& testSpec() const = 0;
- virtual bool hasTestFilters() const = 0;
- virtual RunTests::InWhatOrder runOrder() const = 0;
- virtual unsigned int rngSeed() const = 0;
- virtual int benchmarkResolutionMultiple() const = 0;
- virtual UseColour::YesOrNo useColour() const = 0;
- virtual std::vector const& getSectionsToRun() const = 0;
- virtual Verbosity verbosity() const = 0;
- };
-
- using IConfigPtr = std::shared_ptr;
-}
-
-// end catch_interfaces_config.h
// Libstdc++ doesn't like incomplete classes for unique_ptr
#include
@@ -4673,8 +4918,8 @@ namespace Catch {
AssertionStats( AssertionStats const& ) = default;
AssertionStats( AssertionStats && ) = default;
- AssertionStats& operator = ( AssertionStats const& ) = default;
- AssertionStats& operator = ( AssertionStats && ) = default;
+ AssertionStats& operator = ( AssertionStats const& ) = delete;
+ AssertionStats& operator = ( AssertionStats && ) = delete;
virtual ~AssertionStats();
AssertionResult assertionResult;
@@ -5758,58 +6003,6 @@ std::string StringMaker::convert(Catch::Detail::Approx co
// end catch_approx.cpp
// start catch_assertionhandler.cpp
-// start catch_context.h
-
-#include
-
-namespace Catch {
-
- struct IResultCapture;
- struct IRunner;
- struct IConfig;
- struct IMutableContext;
-
- using IConfigPtr = std::shared_ptr;
-
- struct IContext
- {
- virtual ~IContext();
-
- virtual IResultCapture* getResultCapture() = 0;
- virtual IRunner* getRunner() = 0;
- virtual IConfigPtr const& getConfig() const = 0;
- };
-
- struct IMutableContext : IContext
- {
- virtual ~IMutableContext();
- virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
- virtual void setRunner( IRunner* runner ) = 0;
- virtual void setConfig( IConfigPtr const& config ) = 0;
-
- private:
- static IMutableContext *currentContext;
- friend IMutableContext& getCurrentMutableContext();
- friend void cleanUpContext();
- static void createContext();
- };
-
- inline IMutableContext& getCurrentMutableContext()
- {
- if( !IMutableContext::currentContext )
- IMutableContext::createContext();
- return *IMutableContext::currentContext;
- }
-
- inline IContext& getCurrentContext()
- {
- return getCurrentMutableContext();
- }
-
- void cleanUpContext();
-}
-
-// end catch_context.h
// start catch_debugger.h
namespace Catch {
@@ -5996,6 +6189,8 @@ namespace Catch {
void pushScopedMessage( MessageInfo const& message ) override;
void popScopedMessage( MessageInfo const& message ) override;
+ void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
+
std::string getCurrentTestName() const override;
const AssertionResult* getLastResult() const override;
@@ -6043,6 +6238,7 @@ namespace Catch {
Totals m_totals;
IStreamingReporterPtr m_reporter;
std::vector m_messages;
+ std::vector m_messageScopes; /* Keeps owners of so-called unscoped messages. */
AssertionInfo m_lastAssertionInfo;
std::vector m_unfinishedSections;
std::vector m_activeSections;
@@ -6679,6 +6875,7 @@ inline auto Column::operator + (Column const& other) -> Columns {
// ----------- end of #include from clara_textflow.hpp -----------
// ........... back in clara.hpp
+#include
#include
#include
#include
@@ -6971,7 +7168,7 @@ namespace detail {
}
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
std::string srcLC = source;
- std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } );
+ std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( std::tolower(c) ); } );
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
target = true;
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
@@ -9374,14 +9571,20 @@ namespace Catch {
////////////////////////////////////////////////////////////////////////////
ScopedMessage::ScopedMessage( MessageBuilder const& builder )
- : m_info( builder.m_info )
+ : m_info( builder.m_info ), m_moved()
{
m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info );
}
+ ScopedMessage::ScopedMessage( ScopedMessage&& old )
+ : m_info( old.m_info ), m_moved()
+ {
+ old.m_moved = true;
+ }
+
ScopedMessage::~ScopedMessage() {
- if ( !uncaught_exceptions() ){
+ if ( !uncaught_exceptions() && !m_moved ){
getResultCapture().popScopedMessage(m_info);
}
}
@@ -9489,6 +9692,22 @@ namespace Catch {
auto str() const -> std::string;
};
+ class RedirectedStreams {
+ public:
+ RedirectedStreams(RedirectedStreams const&) = delete;
+ RedirectedStreams& operator=(RedirectedStreams const&) = delete;
+ RedirectedStreams(RedirectedStreams&&) = delete;
+ RedirectedStreams& operator=(RedirectedStreams&&) = delete;
+
+ RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
+ ~RedirectedStreams();
+ private:
+ std::string& m_redirectedCout;
+ std::string& m_redirectedCerr;
+ RedirectedStdOut m_redirectedStdOut;
+ RedirectedStdErr m_redirectedStdErr;
+ };
+
#if defined(CATCH_CONFIG_NEW_CAPTURE)
// Windows's implementation of std::tmpfile is terrible (it tries
@@ -9580,6 +9799,16 @@ namespace Catch {
{}
auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
+ RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
+ : m_redirectedCout(redirectedCout),
+ m_redirectedCerr(redirectedCerr)
+ {}
+
+ RedirectedStreams::~RedirectedStreams() {
+ m_redirectedCout += m_redirectedStdOut.str();
+ m_redirectedCerr += m_redirectedStdErr.str();
+ }
+
#if defined(CATCH_CONFIG_NEW_CAPTURE)
#if defined(_MSC_VER)
@@ -10161,6 +10390,9 @@ namespace Catch {
// and should be let to clear themselves out.
static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
+ if (result.getResultType() != ResultWas::Warning)
+ m_messageScopes.clear();
+
// Reset working state
resetAssertionInfo();
m_lastResult = result;
@@ -10215,6 +10447,7 @@ namespace Catch {
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
m_messages.clear();
+ m_messageScopes.clear();
}
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
@@ -10241,6 +10474,10 @@ namespace Catch {
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
}
+ void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
+ m_messageScopes.emplace_back( builder );
+ }
+
std::string RunContext::getCurrentTestName() const {
return m_activeTestCase
? m_activeTestCase->getTestCaseInfo().name
@@ -10301,6 +10538,7 @@ namespace Catch {
m_lastAssertionPassed = true;
++m_totals.assertions.passed;
resetAssertionInfo();
+ m_messageScopes.clear();
}
bool RunContext::aborting() const {
@@ -10322,13 +10560,10 @@ namespace Catch {
CATCH_TRY {
if (m_reporter->getPreferences().shouldRedirectStdOut) {
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
- RedirectedStdOut redirectedStdOut;
- RedirectedStdErr redirectedStdErr;
+ RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
timer.start();
invokeActiveTestCase();
- redirectedCout += redirectedStdOut.str();
- redirectedCerr += redirectedStdErr.str();
#else
OutputRedirect r(redirectedCout, redirectedCerr);
timer.start();
@@ -10355,6 +10590,7 @@ namespace Catch {
m_testCaseTracker->close();
handleUnfinishedSections();
m_messages.clear();
+ m_messageScopes.clear();
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats);
@@ -10762,9 +10998,9 @@ namespace Catch {
return 1;
auto result = m_cli.parse( clara::Args( argc, argv ) );
- config();
- getCurrentMutableContext().setConfig( m_config );
if( !result ) {
+ config();
+ getCurrentMutableContext().setConfig(m_config);
Catch::cerr()
<< Colour( Colour::Red )
<< "\nError(s) in input:\n"
@@ -12429,7 +12665,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 6, 1, "", 0 );
+ static Version version( 2, 7, 0, "", 0 );
return version;
}
@@ -12781,7 +13017,7 @@ namespace Catch {
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
- sprintf(buffer, "%.3f", duration);
+ std::sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
@@ -13315,7 +13551,7 @@ public:
case Unit::Nanoseconds:
return "ns";
case Unit::Microseconds:
- return "µs";
+ return "us";
case Unit::Milliseconds:
return "ms";
case Unit::Seconds:
@@ -14464,6 +14700,7 @@ int main (int argc, char * const argv[]) {
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
+#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )