From 132f23cfff8b63ad240e757335f5bc5d175ece0c Mon Sep 17 00:00:00 2001 From: Malcolm Noyes Date: Mon, 16 Dec 2013 22:17:34 +0000 Subject: [PATCH] Fix order of config override when no override of first test --- include/internal/catch_config.hpp | 247 +++++++++++------- include/internal/catch_vs_test_registry.hpp | 1 - projects/SelfTest/VisualStudioConfigTests.cpp | 107 ++++++++ projects/SelfTest/VisualStudioTests.cpp | 2 + .../ManagedTestCatch/ManagedTestCatch.vcxproj | 1 + .../ManagedTestCatch.vcxproj.filters | 3 + .../ManagedTestCatch/ManagedTestCatch.vcxproj | 1 + .../ManagedTestCatch.vcxproj.filters | 3 + .../NativeTestCatch/NativeTestCatch.vcxproj | 1 + .../NativeTestCatch.vcxproj.filters | 3 + 10 files changed, 279 insertions(+), 90 deletions(-) create mode 100644 projects/SelfTest/VisualStudioConfigTests.cpp diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index e68a8b1a..fd70a12a 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -42,70 +42,122 @@ namespace CatchOverrides { const Catch::Ptr origConfig; }; + enum OverrideType { OverrideUpdate, OverrideReset}; // Note: ordered; update must be before reset + template class Config { - typedef std::map LineData; + typedef std::map, bool> BoolLineData; + typedef std::map FileBoolLineData; + typedef std::map, int> LineData; typedef std::map FileLineData; - typedef std::map StringLineData; + typedef std::multimap, std::string> StringLineData; typedef std::map FileStringLineData; public: bool includeSuccessfulResults(const std::string& file, int c) const { bool result(false); - FileLineData::const_iterator it = showSuccessfulTestsData.find(file); + FileBoolLineData::const_iterator it = showSuccessfulTestsData.find(file); if( it != showSuccessfulTestsData.end() ) { - for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) - { - if( c <= lineIt->first ) - break; - result = lineIt->second ? true : false; + BoolLineData::const_iterator start = it->second.begin(); + BoolLineData::const_iterator end = it->second.end(); + for( BoolLineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideReset ) { + if( c == current.first ) { + result = lineIt->second; + end = lineIt; + break; + } + else + start = lineIt; + } + } + for( BoolLineData::const_iterator lineIt = start; lineIt != end; ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideUpdate ) { + if( c < current.first ) + break; + result = lineIt->second; + } } } return result; } - void insertSuccessfulResults(const std::string& file, int c, bool v) + void insertSuccessfulResults(const std::string& file, OverrideType overRide, int c, bool v) { - FileLineData::iterator it = showSuccessfulTestsData.find(file); + FileBoolLineData::iterator it = showSuccessfulTestsData.find(file); if( it == showSuccessfulTestsData.end() ) { - LineData tmp; - tmp.insert(std::make_pair(c,(v ? 1 : 0))); + BoolLineData tmp; + std::pair current = std::make_pair(c, overRide); + tmp.insert(std::make_pair(current,v)); showSuccessfulTestsData.insert(std::make_pair(file, tmp)); } else { - it->second.insert(std::make_pair(c,(v ? 1 : 0))); + std::pair current = std::make_pair(c, overRide); + BoolLineData::iterator lineIt = it->second.find(current); + if( lineIt == it->second.end() ) { + it->second.insert(std::make_pair(current,v)); + } + else { + lineIt->second = v; + } } } bool warnAboutMissingAssertions(const std::string& file, int c) const { bool result(false); - FileLineData::const_iterator it = missingAssertionData.find(file); + FileBoolLineData::const_iterator it = missingAssertionData.find(file); if( it != missingAssertionData.end() ) { - for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) - { - if( c <= lineIt->first ) - break; - result = lineIt->second ? true : false; + BoolLineData::const_iterator start = it->second.begin(); + BoolLineData::const_iterator end = it->second.end(); + for( BoolLineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideReset ) { + if( c == current.first ) { + result = lineIt->second; + end = lineIt; + break; + } + else + start = lineIt; + } + } + for( BoolLineData::const_iterator lineIt = start; lineIt != end; ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideUpdate ) { + if( c < current.first ) + break; + result = lineIt->second; + } } } return result; } - void insertMissingAssertions(const std::string& file, int c, bool v) + void insertMissingAssertions(const std::string& file, OverrideType overRide, int c, bool v) { - FileLineData::iterator it = missingAssertionData.find(file); + FileBoolLineData::iterator it = missingAssertionData.find(file); if( it == missingAssertionData.end() ) { - LineData tmp; - tmp.insert(std::make_pair(c,(v ? 1 : 0))); + BoolLineData tmp; + std::pair current = std::make_pair(c, overRide); + tmp.insert(std::make_pair(current,v)); missingAssertionData.insert(std::make_pair(file, tmp)); } else { - it->second.insert(std::make_pair(c,(v ? 1 : 0))); + std::pair current = std::make_pair(c, overRide); + BoolLineData::iterator lineIt = it->second.find(current); + if( lineIt == it->second.end() ) { + it->second.insert(std::make_pair(current,v)); + } + else { + lineIt->second = v; + } } } int abortAfter(const std::string& file, int c) const @@ -114,41 +166,71 @@ namespace CatchOverrides { FileLineData::const_iterator it = abortAfterData.find(file); if( it != abortAfterData.end() ) { - for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) - { - if( c <= lineIt->first ) - break; - result = lineIt->second; + LineData::const_iterator start = it->second.begin(); + LineData::const_iterator end = it->second.end(); + for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideReset ) { + if( c == current.first ) { + result = lineIt->second; + end = lineIt; + break; + } + else + start = lineIt; + } + } + for( LineData::const_iterator lineIt = start; lineIt != end; ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideUpdate ) { + if( c < current.first ) + break; + result = lineIt->second; + } } } return result; } - void insertAbortAfter(const std::string& file, int c, int v) - { + void insertAbortAfter(const std::string& file, OverrideType overRide, int c, int v) { FileLineData::iterator it = abortAfterData.find(file); - if( it == abortAfterData.end() ) - { + if( it == abortAfterData.end() ) { LineData tmp; - tmp.insert(std::make_pair(c,v)); + std::pair current = std::make_pair(c, overRide); + tmp.insert(std::make_pair(current,v)); abortAfterData.insert(std::make_pair(file, tmp)); } - else - { - it->second.insert(std::make_pair(c,v)); + else { + std::pair current = std::make_pair(c, overRide); + LineData::iterator lineIt = it->second.find(current); + if( lineIt == it->second.end() ) { + it->second.insert(std::make_pair(current,v)); + } + else { + lineIt->second = v; + } } } - std::vector listOfTests(const std::string& file, int c) const - { + std::vector listOfTests(const std::string& file, int c) const { std::vector result; FileStringLineData::const_iterator it = testData.find(file); - if( it != testData.end() ) - { - for( StringLineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) - { - if( lineIt->second.empty() && c > lineIt->first) - result.clear(); - else { - if( c <= lineIt->first ) + if( it != testData.end() ) { + StringLineData::const_iterator start = it->second.begin(); + StringLineData::const_iterator end = it->second.end(); + for( StringLineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideReset ) { + if( c == current.first ) { + end = lineIt; + break; + } + else + start = lineIt; + } + } + for( StringLineData::const_iterator lineIt = start; lineIt != end; ++lineIt ) { + const std::pair& current = lineIt->first; + if( current.second == OverrideUpdate ) { + if( c < current.first ) break; result.push_back(lineIt->second); } @@ -156,31 +238,28 @@ namespace CatchOverrides { } return result; } - void insertTest(const std::string& file, int c, const std::string& v) - { + void insertTest(const std::string& file, OverrideType overRide, int c, const std::string& v) { FileStringLineData::iterator it = testData.find(file); - if( it == testData.end() ) - { + if( it == testData.end() ) { StringLineData tmp; - tmp.insert(std::make_pair(c,v)); + std::pair current = std::make_pair(c, overRide); + tmp.insert(std::make_pair(current,v)); testData.insert(std::make_pair(file, tmp)); } - else - { - it->second.insert(std::make_pair(c,v)); + else { + std::pair current = std::make_pair(c, overRide); + it->second.insert(std::make_pair(current,v)); } } - static Config& instance() - { - if( !s_instance ) - { + static Config& instance() { + if( !s_instance ) { s_instance = new Config(); } return *s_instance; } private: - FileLineData showSuccessfulTestsData; - FileLineData missingAssertionData; + FileBoolLineData showSuccessfulTestsData; + FileBoolLineData missingAssertionData; FileLineData abortAfterData; FileStringLineData testData; @@ -190,54 +269,44 @@ namespace CatchOverrides { Config* Config::s_instance = NULL; template - struct ConfigReset - { - ConfigReset( const std::string& file, int c, int defaultAbortAfter ) - { - Config::instance().insertSuccessfulResults(file, c, false); - Config::instance().insertMissingAssertions(file, c, false); - Config::instance().insertAbortAfter(file, c, defaultAbortAfter); - Config::instance().insertTest(file, c, ""); + struct ConfigReset { + ConfigReset( const std::string& file, int c, int defaultAbortAfter ) { + Config::instance().insertSuccessfulResults(file, OverrideReset, c, false); + Config::instance().insertMissingAssertions(file, OverrideReset, c, false); + Config::instance().insertAbortAfter(file, OverrideReset, c, defaultAbortAfter); + Config::instance().insertTest(file, OverrideReset, c, ""); } }; template - struct ConfigShowSuccessfulTests - { + struct ConfigShowSuccessfulTests { template - ConfigShowSuccessfulTests( const std::string& file, int c, U v ) - { - Config::instance().insertSuccessfulResults(file, c, v ? true : false); + ConfigShowSuccessfulTests( const std::string& file, int c, U v ) { + Config::instance().insertSuccessfulResults(file, OverrideUpdate, c, v ? true : false); } }; template - struct ConfigWarnMissingAssertions - { + struct ConfigWarnMissingAssertions { template - ConfigWarnMissingAssertions( const std::string& file, int c, U v ) - { - Config::instance().insertMissingAssertions(file, c, v ? true : false); + ConfigWarnMissingAssertions( const std::string& file, int c, U v ) { + Config::instance().insertMissingAssertions(file, OverrideUpdate, c, v ? true : false); } }; template - struct ConfigAbortAfter - { + struct ConfigAbortAfter { template - ConfigAbortAfter( const std::string& file, int c, U v ) - { - Config::instance().insertAbortAfter(file, c, v); + ConfigAbortAfter( const std::string& file, int c, U v ) { + Config::instance().insertAbortAfter(file, OverrideUpdate, c, v); } }; template - struct ConfigAddTest - { + struct ConfigAddTest { template - ConfigAddTest( const std::string& file, int c, U v ) - { - Config::instance().insertTest(file, c, v); + ConfigAddTest( const std::string& file, int c, U v ) { + Config::instance().insertTest(file, OverrideUpdate, c, v); } }; } diff --git a/include/internal/catch_vs_test_registry.hpp b/include/internal/catch_vs_test_registry.hpp index e3b2de67..0636aefb 100644 --- a/include/internal/catch_vs_test_registry.hpp +++ b/include/internal/catch_vs_test_registry.hpp @@ -278,7 +278,6 @@ private: { CatchOverrides::ConfigGuard cg; \ Catch::ConfigData cd(cg.value().get()); \ cd.name = name_desc.name; \ - cd.abortAfter = 1; \ cd.showSuccessfulTests = CatchOverrides::Config::instance().includeSuccessfulResults(__FILE__, Count ); \ cd.warnings = (CatchOverrides::Config::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \ cd.abortAfter = CatchOverrides::Config::instance().abortAfter(__FILE__, Count ); \ diff --git a/projects/SelfTest/VisualStudioConfigTests.cpp b/projects/SelfTest/VisualStudioConfigTests.cpp new file mode 100644 index 00000000..6a771164 --- /dev/null +++ b/projects/SelfTest/VisualStudioConfigTests.cpp @@ -0,0 +1,107 @@ +/* + * Created by Phil on 22/10/2010. + * Copyright 2010 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE) + +namespace VisualStudioConfigTests +{ + struct Z1 {}; + TEST_CASE("VSRequire 1, initial config defaults are set", "[vs]") + { + CatchOverrides::ConfigReset guard("VisualStudioConfigTests.cpp",0, 1); + REQUIRE(!CatchOverrides::Config::instance().includeSuccessfulResults("VisualStudioConfigTests.cpp",0)); + REQUIRE(!CatchOverrides::Config::instance().warnAboutMissingAssertions("VisualStudioConfigTests.cpp",0)); + REQUIRE(CatchOverrides::Config::instance().abortAfter("VisualStudioConfigTests.cpp",0) == 1); + std::vector tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",0); + REQUIRE(tests.empty()); + } + + struct Z2 {}; + TEST_CASE("VSRequire 2, initial config defaults are overridden", "[vs]") + { + CatchOverrides::ConfigShowSuccessfulTests isr1("VisualStudioConfigTests.cpp",0, true); + CatchOverrides::ConfigWarnMissingAssertions wma1("VisualStudioConfigTests.cpp",0, true); + CatchOverrides::ConfigAbortAfter aa1("VisualStudioConfigTests.cpp",0, 42); + CatchOverrides::ConfigAddTest at1("VisualStudioConfigTests.cpp",0,"T1"); + CatchOverrides::ConfigReset guard("VisualStudioConfigTests.cpp",0, 1); + REQUIRE(CatchOverrides::Config::instance().includeSuccessfulResults("VisualStudioConfigTests.cpp",0)); + REQUIRE(CatchOverrides::Config::instance().warnAboutMissingAssertions("VisualStudioConfigTests.cpp",0)); + REQUIRE(CatchOverrides::Config::instance().abortAfter("VisualStudioConfigTests.cpp",0) == 42); + std::vector tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",0); + REQUIRE(tests.size() == 1); + REQUIRE(tests[0] == "T1"); + } + + struct Z3 {}; + TEST_CASE("VSRequire 3, initial config defaults are reset", "[vs]") + { + CatchOverrides::ConfigShowSuccessfulTests isr1("VisualStudioConfigTests.cpp",0, true); + CatchOverrides::ConfigWarnMissingAssertions wma1("VisualStudioConfigTests.cpp",0, true); + CatchOverrides::ConfigAbortAfter aa1("VisualStudioConfigTests.cpp",0, 42); + CatchOverrides::ConfigAddTest at1("VisualStudioConfigTests.cpp",0,"T1"); + CatchOverrides::ConfigReset guard0("VisualStudioConfigTests.cpp",0, 1); + CatchOverrides::ConfigReset guard1("VisualStudioConfigTests.cpp",1, 1); + REQUIRE(CatchOverrides::Config::instance().includeSuccessfulResults("VisualStudioConfigTests.cpp",0)); + REQUIRE(CatchOverrides::Config::instance().warnAboutMissingAssertions("VisualStudioConfigTests.cpp",0)); + REQUIRE(CatchOverrides::Config::instance().abortAfter("VisualStudioConfigTests.cpp",0) == 42); + std::vector tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",0); + REQUIRE(tests.size() == 1); + REQUIRE(tests[0] == "T1"); + + REQUIRE(!CatchOverrides::Config::instance().includeSuccessfulResults("VisualStudioConfigTests.cpp",1)); + REQUIRE(!CatchOverrides::Config::instance().warnAboutMissingAssertions("VisualStudioConfigTests.cpp",1)); + REQUIRE(CatchOverrides::Config::instance().abortAfter("VisualStudioConfigTests.cpp",1) == 1); + tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",1); + REQUIRE(tests.empty()); + } + + struct Z7 {}; + TEST_CASE("VSRequire 7, initial multi-line list config gets all values", "[vs]") + { + CatchOverrides::ConfigAddTest a1("VisualStudioConfigTests.cpp",0,"T1"); + CatchOverrides::ConfigAddTest a2("VisualStudioConfigTests.cpp",0,"T2"); + CatchOverrides::ConfigAddTest a3("VisualStudioConfigTests.cpp",0,"T3"); + CatchOverrides::ConfigReset guard0("VisualStudioConfigTests.cpp",0, 1); + CatchOverrides::ConfigReset guard1("VisualStudioConfigTests.cpp",1, 1); + + std::vector tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",0); + REQUIRE(tests.size() == 3); + REQUIRE(tests[0] == "T1"); + REQUIRE(tests[1] == "T2"); + REQUIRE(tests[2] == "T3"); + tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",1); + REQUIRE(tests.empty()); + } + + struct Z8 {}; + TEST_CASE("VSRequire 8, initial incrementing 'line' sets values", "[vs]") + { + CatchOverrides::ConfigShowSuccessfulTests isr1("VisualStudioConfigTests.cpp",0, true); + CatchOverrides::ConfigWarnMissingAssertions wma1("VisualStudioConfigTests.cpp",1, true); + CatchOverrides::ConfigAbortAfter aa1("VisualStudioConfigTests.cpp",2, 42); + CatchOverrides::ConfigAddTest at1("VisualStudioConfigTests.cpp",3,"T1"); + CatchOverrides::ConfigReset guard0("VisualStudioConfigTests.cpp",4, 1); + CatchOverrides::ConfigReset guard1("VisualStudioConfigTests.cpp",5, 1); + REQUIRE(CatchOverrides::Config::instance().includeSuccessfulResults("VisualStudioConfigTests.cpp",4)); + REQUIRE(CatchOverrides::Config::instance().warnAboutMissingAssertions("VisualStudioConfigTests.cpp",4)); + REQUIRE(CatchOverrides::Config::instance().abortAfter("VisualStudioConfigTests.cpp",4) == 42); + std::vector tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",4); + REQUIRE(tests.size() == 1); + REQUIRE(tests[0] == "T1"); + + REQUIRE(!CatchOverrides::Config::instance().includeSuccessfulResults("VisualStudioConfigTests.cpp",5)); + REQUIRE(!CatchOverrides::Config::instance().warnAboutMissingAssertions("VisualStudioConfigTests.cpp",5)); + REQUIRE(CatchOverrides::Config::instance().abortAfter("VisualStudioConfigTests.cpp",5) == 1); + tests = CatchOverrides::Config::instance().listOfTests("VisualStudioConfigTests.cpp",5); + REQUIRE(tests.empty()); + } + +} +#endif diff --git a/projects/SelfTest/VisualStudioTests.cpp b/projects/SelfTest/VisualStudioTests.cpp index e55db859..063fb704 100644 --- a/projects/SelfTest/VisualStudioTests.cpp +++ b/projects/SelfTest/VisualStudioTests.cpp @@ -28,6 +28,8 @@ namespace VisualStudioTests { bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults(); REQUIRE(!show); + int abortAfter = Catch::getCurrentContext().getConfig()->abortAfter(); + REQUIRE(abortAfter == 1); } CATCH_CONFIG_SHOW_SUCCESS(true) diff --git a/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj b/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj index 1dd4095e..4920fd09 100644 --- a/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj +++ b/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj @@ -151,6 +151,7 @@ + diff --git a/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj.filters b/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj.filters index e81eb51c..6c23ab87 100644 --- a/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj.filters +++ b/projects/VS2010/ManagedTestCatch/ManagedTestCatch.vcxproj.filters @@ -72,6 +72,9 @@ Source Files + + Source Files + diff --git a/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj b/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj index d8e9a677..f2274418 100644 --- a/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj +++ b/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj @@ -170,6 +170,7 @@ + diff --git a/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj.filters b/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj.filters index 2db549a5..6c7a2dfd 100644 --- a/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj.filters +++ b/projects/VS2012/ManagedTestCatch/ManagedTestCatch.vcxproj.filters @@ -72,6 +72,9 @@ Source Files + + Source Files + diff --git a/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj b/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj index afc168fa..e09b3c23 100644 --- a/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj +++ b/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj @@ -166,6 +166,7 @@ + Create diff --git a/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj.filters b/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj.filters index 1b5c5e7e..2b8c76a0 100644 --- a/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj.filters +++ b/projects/VS2012/NativeTestCatch/NativeTestCatch.vcxproj.filters @@ -77,5 +77,8 @@ Source Files + + Source Files + \ No newline at end of file