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 9 #include "catch_list.h" 10 11 #include "catch_interfaces_registry_hub.h" 12 #include "catch_interfaces_reporter.h" 13 #include "catch_interfaces_testcase.h" 14 15 #include "catch_stream.h" 16 #include "catch_text.h" 17 18 #include "catch_console_colour.h" 19 #include "catch_test_spec_parser.h" 20 #include "catch_tostring.h" 21 #include "catch_string_manip.h" 22 23 #include <limits> 24 #include <algorithm> 25 #include <iomanip> 26 27 namespace Catch { 28 listTests(Config const & config)29 std::size_t listTests( Config const& config ) { 30 TestSpec testSpec = config.testSpec(); 31 if( config.hasTestFilters() ) 32 Catch::cout() << "Matching test cases:\n"; 33 else { 34 Catch::cout() << "All available test cases:\n"; 35 } 36 37 auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 38 for( auto const& testCaseInfo : matchedTestCases ) { 39 Colour::Code colour = testCaseInfo.isHidden() 40 ? Colour::SecondaryText 41 : Colour::None; 42 Colour colourGuard( colour ); 43 44 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; 45 if( config.verbosity() >= Verbosity::High ) { 46 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; 47 std::string description = testCaseInfo.description; 48 if( description.empty() ) 49 description = "(NO DESCRIPTION)"; 50 Catch::cout() << Column( description ).indent(4) << std::endl; 51 } 52 if( !testCaseInfo.tags.empty() ) 53 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; 54 } 55 56 if( !config.hasTestFilters() ) 57 Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; 58 else 59 Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; 60 return matchedTestCases.size(); 61 } 62 listTestsNamesOnly(Config const & config)63 std::size_t listTestsNamesOnly( Config const& config ) { 64 TestSpec testSpec = config.testSpec(); 65 std::size_t matchedTests = 0; 66 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 67 for( auto const& testCaseInfo : matchedTestCases ) { 68 matchedTests++; 69 if( startsWith( testCaseInfo.name, '#' ) ) 70 Catch::cout() << '"' << testCaseInfo.name << '"'; 71 else 72 Catch::cout() << testCaseInfo.name; 73 if ( config.verbosity() >= Verbosity::High ) 74 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 75 Catch::cout() << std::endl; 76 } 77 return matchedTests; 78 } 79 add(std::string const & spelling)80 void TagInfo::add( std::string const& spelling ) { 81 ++count; 82 spellings.insert( spelling ); 83 } 84 all() const85 std::string TagInfo::all() const { 86 std::string out; 87 for( auto const& spelling : spellings ) 88 out += "[" + spelling + "]"; 89 return out; 90 } 91 listTags(Config const & config)92 std::size_t listTags( Config const& config ) { 93 TestSpec testSpec = config.testSpec(); 94 if( config.hasTestFilters() ) 95 Catch::cout() << "Tags for matching test cases:\n"; 96 else { 97 Catch::cout() << "All available tags:\n"; 98 } 99 100 std::map<std::string, TagInfo> tagCounts; 101 102 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 103 for( auto const& testCase : matchedTestCases ) { 104 for( auto const& tagName : testCase.getTestCaseInfo().tags ) { 105 std::string lcaseTagName = toLower( tagName ); 106 auto countIt = tagCounts.find( lcaseTagName ); 107 if( countIt == tagCounts.end() ) 108 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 109 countIt->second.add( tagName ); 110 } 111 } 112 113 for( auto const& tagCount : tagCounts ) { 114 ReusableStringStream rss; 115 rss << " " << std::setw(2) << tagCount.second.count << " "; 116 auto str = rss.str(); 117 auto wrapper = Column( tagCount.second.all() ) 118 .initialIndent( 0 ) 119 .indent( str.size() ) 120 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); 121 Catch::cout() << str << wrapper << '\n'; 122 } 123 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 124 return tagCounts.size(); 125 } 126 listReporters(Config const &)127 std::size_t listReporters( Config const& /*config*/ ) { 128 Catch::cout() << "Available reporters:\n"; 129 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 130 std::size_t maxNameLen = 0; 131 for( auto const& factoryKvp : factories ) 132 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); 133 134 for( auto const& factoryKvp : factories ) { 135 Catch::cout() 136 << Column( factoryKvp.first + ":" ) 137 .indent(2) 138 .width( 5+maxNameLen ) 139 + Column( factoryKvp.second->getDescription() ) 140 .initialIndent(0) 141 .indent(2) 142 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) 143 << "\n"; 144 } 145 Catch::cout() << std::endl; 146 return factories.size(); 147 } 148 list(Config const & config)149 Option<std::size_t> list( Config const& config ) { 150 Option<std::size_t> listedCount; 151 if( config.listTests() ) 152 listedCount = listedCount.valueOr(0) + listTests( config ); 153 if( config.listTestNamesOnly() ) 154 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); 155 if( config.listTags() ) 156 listedCount = listedCount.valueOr(0) + listTags( config ); 157 if( config.listReporters() ) 158 listedCount = listedCount.valueOr(0) + listReporters( config ); 159 return listedCount; 160 } 161 162 } // end namespace Catch 163