diff --git a/CMakeLists.txt b/CMakeLists.txt
index 549ee178..e2329c69 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.7.1)
+project(Catch2 LANGUAGES CXX VERSION 2.7.2)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
diff --git a/README.md b/README.md
index a09ad44b..535ac6ec 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/ZFBZ5XbLA9F1gzKi)
+[](https://wandbox.org/permlink/rsEsNO9M0flb5NlQ)
[](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 528f6cf1..c5f92d2b 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -2,6 +2,7 @@
# Release notes
**Contents**
+[2.7.2](#272)
[2.7.1](#271)
[2.7.0](#270)
[2.6.1](#261)
@@ -22,6 +23,28 @@
[Older versions](#older-versions)
[Even Older versions](#even-older-versions)
+
+## 2.7.2
+
+### Improvements
+* Added an approximate vector matcher (#1499)
+
+### Fixes
+* Filters will no longer be shown if there were none
+* Fixed compilation error when using Homebrew GCC on OS X (#1588, #1589)
+* Fixed the console reporter not showing messages that start with a newline (#1455, #1470)
+* Modified JUnit reporter's output so that rng seed and filters are reported according to the JUnit schema (#1598)
+* Fixed some obscure warnings and static analysis passes
+
+### Miscellaneous
+* Various improvements to `ParseAndAddCatchTests` (#1559, #1601)
+ * When a target is parsed, it receives `ParseAndAddCatchTests_TESTS` property which summarizes found tests
+ * Fixed problem with tests not being found if the `OptionalCatchTestLauncher` variables is used
+ * Including the script will no longer forcefully modify `CMAKE_MINIMUM_REQUIRED_VERSION`
+ * CMake object libraries are ignored when parsing to avoid needless warnings
+* `CatchAddTests` now adds test's tags to their CTest labels (#1600)
+* Added basic CPack support to our build
+
## 2.7.1
### Improvements
diff --git a/include/catch.hpp b/include/catch.hpp
index 5ee7ffdd..5667def9 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 7
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_PATCH 2
#ifdef __clang__
# pragma clang system_header
diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp
index 43832053..5f4917c1 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, 7, 1, "", 0 );
+ static Version version( 2, 7, 2, "", 0 );
return version;
}
diff --git a/single_include/catch2/catch.hpp b/single_include/catch2/catch.hpp
index 98672c07..df14c357 100644
--- a/single_include/catch2/catch.hpp
+++ b/single_include/catch2/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v2.7.1
- * Generated: 2019-04-05 18:22:37.720122
+ * Catch v2.7.2
+ * Generated: 2019-04-22 23:13:14.687465
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 7
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_PATCH 2
#ifdef __clang__
# pragma clang system_header
@@ -3113,7 +3113,7 @@ public:
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
- // infering std::function is hard (but possible) and
+ // inferring std::function is hard (but possible) and
// requires a lot of TMP.
template
Generic::PredicateMatcher Predicate(std::function const& predicate, std::string const& description = "") {
@@ -3201,28 +3201,6 @@ namespace Catch {
namespace Matchers {
namespace Vector {
- namespace Detail {
- template
- size_t count(InputIterator first, InputIterator last, T const& item) {
- size_t cnt = 0;
- for (; first != last; ++first) {
- if (*first == item) {
- ++cnt;
- }
- }
- return cnt;
- }
- template
- bool contains(InputIterator first, InputIterator last, T const& item) {
- for (; first != last; ++first) {
- if (*first == item) {
- return true;
- }
- }
- return false;
- }
- }
-
template
struct ContainsElementMatcher : MatcherBase> {
@@ -3297,6 +3275,42 @@ namespace Matchers {
std::vector const& m_comparator;
};
+ template
+ struct ApproxMatcher : MatcherBase> {
+
+ ApproxMatcher(std::vector const& comparator) : m_comparator( comparator ) {}
+
+ bool match(std::vector const &v) const override {
+ if (m_comparator.size() != v.size())
+ return false;
+ for (std::size_t i = 0; i < v.size(); ++i)
+ if (m_comparator[i] != approx(v[i]))
+ return false;
+ return true;
+ }
+ std::string describe() const override {
+ return "is approx: " + ::Catch::Detail::stringify( m_comparator );
+ }
+ template ::value>::type>
+ ApproxMatcher& epsilon( T const& newEpsilon ) {
+ approx.epsilon(newEpsilon);
+ return *this;
+ }
+ template ::value>::type>
+ ApproxMatcher& margin( T const& newMargin ) {
+ approx.margin(newMargin);
+ return *this;
+ }
+ template ::value>::type>
+ ApproxMatcher& scale( T const& newScale ) {
+ approx.scale(newScale);
+ return *this;
+ }
+
+ std::vector const& m_comparator;
+ mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
+ };
+
template
struct UnorderedEqualsMatcher : MatcherBase> {
UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {}
@@ -3306,28 +3320,7 @@ namespace Matchers {
if (m_target.size() != vec.size()) {
return false;
}
- auto lfirst = m_target.begin(), llast = m_target.end();
- auto rfirst = vec.begin(), rlast = vec.end();
- // Cut common prefix to optimize checking of permuted parts
- while (lfirst != llast && *lfirst == *rfirst) {
- ++lfirst; ++rfirst;
- }
- if (lfirst == llast) {
- return true;
- }
-
- for (auto mid = lfirst; mid != llast; ++mid) {
- // Skip already counted items
- if (Detail::contains(lfirst, mid, *mid)) {
- continue;
- }
- size_t num_vec = Detail::count(rfirst, rlast, *mid);
- if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
- return false;
- }
- }
-
- return true;
+ return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
}
std::string describe() const override {
@@ -3357,6 +3350,11 @@ namespace Matchers {
return Vector::EqualsMatcher( comparator );
}
+ template
+ Vector::ApproxMatcher Approx( std::vector const& comparator ) {
+ return Vector::ApproxMatcher( comparator );
+ }
+
template
Vector::UnorderedEqualsMatcher UnorderedEquals(std::vector const& target) {
return Vector::UnorderedEqualsMatcher(target);
@@ -4535,7 +4533,7 @@ namespace Catch {
public:
NamePattern( std::string const& name );
virtual ~NamePattern();
- virtual bool matches( TestCaseInfo const& testCase ) const override;
+ bool matches( TestCaseInfo const& testCase ) const override;
private:
WildcardPattern m_wildcardPattern;
};
@@ -4544,7 +4542,7 @@ namespace Catch {
public:
TagPattern( std::string const& tag );
virtual ~TagPattern();
- virtual bool matches( TestCaseInfo const& testCase ) const override;
+ bool matches( TestCaseInfo const& testCase ) const override;
private:
std::string m_tag;
};
@@ -4553,7 +4551,7 @@ namespace Catch {
public:
ExcludedPattern( PatternPtr const& underlyingPattern );
virtual ~ExcludedPattern();
- virtual bool matches( TestCaseInfo const& testCase ) const override;
+ bool matches( TestCaseInfo const& testCase ) const override;
private:
PatternPtr m_underlyingPattern;
};
@@ -4728,7 +4726,7 @@ namespace Catch {
std::vector const& getTestsOrTags() const override;
std::vector const& getSectionsToRun() const override;
- virtual TestSpec const& testSpec() const override;
+ TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const;
@@ -5419,11 +5417,11 @@ namespace Catch {
class ReporterFactory : public IReporterFactory {
- virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
+ IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr( new T( config ) );
}
- virtual std::string getDescription() const override {
+ std::string getDescription() const override {
return T::getDescription();
}
};
@@ -5440,10 +5438,10 @@ namespace Catch {
class ListenerFactory : public IReporterFactory {
- virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
+ IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr( new T( config ) );
}
- virtual std::string getDescription() const override {
+ std::string getDescription() const override {
return std::string();
}
};
@@ -5844,8 +5842,6 @@ namespace TestCaseTracking {
public:
- static TrackerContext& instance();
-
ITracker& startRun();
void endRun();
@@ -5991,18 +5987,18 @@ namespace Detail {
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
}
- void Approx::setMargin(double margin) {
- CATCH_ENFORCE(margin >= 0,
- "Invalid Approx::margin: " << margin << '.'
+ void Approx::setMargin(double newMargin) {
+ CATCH_ENFORCE(newMargin >= 0,
+ "Invalid Approx::margin: " << newMargin << '.'
<< " Approx::Margin has to be non-negative.");
- m_margin = margin;
+ m_margin = newMargin;
}
- void Approx::setEpsilon(double epsilon) {
- CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
- "Invalid Approx::epsilon: " << epsilon << '.'
+ void Approx::setEpsilon(double newEpsilon) {
+ CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
+ "Invalid Approx::epsilon: " << newEpsilon << '.'
<< " Approx::epsilon has to be in [0, 1]");
- m_epsilon = epsilon;
+ m_epsilon = newEpsilon;
}
} // end namespace Detail
@@ -6638,6 +6634,9 @@ public:
m_suffix = false;
auto width = m_column.m_width - indent();
m_end = m_pos;
+ if (line()[m_pos] == '\n') {
+ ++m_end;
+ }
while (m_end < line().size() && line()[m_end] != '\n')
++m_end;
@@ -8042,10 +8041,7 @@ namespace Catch {
m_stream( openStream() )
{
TestSpecParser parser(ITagAliasRegistry::get());
- if (data.testsOrTags.empty()) {
- parser.parse("~[.]"); // All not hidden tests
- }
- else {
+ if (!data.testsOrTags.empty()) {
m_hasTestFilters = true;
for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags );
@@ -8163,7 +8159,7 @@ namespace {
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
}
- virtual void use( Colour::Code _colourCode ) override {
+ void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -8226,7 +8222,7 @@ namespace {
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
public:
- virtual void use( Colour::Code _colourCode ) override {
+ void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@@ -8337,27 +8333,27 @@ namespace Catch {
class Context : public IMutableContext, NonCopyable {
public: // IContext
- virtual IResultCapture* getResultCapture() override {
+ IResultCapture* getResultCapture() override {
return m_resultCapture;
}
- virtual IRunner* getRunner() override {
+ IRunner* getRunner() override {
return m_runner;
}
- virtual IConfigPtr const& getConfig() const override {
+ IConfigPtr const& getConfig() const override {
return m_config;
}
- virtual ~Context() override;
+ ~Context() override;
public: // IMutableContext
- virtual void setResultCapture( IResultCapture* resultCapture ) override {
+ void setResultCapture( IResultCapture* resultCapture ) override {
m_resultCapture = resultCapture;
}
- virtual void setRunner( IRunner* runner ) override {
+ void setRunner( IRunner* runner ) override {
m_runner = runner;
}
- virtual void setConfig( IConfigPtr const& config ) override {
+ void setConfig( IConfigPtr const& config ) override {
m_config = config;
}
@@ -8423,19 +8419,23 @@ namespace Catch {
# include
# include
# include
-# include
# include
# include
-namespace Catch {
+#ifdef __apple_build_version__
+ // These headers will only compile with AppleClang (XCode)
+ // For other compilers (Clang, GCC, ... ) we need to exclude them
+# include
+#endif
+ namespace Catch {
+ #ifdef __apple_build_version__
// The following function is taken directly from the following technical note:
- // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+ // https://developer.apple.com/library/archive/qa/qa1361/_index.html
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
bool isDebuggerActive(){
-
int mib[4];
struct kinfo_proc info;
std::size_t size;
@@ -8465,6 +8465,12 @@ namespace Catch {
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}
+ #else
+ bool isDebuggerActive() {
+ // We need to find another way to determine this for non-appleclang compilers on macOS
+ return false;
+ }
+ #endif
} // namespace Catch
#elif defined(CATCH_PLATFORM_LINUX)
@@ -8569,7 +8575,7 @@ namespace Catch {
public:
~ExceptionTranslatorRegistry();
virtual void registerTranslator( const IExceptionTranslator* translator );
- virtual std::string translateActiveException() const override;
+ std::string translateActiveException() const override;
std::string tryTranslators() const;
private:
@@ -9842,7 +9848,7 @@ namespace Catch {
if (strerror_s(buffer, errno)) {
CATCH_RUNTIME_ERROR("Could not translate errno to a string");
}
- CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
+ CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
}
}
#else
@@ -10920,7 +10926,10 @@ namespace Catch {
auto const& allTestCases = getAllTestCasesSorted(*config);
for (auto const& testCase : allTestCases) {
- if (!context.aborting() && matchTest(testCase, testSpec, *config))
+ bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
+ (testSpec.hasFilters() && matchTest(testCase, testSpec, *config));
+
+ if (!context.aborting() && matching)
totals += context.runTest(testCase);
else
context.reporter().skipTest(testCase);
@@ -11646,7 +11655,7 @@ namespace Catch {
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
- << "Tag names starting with non alpha-numeric characters are reserved\n"
+ << "Tag names starting with non alphanumeric characters are reserved\n"
<< _lineInfo );
}
}
@@ -11828,9 +11837,12 @@ namespace Catch {
std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) {
std::vector filtered;
filtered.reserve( testCases.size() );
- for( auto const& testCase : testCases )
- if( matchTest( testCase, testSpec, config ) )
- filtered.push_back( testCase );
+ for (auto const& testCase : testCases) {
+ if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
+ (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
+ filtered.push_back(testCase);
+ }
+ }
return filtered;
}
std::vector const& getAllTestCasesSorted( IConfig const& config ) {
@@ -11906,11 +11918,6 @@ namespace TestCaseTracking {
ITracker::~ITracker() = default;
- TrackerContext& TrackerContext::instance() {
- static TrackerContext s_instance;
- return s_instance;
- }
-
ITracker& TrackerContext::startRun() {
m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
m_currentTracker = nullptr;
@@ -12692,7 +12699,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 7, 1, "", 0 );
+ static Version version( 2, 7, 2, "", 0 );
return version;
}
@@ -14051,22 +14058,6 @@ namespace Catch {
void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
CumulativeReporterBase::testRunStarting( runInfo );
xml.startElement( "testsuites" );
-
- if ( m_config->hasTestFilters() || m_config->rngSeed() != 0 )
- xml.startElement("properties");
-
- if ( m_config->hasTestFilters() ) {
- xml.scopedElement( "property" )
- .writeAttribute( "name" , "filters" )
- .writeAttribute( "value" , serializeFilters( m_config->getTestsOrTags() ) );
- }
-
- if( m_config->rngSeed() != 0 ) {
- xml.scopedElement( "property" )
- .writeAttribute( "name", "random-seed" )
- .writeAttribute( "value", m_config->rngSeed() );
- xml.endElement();
- }
}
void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
@@ -14105,6 +14096,7 @@ namespace Catch {
void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
+
TestGroupStats const& stats = groupNode.value;
xml.writeAttribute( "name", stats.groupInfo.name );
xml.writeAttribute( "errors", unexpectedExceptions );
@@ -14117,6 +14109,21 @@ namespace Catch {
xml.writeAttribute( "time", suiteTime );
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
+ // Write properties if there are any
+ if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
+ auto properties = xml.scopedElement("properties");
+ if (m_config->hasTestFilters()) {
+ xml.scopedElement("property")
+ .writeAttribute("name", "filters")
+ .writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));
+ }
+ if (m_config->rngSeed() != 0) {
+ xml.scopedElement("property")
+ .writeAttribute("name", "random-seed")
+ .writeAttribute("value", m_config->rngSeed());
+ }
+ }
+
// Write test cases
for( auto const& child : groupNode.children )
writeTestCase( *child );