blob: 4aa704419707d72826ba44990579e318b6e04fb7 [file] [log] [blame]
Phil Nashfd58d482011-01-07 19:57:32 +00001/*
Phil Nashddfe9632012-08-14 19:30:30 +01002 * Created by Phil on 14/08/2012.
3 * Copyright 2012 Two Blue Cubes Ltd. All rights reserved.
Phil Nashfd58d482011-01-07 19:57:32 +00004 *
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)
Phil Nashfd58d482011-01-07 19:57:32 +00007 */
Matt Wozniskif29c8982012-09-17 01:42:29 -04008#ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
9#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nashfd58d482011-01-07 19:57:32 +000010
Phil Nashb1e7d162014-05-16 18:28:58 +010011#include "catch_test_spec.hpp"
Phil Nashddfe9632012-08-14 19:30:30 +010012#include "catch_test_case_info.h"
Phil Nashfd58d482011-01-07 19:57:32 +000013#include "catch_interfaces_testcase.h"
Phil Nash6ba20572013-03-22 19:00:42 +000014#include "catch_common.h"
Phil Nashfd58d482011-01-07 19:57:32 +000015
Martin Hořeňovský9012f952017-02-12 12:17:07 +010016#include <cctype>
17
Phil Nashc67a7ee2012-05-15 23:58:23 +010018namespace Catch {
19
Phil Nash9c1f9a82014-07-03 08:09:57 +010020 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
Martin Hořeňovský3b98a012017-01-15 09:41:33 +010021 if( startsWith( tag, '.' ) ||
Phil Nash9c1f9a82014-07-03 08:09:57 +010022 tag == "hide" ||
23 tag == "!hide" )
24 return TestCaseInfo::IsHidden;
25 else if( tag == "!throws" )
26 return TestCaseInfo::Throws;
27 else if( tag == "!shouldfail" )
28 return TestCaseInfo::ShouldFail;
29 else if( tag == "!mayfail" )
30 return TestCaseInfo::MayFail;
Phil Nash31c23b92017-01-23 17:44:55 +000031 else if( tag == "!nonportable" )
32 return TestCaseInfo::NonPortable;
Phil Nash9c1f9a82014-07-03 08:09:57 +010033 else
34 return TestCaseInfo::None;
Phil Nash20cad7c2014-04-15 18:44:37 +010035 }
36 inline bool isReservedTag( std::string const& tag ) {
Martin Hořeňovskýd0620c32017-01-26 19:11:20 +010037 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
Phil Nash20cad7c2014-04-15 18:44:37 +010038 }
Phil Nash9bf43e72014-05-16 18:52:55 +010039 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
40 if( isReservedTag( tag ) ) {
Martin Hořeňovskýf64d9142017-03-22 17:53:22 +010041 std::ostringstream ss;
42 ss << Colour(Colour::Red)
43 << "Tag name [" << tag << "] not allowed.\n"
44 << "Tag names starting with non alpha-numeric characters are reserved\n"
45 << Colour(Colour::FileName)
46 << _lineInfo << '\n';
47 throw std::runtime_error(ss.str());
Phil Nash9bf43e72014-05-16 18:52:55 +010048 }
49 }
Phil Nash20cad7c2014-04-15 18:44:37 +010050
Phil Nash8baa06c2012-11-25 11:19:55 +000051 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash2a9d8d92013-04-23 18:58:56 +010052 std::string const& _className,
53 std::string const& _name,
54 std::string const& _descOrTags,
55 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +010056 {
Phil Nash337dc252013-11-19 07:21:03 +000057 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
Phil Nash9bf43e72014-05-16 18:52:55 +010058
59 // Parse out tags
Phil Nash8baa06c2012-11-25 11:19:55 +000060 std::set<std::string> tags;
Phil Nash9bf43e72014-05-16 18:52:55 +010061 std::string desc, tag;
62 bool inTag = false;
63 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
64 char c = _descOrTags[i];
65 if( !inTag ) {
66 if( c == '[' )
67 inTag = true;
68 else
69 desc += c;
Phil Nash20cad7c2014-04-15 18:44:37 +010070 }
Phil Nash9bf43e72014-05-16 18:52:55 +010071 else {
72 if( c == ']' ) {
Phil Nash0dd214f2014-12-15 07:25:34 +000073 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
74 if( prop == TestCaseInfo::IsHidden )
Phil Nashee956bc2014-05-19 17:50:58 +010075 isHidden = true;
Phil Nash0dd214f2014-12-15 07:25:34 +000076 else if( prop == TestCaseInfo::None )
77 enforceNotReservedTag( tag, _lineInfo );
78
79 tags.insert( tag );
Phil Nash9bf43e72014-05-16 18:52:55 +010080 tag.clear();
Phil Nash0dd214f2014-12-15 07:25:34 +000081 inTag = false;
Phil Nash9bf43e72014-05-16 18:52:55 +010082 }
83 else
84 tag += c;
85 }
Phil Nash47a5ad32013-12-04 07:58:39 +000086 }
Phil Nashb43d7702014-05-20 18:11:23 +010087 if( isHidden ) {
88 tags.insert( "hide" );
89 tags.insert( "." );
90 }
Phil Nashe9173812015-11-04 18:01:28 +000091
Phil Nash9c1f9a82014-07-03 08:09:57 +010092 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
Phil Nash8baa06c2012-11-25 11:19:55 +000093 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +010094 }
Phil Nashfd58d482011-01-07 19:57:32 +000095
Phil Nash088c5bc2015-07-02 08:20:18 +010096 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
97 {
98 testCaseInfo.tags = tags;
99 testCaseInfo.lcaseTags.clear();
Phil Nashe9173812015-11-04 18:01:28 +0000100
Phil Nash088c5bc2015-07-02 08:20:18 +0100101 std::ostringstream oss;
102 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
Martin Hořeňovskýbcaa2f92017-01-29 23:07:15 +0100103 oss << '[' << *it << ']';
Phil Nash088c5bc2015-07-02 08:20:18 +0100104 std::string lcaseTag = toLower( *it );
105 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
106 testCaseInfo.lcaseTags.insert( lcaseTag );
107 }
108 testCaseInfo.tagsAsString = oss.str();
109 }
Phil Nashe9173812015-11-04 18:01:28 +0000110
Phil Nash2a9d8d92013-04-23 18:58:56 +0100111 TestCaseInfo::TestCaseInfo( std::string const& _name,
112 std::string const& _className,
113 std::string const& _description,
114 std::set<std::string> const& _tags,
Phil Nash2a9d8d92013-04-23 18:58:56 +0100115 SourceLineInfo const& _lineInfo )
Phil Nash8baa06c2012-11-25 11:19:55 +0000116 : name( _name ),
117 className( _className ),
118 description( _description ),
Phil Nashfe981232012-12-05 08:40:53 +0000119 lineInfo( _lineInfo ),
Phil Nash9c1f9a82014-07-03 08:09:57 +0100120 properties( None )
Phil Nash15fd0322013-03-28 22:13:31 +0000121 {
Phil Nash088c5bc2015-07-02 08:20:18 +0100122 setTags( *this, _tags );
Phil Nash15fd0322013-03-28 22:13:31 +0000123 }
Phil Nash9c6ce972012-08-14 08:38:22 +0100124
Phil Nash2a9d8d92013-04-23 18:58:56 +0100125 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nash8baa06c2012-11-25 11:19:55 +0000126 : name( other.name ),
127 className( other.className ),
128 description( other.description ),
129 tags( other.tags ),
Phil Nashfbf3f6f2014-05-20 18:03:54 +0100130 lcaseTags( other.lcaseTags ),
Phil Nash15fd0322013-03-28 22:13:31 +0000131 tagsAsString( other.tagsAsString ),
Phil Nashfe981232012-12-05 08:40:53 +0000132 lineInfo( other.lineInfo ),
Phil Nash9c1f9a82014-07-03 08:09:57 +0100133 properties( other.properties )
Phil Nashddfe9632012-08-14 19:30:30 +0100134 {}
Phil Nashfd58d482011-01-07 19:57:32 +0000135
Phil Nash9c1f9a82014-07-03 08:09:57 +0100136 bool TestCaseInfo::isHidden() const {
137 return ( properties & IsHidden ) != 0;
138 }
139 bool TestCaseInfo::throws() const {
140 return ( properties & Throws ) != 0;
141 }
142 bool TestCaseInfo::okToFail() const {
143 return ( properties & (ShouldFail | MayFail ) ) != 0;
144 }
145 bool TestCaseInfo::expectedToFail() const {
146 return ( properties & (ShouldFail ) ) != 0;
147 }
148
149
Phil Nash2a9d8d92013-04-23 18:58:56 +0100150 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nash8baa06c2012-11-25 11:19:55 +0000151
Phil Nash2a9d8d92013-04-23 18:58:56 +0100152 TestCase::TestCase( TestCase const& other )
Phil Nash8baa06c2012-11-25 11:19:55 +0000153 : TestCaseInfo( other ),
154 test( other.test )
Phil Nashc2675b52012-08-23 08:38:27 +0100155 {}
156
Phil Nash2a9d8d92013-04-23 18:58:56 +0100157 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nash8baa06c2012-11-25 11:19:55 +0000158 TestCase other( *this );
159 other.name = _newName;
160 return other;
Phil Nashddfe9632012-08-14 19:30:30 +0100161 }
Phil Nash684baf12011-01-14 08:47:43 +0000162
Phil Nashfbf3f6f2014-05-20 18:03:54 +0100163 void TestCase::swap( TestCase& other ) {
164 test.swap( other.test );
165 name.swap( other.name );
166 className.swap( other.className );
167 description.swap( other.description );
168 tags.swap( other.tags );
169 lcaseTags.swap( other.lcaseTags );
170 tagsAsString.swap( other.tagsAsString );
Phil Nash9c1f9a82014-07-03 08:09:57 +0100171 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
Phil Nashfbf3f6f2014-05-20 18:03:54 +0100172 std::swap( lineInfo, other.lineInfo );
173 }
174
Phil Nash8baa06c2012-11-25 11:19:55 +0000175 void TestCase::invoke() const {
176 test->invoke();
Phil Nashddfe9632012-08-14 19:30:30 +0100177 }
178
Phil Nash2a9d8d92013-04-23 18:58:56 +0100179 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nash8baa06c2012-11-25 11:19:55 +0000180 return test.get() == other.test.get() &&
181 name == other.name &&
182 className == other.className;
Phil Nashddfe9632012-08-14 19:30:30 +0100183 }
184
Phil Nash2a9d8d92013-04-23 18:58:56 +0100185 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nash8baa06c2012-11-25 11:19:55 +0000186 return name < other.name;
Phil Nashddfe9632012-08-14 19:30:30 +0100187 }
Phil Nash2a9d8d92013-04-23 18:58:56 +0100188 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nash06a671a2012-11-22 19:17:20 +0000189 TestCase temp( other );
Phil Nashc2675b52012-08-23 08:38:27 +0100190 swap( temp );
191 return *this;
192 }
Phil Nash85c0e3d2012-09-21 07:48:03 +0100193
Phil Nash2a9d8d92013-04-23 18:58:56 +0100194 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nash8baa06c2012-11-25 11:19:55 +0000195 {
196 return *this;
197 }
198
Phil Nash85c0e3d2012-09-21 07:48:03 +0100199} // end namespace Catch
Phil Nashfd58d482011-01-07 19:57:32 +0000200
Matt Wozniskif29c8982012-09-17 01:42:29 -0400201#endif // TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED