1 /* 2 * Created by Phil on 5/11/2010. 3 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 #ifndef TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED 9 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED 10 11 #include "catch_commandline.hpp" 12 #include "catch_text.h" 13 #include "catch_console_colour.hpp" 14 #include "catch_interfaces_reporter.h" 15 #include "catch_test_spec_parser.hpp" 16 17 #include <limits> 18 #include <algorithm> 19 20 namespace Catch { 21 listTests(Config const & config)22 inline std::size_t listTests( Config const& config ) { 23 24 TestSpec testSpec = config.testSpec(); 25 if( config.testSpec().hasFilters() ) 26 Catch::cout() << "Matching test cases:\n"; 27 else { 28 Catch::cout() << "All available test cases:\n"; 29 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); 30 } 31 32 std::size_t matchedTests = 0; 33 TextAttributes nameAttr, descAttr, tagsAttr; 34 nameAttr.setInitialIndent( 2 ).setIndent( 4 ); 35 descAttr.setIndent( 4 ); 36 tagsAttr.setIndent( 6 ); 37 38 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 39 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); 40 it != itEnd; 41 ++it ) { 42 matchedTests++; 43 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); 44 Colour::Code colour = testCaseInfo.isHidden() 45 ? Colour::SecondaryText 46 : Colour::None; 47 Colour colourGuard( colour ); 48 49 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; 50 if( config.listExtraInfo() ) { 51 Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; 52 std::string description = testCaseInfo.description; 53 if( description.empty() ) 54 description = "(NO DESCRIPTION)"; 55 Catch::cout() << Text( description, descAttr ) << std::endl; 56 } 57 if( !testCaseInfo.tags.empty() ) 58 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; 59 } 60 61 if( !config.testSpec().hasFilters() ) 62 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; 63 else 64 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; 65 return matchedTests; 66 } 67 listTestsNamesOnly(Config const & config)68 inline std::size_t listTestsNamesOnly( Config const& config ) { 69 TestSpec testSpec = config.testSpec(); 70 if( !config.testSpec().hasFilters() ) 71 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); 72 std::size_t matchedTests = 0; 73 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 74 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); 75 it != itEnd; 76 ++it ) { 77 matchedTests++; 78 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); 79 if( startsWith( testCaseInfo.name, '#' ) ) 80 Catch::cout() << '"' << testCaseInfo.name << '"'; 81 else 82 Catch::cout() << testCaseInfo.name; 83 if ( config.listExtraInfo() ) 84 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 85 Catch::cout() << std::endl; 86 } 87 return matchedTests; 88 } 89 90 struct TagInfo { TagInfoCatch::TagInfo91 TagInfo() : count ( 0 ) {} addCatch::TagInfo92 void add( std::string const& spelling ) { 93 ++count; 94 spellings.insert( spelling ); 95 } allCatch::TagInfo96 std::string all() const { 97 std::string out; 98 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end(); 99 it != itEnd; 100 ++it ) 101 out += "[" + *it + "]"; 102 return out; 103 } 104 std::set<std::string> spellings; 105 std::size_t count; 106 }; 107 listTags(Config const & config)108 inline std::size_t listTags( Config const& config ) { 109 TestSpec testSpec = config.testSpec(); 110 if( config.testSpec().hasFilters() ) 111 Catch::cout() << "Tags for matching test cases:\n"; 112 else { 113 Catch::cout() << "All available tags:\n"; 114 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); 115 } 116 117 std::map<std::string, TagInfo> tagCounts; 118 119 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 120 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); 121 it != itEnd; 122 ++it ) { 123 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), 124 tagItEnd = it->getTestCaseInfo().tags.end(); 125 tagIt != tagItEnd; 126 ++tagIt ) { 127 std::string tagName = *tagIt; 128 std::string lcaseTagName = toLower( tagName ); 129 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName ); 130 if( countIt == tagCounts.end() ) 131 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 132 countIt->second.add( tagName ); 133 } 134 } 135 136 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(), 137 countItEnd = tagCounts.end(); 138 countIt != countItEnd; 139 ++countIt ) { 140 std::ostringstream oss; 141 oss << " " << std::setw(2) << countIt->second.count << " "; 142 Text wrapper( countIt->second.all(), TextAttributes() 143 .setInitialIndent( 0 ) 144 .setIndent( oss.str().size() ) 145 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); 146 Catch::cout() << oss.str() << wrapper << '\n'; 147 } 148 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 149 return tagCounts.size(); 150 } 151 listReporters(Config const &)152 inline std::size_t listReporters( Config const& /*config*/ ) { 153 Catch::cout() << "Available reporters:\n"; 154 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 155 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; 156 std::size_t maxNameLen = 0; 157 for(it = itBegin; it != itEnd; ++it ) 158 maxNameLen = (std::max)( maxNameLen, it->first.size() ); 159 160 for(it = itBegin; it != itEnd; ++it ) { 161 Text wrapper( it->second->getDescription(), TextAttributes() 162 .setInitialIndent( 0 ) 163 .setIndent( 7+maxNameLen ) 164 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); 165 Catch::cout() << " " 166 << it->first 167 << ':' 168 << std::string( maxNameLen - it->first.size() + 2, ' ' ) 169 << wrapper << '\n'; 170 } 171 Catch::cout() << std::endl; 172 return factories.size(); 173 } 174 list(Config const & config)175 inline Option<std::size_t> list( Config const& config ) { 176 Option<std::size_t> listedCount; 177 if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) 178 listedCount = listedCount.valueOr(0) + listTests( config ); 179 if( config.listTestNamesOnly() ) 180 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); 181 if( config.listTags() ) 182 listedCount = listedCount.valueOr(0) + listTags( config ); 183 if( config.listReporters() ) 184 listedCount = listedCount.valueOr(0) + listReporters( config ); 185 return listedCount; 186 } 187 188 } // end namespace Catch 189 190 #endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED 191