mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-22 11:23:29 +01:00
Merged from develop
This commit is contained in:
commit
d9fbc62093
@ -1,11 +1,13 @@
|
||||
![catch logo](catch-logo-small.png)
|
||||
|
||||
*v1.0 build 53 (master branch)*
|
||||
*v1.1 build 14 (develop branch)*
|
||||
|
||||
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch)
|
||||
|
||||
[Please see this page if you are updating from a version before 1.0](docs/whats-changed.md)
|
||||
|
||||
<a href="https://raw.githubusercontent.com/philsquared/Catch/develop/single_include/catch.hpp">[The latest, single header, version can be downloaded directly using this link]</a>
|
||||
|
||||
## What's the Catch?
|
||||
|
||||
Catch stands for C++ Automated Test Cases in Headers and is a multi-paradigm automated test framework for C++ and Objective-C (and, maybe, C). It is implemented entirely in a set of header files, but is packaged up as a single header for extra convenience.
|
||||
|
@ -9,6 +9,8 @@ Before looking at this material be sure to read the [tutorial](tutorial.md)
|
||||
* [Command line](command-line.md)
|
||||
* [Build systems](build-systems.md)
|
||||
* [Supplying your own main()](own-main.md)
|
||||
* [Configuration](configuration.md)
|
||||
* [String Conversions](tostring.md)
|
||||
* [Why are my tests slow to compile?](slow-compiles.md)
|
||||
|
||||
Other
|
||||
@ -16,8 +18,3 @@ Other
|
||||
* [Why Catch?](why-catch.md)
|
||||
* [What's changed](whats-changed.md)
|
||||
* [Contributing](contributing.md)
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
|
||||
|
@ -17,12 +17,12 @@ The ```CHECK``` family are equivalent but execution continues in the same test c
|
||||
Evaluates the expression and records the result. If an exception is thrown it is caught, reported, and counted as a failure. These are the macros you will use most of the time
|
||||
|
||||
Examples:
|
||||
|
||||
```c++
|
||||
```
|
||||
CHECK( str == "string value" );
|
||||
CHECK( thisReturnsTrue() );
|
||||
REQUIRE( i == 42 );
|
||||
```
|
||||
|
||||
* **REQUIRE_FALSE(** _expression_ **)** and
|
||||
* **CHECK_FALSE(** _expression_ **)**
|
||||
|
||||
@ -30,10 +30,28 @@ Evaluates the expression and records the _logical NOT_ of the result. If an exce
|
||||
(these forms exist as a workaround for the fact that ! prefixed expressions cannot be decomposed).
|
||||
|
||||
Example:
|
||||
```c++
|
||||
```
|
||||
REQUIRE_FALSE( thisReturnsFalse() );
|
||||
```
|
||||
|
||||
### Floating point comparisons
|
||||
|
||||
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
|
||||
|
||||
Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called ```Approx```. ```Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
|
||||
|
||||
```
|
||||
REQUIRE( performComputation() == Approx( 2.1 ) );
|
||||
```
|
||||
|
||||
By default a small epsilon value is used that covers many simple cases of rounding errors. When this is insufficent the epsilon value (the amount within which a difference either way is ignored) can be specified by calling the ```epsilon()``` method on the ```Approx``` instance. e.g.:
|
||||
|
||||
```
|
||||
REQUIRE( 22/7 == Approx( 3.141 ).epsilon( 0.01 ) );
|
||||
```
|
||||
|
||||
When dealing with very large or very small numbers it can be useful to specify a scale, which can be achieved by calling the ```scale()``` method on the ```Approx``` instance.
|
||||
|
||||
## Exceptions
|
||||
|
||||
* **REQUIRE_THROWS(** _expression_ **)** and
|
||||
@ -61,4 +79,4 @@ To support Matchers a slightly different form is used. Matchers will be more ful
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -1,5 +1,50 @@
|
||||
# Integration with build systems
|
||||
|
||||
Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
|
||||
|
||||
# Continuous Integration systems
|
||||
|
||||
Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (as has been done with TeamCity).
|
||||
|
||||
Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them.
|
||||
|
||||
## XML Reporter
|
||||
```-r xml```
|
||||
|
||||
The XML Reporter writes in an XML format that is specific to Catch.
|
||||
|
||||
The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
|
||||
|
||||
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course.
|
||||
|
||||
## JUnit Reporter
|
||||
```-r junit```
|
||||
|
||||
The JUnit Reporter writes in an XML format that mimics the JUnit ANT schema.
|
||||
|
||||
The advantage of this format is that the JUnit Ant schema is widely understood by most build servers and so can usually be consumed with no additional work.
|
||||
|
||||
The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
|
||||
|
||||
## TeamCity Reporter
|
||||
```-r teamcity```
|
||||
|
||||
The TeamCity Reporter writes TeamCity service messages to stdout. In order to be able to use this reporter an additional header must also be included.
|
||||
|
||||
```catch_reporter_teamcity.hpp``` can be found in the ```include\reporters``` directory. It should be included in the same file that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. The ```#include``` should be placed after ```#include```ing Catch itself.
|
||||
|
||||
e.g.:
|
||||
|
||||
```
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "catch_reporter_teamcity.hpp"
|
||||
```
|
||||
|
||||
Being specific to TeamCity this is the best reporter to use with it - but it is completely unsuitable for any other purpose. It is a streaming format (it writes as it goes) - although test results don't appear in the TeamCity interface until the completion of a suite (usually the whole test run).
|
||||
|
||||
# Low-level tools
|
||||
|
||||
## CMake
|
||||
|
||||
You can use the following CMake script to automatically fetch Catch from github and configure it as an external project:
|
||||
@ -35,3 +80,7 @@ add_subdirectory(${EXT_PROJECTS_DIR}/catch)
|
||||
include_directories(${CATCH_INCLUDE_DIR} ${COMMON_INCLUDES})
|
||||
enable_testing(true) # Enables unit-testing.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
@ -1,18 +1,33 @@
|
||||
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
|
||||
Note that options are described according to the following pattern:
|
||||
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
|
||||
|
||||
<a href="#specifying-which-tests-to-run"> ` <test-spec> ...`</a><br />
|
||||
<a href="#choosing-a-reporter-to-use"> ` -r, --reporter`</a><br />
|
||||
<a href="#breaking-into-the-debugger"> ` -b, --break`</a><br />
|
||||
<a href="#usage"> ` -h, -?, --help`</a><br />
|
||||
<a href="#listing-available-tests-tags-or-reporters"> ` -l, --list-tests`</a><br />
|
||||
<a href="#listing-available-tests-tags-or-reporters"> ` -t, --list-tags`</a><br />
|
||||
<a href="#showing-results-for-successful-tests"> ` -s, --success`</a><br />
|
||||
<a href="#aborting-after-a-certain-number-of-failures"> ` -a, --abort`</a><br />
|
||||
<a href="#listing-available-tests-tags-or-reporters"> ` -l, --list`</a><br />
|
||||
<a href="#sending-output-to-a-file"> ` -o, --out`</a><br />
|
||||
<a href="#naming-a-test-run"> ` -n, --name`</a><br />
|
||||
<a href="#breaking-into-the-debugger"> ` -b, --break`</a><br />
|
||||
<a href="#eliding-assertions-expected-to-throw"> ` -e, --nothrow`</a><br />
|
||||
<a href="#invisibles"> ` -i, --invisibles`</a><br />
|
||||
<a href="#sending-output-to-a-file"> ` -o, --out`</a><br />
|
||||
<a href="#choosing-a-reporter-to-use"> ` -r, --reporter`</a><br />
|
||||
<a href="#naming-a-test-run"> ` -n, --name`</a><br />
|
||||
<a href="#aborting-after-a-certain-number-of-failures"> ` -a, --abort`</a><br />
|
||||
<a href="#aborting-after-a-certain-number-of-failures"> ` -x, --abortx`</a><br />
|
||||
<a href="#warnings"> ` -w, --warn`</a><br />
|
||||
<a href="#reporting-timings"> ` -d, --durations`</a><br />
|
||||
<a href="#usage"> ` -h, -?, --help`</a><br />
|
||||
<a href="#input-file"> ` -f, --input-file`</a><br />
|
||||
|
||||
</br>
|
||||
|
||||
<a href="#list-test-names-only"> ` --list-test-names-only`</a><br />
|
||||
<a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br />
|
||||
<a href="#order"> ` --order`</a><br />
|
||||
<a href="#rng-seed"> ` --rng-seed`</a><br />
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
<a id="specifying-which-tests-to-run"></a>
|
||||
## Specifying which tests to run
|
||||
@ -21,7 +36,8 @@ Note that options are described according to the following pattern:
|
||||
|
||||
Test cases, wildcarded test cases, tags and tag expressions are all passed directly as arguments. Tags are distinguished by being enclosed in square brackets.
|
||||
|
||||
If no test specs are supplied then all test cases, except "hidden" tests (tagged ```[hide]```, ```[.]``` or, in the legacy case, prefixed by `'./'`) are run.
|
||||
If no test specs are supplied then all test cases, except "hidden" tests, are run.
|
||||
A test is hidden by giving it any tag starting with (or just) a period (```.```) - or, in the deprecated case, tagged ```[hide]``` or given name starting with `'./'`. To specify hidden tests from the command line ```[.]``` or ```[hide]``` can be used *regardless of how they were declared*.
|
||||
|
||||
Specs must be enclosed in quotes if they contain spaces. If they do not contain spaces the quotes are optional.
|
||||
|
||||
@ -79,7 +95,7 @@ In addition to the command line option, ensure you have built your code with the
|
||||
<pre>-s, --success</pre>
|
||||
|
||||
Usually you only want to see reporting for failed tests. Sometimes it's useful to see *all* the output (especially when you don't trust that that test you just added worked first time!).
|
||||
To see successul, as well as failing, test results just pass this option. Note that each reporter may treat this option differently. The Junit reporter, for example, logs all results regardless.
|
||||
To see successful, as well as failing, test results just pass this option. Note that each reporter may treat this option differently. The Junit reporter, for example, logs all results regardless.
|
||||
|
||||
<a id="aborting-after-a-certain-number-of-failures"></a>
|
||||
## Aborting after a certain number of failures
|
||||
@ -131,6 +147,13 @@ Sometimes exceptions are expected outside of one of the assertions that tests fo
|
||||
|
||||
When running with this option any throw checking assertions are skipped so as not to contribute additional noise. Be careful if this affects the behaviour of subsequent tests.
|
||||
|
||||
<a id="invisibles"></a>
|
||||
## Make whitespace visible
|
||||
<pre>-i, --invisibles</pre>
|
||||
|
||||
If a string comparison fails due to differences in whitespace - especially leading or trailing whitespace - it can be hard to see what's going on.
|
||||
This option transforms tabs and newline characters into ```\t``` and ```\n``` respectively when printing.
|
||||
|
||||
<a id="warnings"></a>
|
||||
## Warnings
|
||||
<pre>-w, --warn <warning name></pre>
|
||||
@ -145,6 +168,47 @@ The ony available warning, presently, is ```NoAssertions```. This warning fails
|
||||
|
||||
When set to ```yes``` Catch will report the duration of each test case, in milliseconds. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not.
|
||||
|
||||
<a id="input-file"></a>
|
||||
## Load test names to run from a file
|
||||
<pre>-f, --input-file <filename></pre>
|
||||
|
||||
Provide the name of a file that contains a list of test case names - one per line. Blank lines are skipped and anything after the comment character, ```#```, is ignored.
|
||||
|
||||
A useful way to generate an initial instance of this file is to use the <a href="#list-test-names-only">list-test-names-only</a> option. This can then be manually curated to specify a specific subset of tests - or in a specific order.
|
||||
|
||||
<a id="list-test-names-only"></a>
|
||||
## Just test names
|
||||
<pre>--list-test-names-only</pre>
|
||||
|
||||
This option lists all available tests in a non-indented form, one on each line. This makes it ideal for saving to a file and feeding back into the <a href="#input-file">```-f``` or ```--input-file```</a> option.
|
||||
|
||||
|
||||
<a id="order"></a>
|
||||
## Specify the order test cases are run
|
||||
<pre>--order <decl|lex|rand></pre>
|
||||
|
||||
Test cases are ordered one of three ways:
|
||||
|
||||
|
||||
### decl
|
||||
Declaration order. The order the tests were originally declared in. Note that ordering between files is not guaranteed and is implementation dependent.
|
||||
|
||||
### lex
|
||||
Lexicographically sorted. Tests are sorted, alpha-numerically, by name.
|
||||
|
||||
### rand
|
||||
Randomly sorted. Test names are sorted using ```std::random_shuffle()```. By default the random number generator is seeded with 0 - and so the order is repeatable. To control the random seed see <a href="#rng-seed">rng-seed</a>.
|
||||
|
||||
<a id="rng-seed"></a>
|
||||
## Specify a seed for the Random Number Generator
|
||||
<pre>--rng-seed <'time'|number></pre>
|
||||
|
||||
Sets a seed for the random number generator using ```std::srand()```.
|
||||
If a number is provided this is used directly as the seed so the random pattern is repeatable.
|
||||
Alternatively if the keyword ```time``` is provided then the result of calling ```std::time(0)``` is used and so the pattern becomes unpredictable.
|
||||
|
||||
In either case the actual value for the seed is printed as part of Catch's output so if an issue is discovered that is sensitive to test ordering the ordering can be reproduced - even if it was originally seeded from ```std::time(0)```.
|
||||
|
||||
<a id="usage"></a>
|
||||
## Usage
|
||||
<pre>-h, -?, --help</pre>
|
||||
@ -153,4 +217,4 @@ Prints the command line arguments to stdout
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
66
docs/configuration.md
Normal file
66
docs/configuration.md
Normal file
@ -0,0 +1,66 @@
|
||||
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
||||
|
||||
Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a small set of macros for configuring how it is built.
|
||||
|
||||
# main()/ implementation
|
||||
|
||||
CATCH_CONFIG_MAIN // Designates this as implementation file and defines main()
|
||||
CATCH_CONFIG_RUNNER // Designates this as implementation file
|
||||
|
||||
Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*.
|
||||
|
||||
# Prefixing Catch macros
|
||||
|
||||
CATCH_CONFIG_PREFIX_ALL
|
||||
|
||||
To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```).
|
||||
|
||||
|
||||
# Terminal colour
|
||||
|
||||
CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring
|
||||
CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used
|
||||
CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used
|
||||
|
||||
Yes, I am English, so I will continue to spell "colour" with a 'u'.
|
||||
|
||||
When sending output to the terminal, if it detects that it can, Catch will use colourised text. On Windows the Win32 API, ```SetConsoleTextAttribute```, is used. On POSIX systems ANSI colour escape codes are inserted into the stream.
|
||||
|
||||
For finer control you can define one of the above identifiers (these are mutually exclusive - but that is not checked so may behave unexpectedly if you mix them):
|
||||
|
||||
Note that when ANSI colour codes are used "unistd.h" must be includable - along with a definition of ```isatty()```
|
||||
|
||||
Typically you should place the ```#define``` before #including "catch.hpp" in your main source file - but if you prefer you can define it for your whole project by whatever your IDE or build system provides for you to do so.
|
||||
|
||||
# Console width
|
||||
|
||||
CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number
|
||||
|
||||
Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this.
|
||||
By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value.
|
||||
|
||||
# stdout
|
||||
|
||||
CATCH_CONFIG_NOSTDOUT
|
||||
|
||||
Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them from ```Catch::cout()``` and ```Catch::cerr()``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
|
||||
This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems.
|
||||
|
||||
# C++ conformance toggles
|
||||
|
||||
CATCH_CONFIG_CPP11_NULLPTR
|
||||
CATCH_CONFIG_CPP11_NOEXCEPT
|
||||
CATCH_CONFIG_SFINAE // Basic, C++03, support for SFINAE
|
||||
CATCH_CONFIG_VARIADIC_MACROS // Usually pre-C++11 compiler extensions are sufficient
|
||||
CATCH_CONFIG_NO_VARIADIC_MACROS // Suppress if Catch is too eager to enable it
|
||||
|
||||
Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative.
|
||||
So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support.
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
@ -16,8 +16,8 @@ In addition to the include files and IDE projects there are a number of tests in
|
||||
|
||||
The other directories are ```scripts``` which contains a set of python scripts to help in testing Catch as well as generating the single include, and docs, which contains the documentation as a set of markdown files.
|
||||
|
||||
*This document is a work in progress and will be updated soon with new information.*
|
||||
*this document is in-progress...*
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -49,4 +49,4 @@ These macros are now deprecated and are just aliases for INFO and CAPTURE (which
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -47,9 +47,9 @@ int main( int argc, char* const argv[] )
|
||||
if( returnCode != 0 ) // Indicates a command line error
|
||||
return returnCode;
|
||||
|
||||
// Writing to session.configData() or session.Config() here
|
||||
// overrides command line args.
|
||||
// Only do this if you know you need to.
|
||||
// writing to session.configData() or session.Config() here
|
||||
// overrides command line args
|
||||
// only do this if you know you need to
|
||||
|
||||
return session.run();
|
||||
}
|
||||
@ -65,4 +65,4 @@ Catch embeds a powerful command line parser which you can also use to parse your
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -19,4 +19,4 @@ As a result the main source file *does* compile the whole of Catch every time! S
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -9,7 +9,7 @@ Test cases and sections are very easy to use in practice:
|
||||
* **TEST_CASE(** _test name_ \[, _tags_ \] **)**
|
||||
* **SECTION(** _section name_ **)**
|
||||
|
||||
_test name_ and _section name_ are free-form quoted strings. The optional _tags_ argument is a quoted string containing one or more tags enclosed in square brackets. Tags are discussed below. Test names must be unique within the Catch executable.
|
||||
_test name_ and _section name_ are free form, quoted, strings. The optional _tags_ argument is a quoted string containing one or more tags enclosed in square brackets. Tags are discussed below. Test names must be unique within the Catch executable.
|
||||
|
||||
For examples see the [Tutorial](tutorial.md)
|
||||
|
||||
@ -57,4 +57,4 @@ Other than the additional prefixes and the formatting in the console reporter th
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -1,4 +1,4 @@
|
||||
Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
|
||||
Although Catch allows you to group tests together as sections within a test case, it can still convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
|
||||
|
||||
```c++
|
||||
class UniqueTestsFixture {
|
||||
@ -29,4 +29,4 @@ The two test cases here will create uniquely-named derived classes of UniqueTest
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
46
docs/tostring.md
Normal file
46
docs/tostring.md
Normal file
@ -0,0 +1,46 @@
|
||||
# String conversions
|
||||
|
||||
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
|
||||
Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
|
||||
|
||||
## operator << overload for std::ostream
|
||||
|
||||
This is the standard way of providing string conversions in C++ - and the chances are you may already provide this for your own purposes. If you're not familiar with this idiom it involves writing a free function of the form:
|
||||
|
||||
```
|
||||
std::ostream& operator << ( std::ostream& os, T const& value ) {
|
||||
os << convertMyTypeToString( value );
|
||||
return os;
|
||||
}
|
||||
```
|
||||
|
||||
(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
|
||||
|
||||
You should put this function in the same namespace as your type.
|
||||
|
||||
Alternatively you may prefer to write it as a member function:
|
||||
|
||||
```
|
||||
std::ostream& T::operator << ( std::ostream& os ) const {
|
||||
os << convertMyTypeToString( *this );
|
||||
return os;
|
||||
}
|
||||
```
|
||||
|
||||
## Catch::toString overload
|
||||
|
||||
If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide an overload for ```Catch::toString()``` for your type.
|
||||
|
||||
```
|
||||
namespace Catch {
|
||||
std::string toString( T const& value ) {
|
||||
return convertMyTypeToString( value );
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace.
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
@ -86,10 +86,10 @@ Of course there are still more issues to do deal with. For example we'll hit pro
|
||||
|
||||
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on.
|
||||
|
||||
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md).
|
||||
2. We introduce test cases with the TEST_CASE macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, below. The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests.
|
||||
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md)).
|
||||
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, below. The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests.
|
||||
3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names.
|
||||
4. We write our individual test assertions using the REQUIRE macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced.
|
||||
4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced.
|
||||
|
||||
<a id="test-cases-and-sections"></a>
|
||||
## Test cases and sections
|
||||
@ -157,7 +157,7 @@ The power of sections really shows, however, when we need to execute a sequence
|
||||
}
|
||||
```
|
||||
|
||||
Sections can be nested to an arbitrary depth (limited only by your stack size). Each leaf section (i.e. a section that contains no nested sections) will be executed exactly once, on a separate path of execution from any other leaf section (so no leaf section can interfere with another). Obviously a failure in a parent section will prevent nested sections from running - but that's the idea.
|
||||
Sections can be nested to an arbitrary depth (limited only by your stack size). Each leaf section (i.e. a section that contains no nested sections) will be executed exactly once, on a separate path of execution from any other leaf section (so no leaf section can interfere with another). A failure in a parent section will prevent nested sections from running - but then that's the idea.
|
||||
|
||||
## BDD-Style
|
||||
|
||||
@ -220,9 +220,11 @@ Scenario: vectors can be sized and resized
|
||||
```
|
||||
|
||||
## Next steps
|
||||
For more specific information see the [Reference pages](Readme.md)
|
||||
|
||||
This has been a brief introduction to get you up and running with Catch, and to point out some of the key differences between Catch and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests.
|
||||
|
||||
Of course there is more to learn - most of which you should be able to page-fault in as you go. Please see the every-growing [Reference section](Readme.md) for what's available.
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
||||
|
@ -21,4 +21,4 @@ If you find any issues please raise issue tickets on the [issue tracker on GitHu
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -39,4 +39,4 @@ See the [tutorial](tutorial.md) to get more of a taste of using CATCH in practic
|
||||
|
||||
---
|
||||
|
||||
[Home](../README.md)
|
||||
[Home](Readme.md)
|
@ -11,11 +11,11 @@
|
||||
|
||||
#include "internal/catch_suppress_warnings.h"
|
||||
|
||||
#ifdef CATCH_CONFIG_MAIN
|
||||
# define CATCH_CONFIG_RUNNER
|
||||
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
|
||||
# define CATCH_IMPL
|
||||
#endif
|
||||
|
||||
#ifdef CATCH_CONFIG_RUNNER
|
||||
#ifdef CATCH_IMPL
|
||||
# ifndef CLARA_CONFIG_MAIN
|
||||
# define CLARA_CONFIG_MAIN_NOT_DEFINED
|
||||
# define CLARA_CONFIG_MAIN
|
||||
@ -43,7 +43,7 @@
|
||||
#include "internal/catch_objc.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef CATCH_CONFIG_RUNNER
|
||||
#ifdef CATCH_IMPL
|
||||
#include "internal/catch_impl.hpp"
|
||||
#endif
|
||||
|
||||
|
@ -60,6 +60,14 @@ namespace Catch {
|
||||
m_testsAlreadyRun.insert( *it );
|
||||
}
|
||||
}
|
||||
std::vector<TestCase> skippedTestCases;
|
||||
getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true );
|
||||
|
||||
for( std::vector<TestCase>::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end();
|
||||
it != itEnd;
|
||||
++it )
|
||||
m_reporter->skipTest( *it );
|
||||
|
||||
context.testGroupEnded( "all tests", totals, 1, 1 );
|
||||
return totals;
|
||||
}
|
||||
@ -97,7 +105,7 @@ namespace Catch {
|
||||
std::set<TestCase> m_testsAlreadyRun;
|
||||
};
|
||||
|
||||
class Session {
|
||||
class Session : NonCopyable {
|
||||
static bool alreadyInstantiated;
|
||||
|
||||
public:
|
||||
@ -108,7 +116,7 @@ namespace Catch {
|
||||
: m_cli( makeCommandLineParser() ) {
|
||||
if( alreadyInstantiated ) {
|
||||
std::string msg = "Only one instance of Catch::Session can ever be used";
|
||||
std::cerr << msg << std::endl;
|
||||
Catch::cerr() << msg << std::endl;
|
||||
throw std::logic_error( msg );
|
||||
}
|
||||
alreadyInstantiated = true;
|
||||
@ -118,15 +126,15 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void showHelp( std::string const& processName ) {
|
||||
std::cout << "\nCatch v" << libraryVersion.majorVersion << "."
|
||||
Catch::cout() << "\nCatch v" << libraryVersion.majorVersion << "."
|
||||
<< libraryVersion.minorVersion << " build "
|
||||
<< libraryVersion.buildNumber;
|
||||
if( libraryVersion.branchName != std::string( "master" ) )
|
||||
std::cout << " (" << libraryVersion.branchName << " branch)";
|
||||
std::cout << "\n";
|
||||
Catch::cout() << " (" << libraryVersion.branchName << " branch)";
|
||||
Catch::cout() << "\n";
|
||||
|
||||
m_cli.usage( std::cout, processName );
|
||||
std::cout << "For more detail usage please see the project docs\n" << std::endl;
|
||||
m_cli.usage( Catch::cout(), processName );
|
||||
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
|
||||
}
|
||||
|
||||
int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
|
||||
@ -140,11 +148,11 @@ namespace Catch {
|
||||
catch( std::exception& ex ) {
|
||||
{
|
||||
Colour colourGuard( Colour::Red );
|
||||
std::cerr << "\nError(s) in input:\n"
|
||||
Catch::cerr() << "\nError(s) in input:\n"
|
||||
<< Text( ex.what(), TextAttributes().setIndent(2) )
|
||||
<< "\n\n";
|
||||
}
|
||||
m_cli.usage( std::cout, m_configData.processName );
|
||||
m_cli.usage( Catch::cout(), m_configData.processName );
|
||||
return (std::numeric_limits<int>::max)();
|
||||
}
|
||||
return 0;
|
||||
@ -170,6 +178,9 @@ namespace Catch {
|
||||
try
|
||||
{
|
||||
config(); // Force config to be constructed
|
||||
|
||||
std::srand( m_configData.rngSeed );
|
||||
|
||||
Runner runner( m_config );
|
||||
|
||||
// Handle list request
|
||||
@ -179,7 +190,7 @@ namespace Catch {
|
||||
return static_cast<int>( runner.runTests().assertions.failed );
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
std::cerr << ex.what() << std::endl;
|
||||
Catch::cerr() << ex.what() << std::endl;
|
||||
return (std::numeric_limits<int>::max)();
|
||||
}
|
||||
}
|
||||
|
6
include/external/clara.h
vendored
6
include/external/clara.h
vendored
@ -620,7 +620,7 @@ namespace Clara {
|
||||
m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
|
||||
{
|
||||
if( other.m_floatingArg.get() )
|
||||
m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );
|
||||
m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
|
||||
}
|
||||
|
||||
CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
|
||||
@ -649,7 +649,7 @@ namespace Clara {
|
||||
ArgBuilder operator[]( UnpositionalTag ) {
|
||||
if( m_floatingArg.get() )
|
||||
throw std::logic_error( "Only one unpositional argument can be added" );
|
||||
m_floatingArg = ArgAutoPtr( new Arg() );
|
||||
m_floatingArg.reset( new Arg() );
|
||||
ArgBuilder builder( m_floatingArg.get() );
|
||||
return builder;
|
||||
}
|
||||
@ -791,7 +791,7 @@ namespace Clara {
|
||||
if( it == itEnd ) {
|
||||
if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
|
||||
unusedTokens.push_back( token );
|
||||
else if( m_throwOnUnrecognisedTokens )
|
||||
else if( errors.empty() && m_throwOnUnrecognisedTokens )
|
||||
errors.push_back( "unrecognised option: " + token.data );
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "catch_common.h"
|
||||
#include "catch_tostring.h"
|
||||
#include "catch_interfaces_runner.h"
|
||||
#include "internal/catch_compiler_capabilities.h"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -134,7 +134,7 @@
|
||||
std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
|
||||
__catchResult \
|
||||
.setLhs( Catch::toString( arg ) ) \
|
||||
.setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \
|
||||
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
|
||||
.setOp( "matches" ) \
|
||||
.setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
|
||||
__catchResult.captureExpression(); \
|
||||
|
@ -29,7 +29,28 @@ namespace Catch {
|
||||
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
|
||||
else
|
||||
throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
|
||||
|
||||
}
|
||||
inline void setOrder( ConfigData& config, std::string const& order ) {
|
||||
if( startsWith( "declared", order ) )
|
||||
config.runOrder = RunTests::InDeclarationOrder;
|
||||
else if( startsWith( "lexical", order ) )
|
||||
config.runOrder = RunTests::InLexicographicalOrder;
|
||||
else if( startsWith( "random", order ) )
|
||||
config.runOrder = RunTests::InRandomOrder;
|
||||
else
|
||||
throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
|
||||
}
|
||||
inline void setRngSeed( ConfigData& config, std::string const& seed ) {
|
||||
if( seed == "time" ) {
|
||||
config.rngSeed = static_cast<unsigned int>( std::time(0) );
|
||||
}
|
||||
else {
|
||||
std::stringstream ss;
|
||||
ss << seed;
|
||||
ss >> config.rngSeed;
|
||||
if( ss.fail() )
|
||||
throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
|
||||
}
|
||||
}
|
||||
inline void setVerbosity( ConfigData& config, int level ) {
|
||||
// !TBD: accept strings?
|
||||
@ -137,10 +158,22 @@ namespace Catch {
|
||||
.describe( "list all/matching test cases names only" )
|
||||
.bind( &ConfigData::listTestNamesOnly );
|
||||
|
||||
cli["--list-reporters"]
|
||||
cli["--list-reporters"]
|
||||
.describe( "list all reporters" )
|
||||
.bind( &ConfigData::listReporters );
|
||||
|
||||
cli["--order"]
|
||||
.describe( "test case order (defaults to decl)" )
|
||||
.bind( &setOrder, "decl|lex|rand" );
|
||||
|
||||
cli["--rng-seed"]
|
||||
.describe( "set a specific seed for random numbers" )
|
||||
.bind( &setRngSeed, "'time'|number" );
|
||||
|
||||
cli["--force-colour"]
|
||||
.describe( "force colourised output" )
|
||||
.bind( &ConfigData::forceColour );
|
||||
|
||||
return cli;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,16 @@
|
||||
namespace Catch {
|
||||
|
||||
class NonCopyable {
|
||||
NonCopyable( NonCopyable const& );
|
||||
void operator = ( NonCopyable const& );
|
||||
#ifdef CATCH_CPP11_OR_GREATER
|
||||
NonCopyable( NonCopyable const& ) = delete;
|
||||
NonCopyable( NonCopyable && ) = delete;
|
||||
NonCopyable& operator = ( NonCopyable const& ) = delete;
|
||||
NonCopyable& operator = ( NonCopyable && ) = delete;
|
||||
#else
|
||||
NonCopyable( NonCopyable const& info );
|
||||
NonCopyable& operator = ( NonCopyable const& );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
NonCopyable() {}
|
||||
virtual ~NonCopyable();
|
||||
@ -63,6 +71,7 @@ namespace Catch {
|
||||
void toLowerInPlace( std::string& s );
|
||||
std::string toLower( std::string const& s );
|
||||
std::string trim( std::string const& str );
|
||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
|
||||
|
||||
struct pluralise {
|
||||
pluralise( std::size_t count, std::string const& label );
|
||||
@ -85,6 +94,7 @@ namespace Catch {
|
||||
# endif
|
||||
bool empty() const;
|
||||
bool operator == ( SourceLineInfo const& other ) const;
|
||||
bool operator < ( SourceLineInfo const& other ) const;
|
||||
|
||||
std::string file;
|
||||
std::size_t line;
|
||||
|
@ -36,7 +36,21 @@ namespace Catch {
|
||||
|
||||
return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
|
||||
}
|
||||
|
||||
|
||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||
bool replaced = false;
|
||||
std::size_t i = str.find( replaceThis );
|
||||
while( i != std::string::npos ) {
|
||||
replaced = true;
|
||||
str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
|
||||
if( i < str.size()-withThis.size() )
|
||||
i = str.find( replaceThis, i+withThis.size() );
|
||||
else
|
||||
i = std::string::npos;
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
pluralise::pluralise( std::size_t count, std::string const& label )
|
||||
: m_count( count ),
|
||||
m_label( label )
|
||||
@ -64,6 +78,9 @@ namespace Catch {
|
||||
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
|
||||
return line == other.line && file == other.file;
|
||||
}
|
||||
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
|
||||
return line < other.line || ( line == other.line && file < other.file );
|
||||
}
|
||||
|
||||
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
||||
#ifndef __GNUG__
|
||||
|
@ -80,6 +80,10 @@
|
||||
// Visual C++
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if (_MSC_VER >= 1600)
|
||||
#define CATCH_CONFIG_CPP11_NULLPTR
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
|
||||
//#define CATCH_CONFIG_SFINAE // Not confirmed
|
||||
#endif
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
#ifndef CATCH_CONFIG_CONSOLE_WIDTH
|
||||
#define CATCH_CONFIG_CONSOLE_WIDTH 80
|
||||
@ -36,10 +37,13 @@ namespace Catch {
|
||||
noThrow( false ),
|
||||
showHelp( false ),
|
||||
showInvisibles( false ),
|
||||
forceColour( false ),
|
||||
abortAfter( -1 ),
|
||||
rngSeed( 0 ),
|
||||
verbosity( Verbosity::Normal ),
|
||||
warnings( WarnAbout::Nothing ),
|
||||
showDurations( ShowDurations::DefaultForReporter )
|
||||
showDurations( ShowDurations::DefaultForReporter ),
|
||||
runOrder( RunTests::InDeclarationOrder )
|
||||
{}
|
||||
|
||||
bool listTests;
|
||||
@ -52,12 +56,15 @@ namespace Catch {
|
||||
bool noThrow;
|
||||
bool showHelp;
|
||||
bool showInvisibles;
|
||||
bool forceColour;
|
||||
|
||||
int abortAfter;
|
||||
unsigned int rngSeed;
|
||||
|
||||
Verbosity::Level verbosity;
|
||||
WarnAbout::What warnings;
|
||||
ShowDurations::OrNot showDurations;
|
||||
RunTests::InWhatOrder runOrder;
|
||||
|
||||
std::string reporterName;
|
||||
std::string outputFilename;
|
||||
@ -76,12 +83,12 @@ namespace Catch {
|
||||
public:
|
||||
|
||||
Config()
|
||||
: m_os( std::cout.rdbuf() )
|
||||
: m_os( Catch::cout().rdbuf() )
|
||||
{}
|
||||
|
||||
Config( ConfigData const& data )
|
||||
: m_data( data ),
|
||||
m_os( std::cout.rdbuf() )
|
||||
m_os( Catch::cout().rdbuf() )
|
||||
{
|
||||
if( !data.testsOrTags.empty() ) {
|
||||
TestSpecParser parser( ITagAliasRegistry::get() );
|
||||
@ -92,7 +99,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
virtual ~Config() {
|
||||
m_os.rdbuf( std::cout.rdbuf() );
|
||||
m_os.rdbuf( Catch::cout().rdbuf() );
|
||||
m_stream.release();
|
||||
}
|
||||
|
||||
@ -114,7 +121,7 @@ namespace Catch {
|
||||
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
|
||||
|
||||
void setStreamBuf( std::streambuf* buf ) {
|
||||
m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
|
||||
m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
|
||||
}
|
||||
|
||||
void useStream( std::string const& streamName ) {
|
||||
@ -126,7 +133,6 @@ namespace Catch {
|
||||
|
||||
std::string getReporterName() const { return m_data.reporterName; }
|
||||
|
||||
|
||||
int abortAfter() const { return m_data.abortAfter; }
|
||||
|
||||
TestSpec const& testSpec() const { return m_testSpec; }
|
||||
@ -141,7 +147,9 @@ namespace Catch {
|
||||
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
|
||||
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
|
||||
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
|
||||
|
||||
virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
|
||||
virtual unsigned int rngSeed() const { return m_data.rngSeed; }
|
||||
virtual bool forceColour() const { return m_data.forceColour; }
|
||||
|
||||
private:
|
||||
ConfigData m_data;
|
||||
|
@ -12,10 +12,6 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
struct IColourImpl;
|
||||
}
|
||||
|
||||
struct Colour {
|
||||
enum Code {
|
||||
None = 0,
|
||||
@ -61,7 +57,6 @@ namespace Catch {
|
||||
static void use( Code _colourCode );
|
||||
|
||||
private:
|
||||
static Detail::IColourImpl* impl();
|
||||
bool m_moved;
|
||||
};
|
||||
|
||||
|
@ -10,14 +10,36 @@
|
||||
|
||||
#include "catch_console_colour.hpp"
|
||||
|
||||
namespace Catch { namespace Detail {
|
||||
struct IColourImpl {
|
||||
virtual ~IColourImpl() {}
|
||||
virtual void use( Colour::Code _colourCode ) = 0;
|
||||
};
|
||||
}}
|
||||
namespace Catch {
|
||||
namespace {
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
struct IColourImpl {
|
||||
virtual ~IColourImpl() {}
|
||||
virtual void use( Colour::Code _colourCode ) = 0;
|
||||
};
|
||||
|
||||
struct NoColourImpl : IColourImpl {
|
||||
void use( Colour::Code ) {}
|
||||
|
||||
static IColourImpl* instance() {
|
||||
static NoColourImpl s_instance;
|
||||
return &s_instance;
|
||||
}
|
||||
};
|
||||
|
||||
} // anon namespace
|
||||
} // namespace Catch
|
||||
|
||||
#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
|
||||
# ifdef CATCH_PLATFORM_WINDOWS
|
||||
# define CATCH_CONFIG_COLOUR_WINDOWS
|
||||
# else
|
||||
# define CATCH_CONFIG_COLOUR_ANSI
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
@ -32,7 +54,7 @@ namespace Catch { namespace Detail {
|
||||
namespace Catch {
|
||||
namespace {
|
||||
|
||||
class Win32ColourImpl : public Detail::IColourImpl {
|
||||
class Win32ColourImpl : public IColourImpl {
|
||||
public:
|
||||
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
|
||||
{
|
||||
@ -69,11 +91,7 @@ namespace {
|
||||
WORD originalAttributes;
|
||||
};
|
||||
|
||||
inline bool shouldUseColourForPlatform() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static Detail::IColourImpl* platformColourInstance() {
|
||||
IColourImpl* platformColourInstance() {
|
||||
static Win32ColourImpl s_instance;
|
||||
return &s_instance;
|
||||
}
|
||||
@ -81,7 +99,7 @@ namespace {
|
||||
} // end anon namespace
|
||||
} // end namespace Catch
|
||||
|
||||
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||
#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@ -92,7 +110,7 @@ namespace {
|
||||
// Thanks to Adam Strzelecki for original contribution
|
||||
// (http://github.com/nanoant)
|
||||
// https://github.com/philsquared/Catch/pull/131
|
||||
class PosixColourImpl : public Detail::IColourImpl {
|
||||
class PosixColourImpl : public IColourImpl {
|
||||
public:
|
||||
virtual void use( Colour::Code _colourCode ) {
|
||||
switch( _colourCode ) {
|
||||
@ -113,53 +131,48 @@ namespace {
|
||||
case Colour::Bright: throw std::logic_error( "not a colour" );
|
||||
}
|
||||
}
|
||||
static IColourImpl* instance() {
|
||||
static PosixColourImpl s_instance;
|
||||
return &s_instance;
|
||||
}
|
||||
|
||||
private:
|
||||
void setColour( const char* _escapeCode ) {
|
||||
std::cout << '\033' << _escapeCode;
|
||||
Catch::cout() << '\033' << _escapeCode;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool shouldUseColourForPlatform() {
|
||||
return isatty(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
static Detail::IColourImpl* platformColourInstance() {
|
||||
static PosixColourImpl s_instance;
|
||||
return &s_instance;
|
||||
IColourImpl* platformColourInstance() {
|
||||
Ptr<IConfig const> config = getCurrentContext().getConfig();
|
||||
return (config && config->forceColour()) || isatty(STDOUT_FILENO)
|
||||
? PosixColourImpl::instance()
|
||||
: NoColourImpl::instance();
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // not Windows
|
||||
#else // not Windows or ANSI ///////////////////////////////////////////////
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
struct NoColourImpl : Detail::IColourImpl {
|
||||
void use( Colour::Code ) {}
|
||||
static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
|
||||
|
||||
static IColourImpl* instance() {
|
||||
static NoColourImpl s_instance;
|
||||
return &s_instance;
|
||||
}
|
||||
};
|
||||
static bool shouldUseColour() {
|
||||
return shouldUseColourForPlatform() && !isDebuggerActive();
|
||||
}
|
||||
}
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // Windows/ ANSI/ None
|
||||
|
||||
namespace Catch {
|
||||
|
||||
Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
|
||||
Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
|
||||
Colour::~Colour(){ if( !m_moved ) use( None ); }
|
||||
void Colour::use( Code _colourCode ) {
|
||||
impl()->use( _colourCode );
|
||||
}
|
||||
|
||||
Detail::IColourImpl* Colour::impl() {
|
||||
return shouldUseColour()
|
||||
? platformColourInstance()
|
||||
: NoColourImpl::instance();
|
||||
void Colour::use( Code _colourCode ) {
|
||||
static IColourImpl* impl = isDebuggerActive()
|
||||
? NoColourImpl::instance()
|
||||
: platformColourInstance();
|
||||
impl->use( _colourCode );
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
@ -60,7 +60,7 @@ namespace Catch {
|
||||
std::string testName = getResultCapture()->getCurrentTestName();
|
||||
|
||||
std::map<std::string, IGeneratorsForTest*>::const_iterator it =
|
||||
m_generatorsByTestName.find( testName );
|
||||
m_generatorsByTestName.find( testName );
|
||||
return it != m_generatorsByTestName.end()
|
||||
? it->second
|
||||
: NULL;
|
||||
@ -96,8 +96,8 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Stream createStream( std::string const& streamName ) {
|
||||
if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
|
||||
if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
|
||||
if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
|
||||
if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
|
||||
if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
|
||||
|
||||
throw std::domain_error( "Unknown stream: " + streamName );
|
||||
|
@ -51,7 +51,7 @@
|
||||
|
||||
size = sizeof(info);
|
||||
if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
|
||||
std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
|
||||
Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@
|
||||
namespace Catch {
|
||||
void writeToDebugConsole( std::string const& text ) {
|
||||
// !TBD: Need a version for Mac/ XCode and other IDEs
|
||||
std::cout << text;
|
||||
Catch::cout() << text;
|
||||
}
|
||||
}
|
||||
#endif // Platform
|
||||
|
@ -35,7 +35,7 @@ namespace Catch {
|
||||
throw;
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
return toString( [exception description] );
|
||||
return Catch::toString( [exception description] );
|
||||
}
|
||||
#else
|
||||
throw;
|
||||
|
85
include/internal/catch_fatal_condition.hpp
Normal file
85
include/internal/catch_fatal_condition.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Created by Phil on 21/08/2014
|
||||
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// Report the error condition then exit the process
|
||||
inline void fatal( std::string const& message, int exitCode ) {
|
||||
IContext& context = Catch::getCurrentContext();
|
||||
IResultCapture* resultCapture = context.getResultCapture();
|
||||
resultCapture->handleFatalErrorCondition( message );
|
||||
|
||||
if( Catch::alwaysTrue() ) // avoids "no return" warnings
|
||||
exit( exitCode );
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct FatalConditionHandler {
|
||||
void reset() {}
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct SignalDefs { int id; const char* name; };
|
||||
extern SignalDefs signalDefs[];
|
||||
SignalDefs signalDefs[] = {
|
||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
||||
{ SIGFPE, "SIGFPE - Floating point error signal" },
|
||||
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" },
|
||||
{ SIGTERM, "SIGTERM - Termination request signal" },
|
||||
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
|
||||
};
|
||||
|
||||
struct FatalConditionHandler {
|
||||
|
||||
static void handleSignal( int sig ) {
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||
if( sig == signalDefs[i].id )
|
||||
fatal( signalDefs[i].name, -sig );
|
||||
fatal( "<unknown signal>", -sig );
|
||||
}
|
||||
|
||||
FatalConditionHandler() : m_isSet( true ) {
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||
signal( signalDefs[i].id, handleSignal );
|
||||
}
|
||||
~FatalConditionHandler() {
|
||||
reset();
|
||||
}
|
||||
void reset() {
|
||||
if( m_isSet ) {
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||
signal( signalDefs[i].id, SIG_DFL );
|
||||
m_isSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool m_isSet;
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#endif // not Windows
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
@ -16,7 +16,7 @@
|
||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#endif
|
||||
|
||||
#include "catch_runner.hpp"
|
||||
#include "../catch_runner.hpp"
|
||||
#include "catch_registry_hub.hpp"
|
||||
#include "catch_notimplemented_exception.hpp"
|
||||
#include "catch_context_impl.hpp"
|
||||
@ -88,8 +88,6 @@ namespace Catch {
|
||||
Matchers::Impl::StdString::EndsWith::~EndsWith() {}
|
||||
|
||||
void Config::dummy() {}
|
||||
|
||||
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
|
@ -35,6 +35,8 @@ namespace Catch {
|
||||
|
||||
virtual std::string getCurrentTestName() const = 0;
|
||||
virtual const AssertionResult* getLastResult() const = 0;
|
||||
|
||||
virtual void handleFatalErrorCondition( std::string const& message ) = 0;
|
||||
};
|
||||
|
||||
IResultCapture& getResultCapture();
|
||||
|
@ -32,6 +32,11 @@ namespace Catch {
|
||||
Always,
|
||||
Never
|
||||
}; };
|
||||
struct RunTests { enum InWhatOrder {
|
||||
InDeclarationOrder,
|
||||
InLexicographicalOrder,
|
||||
InRandomOrder
|
||||
}; };
|
||||
|
||||
class TestSpec;
|
||||
|
||||
@ -49,6 +54,9 @@ namespace Catch {
|
||||
virtual bool showInvisibles() const = 0;
|
||||
virtual ShowDurations::OrNot showDurations() const = 0;
|
||||
virtual TestSpec const& testSpec() const = 0;
|
||||
virtual RunTests::InWhatOrder runOrder() const = 0;
|
||||
virtual unsigned int rngSeed() const = 0;
|
||||
virtual bool forceColour() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -238,11 +238,14 @@ namespace Catch
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
|
||||
|
||||
// The return value indicates if the messages buffer should be cleared:
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
|
||||
virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
|
||||
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
|
||||
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace Catch {
|
||||
struct ITestCaseRegistry {
|
||||
virtual ~ITestCaseRegistry();
|
||||
virtual std::vector<TestCase> const& getAllTests() const = 0;
|
||||
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
|
||||
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const = 0;
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ namespace Catch
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats );
|
||||
virtual void testGroupEnded( TestGroupStats const& testGroupStats );
|
||||
virtual void testRunEnded( TestRunStats const& testRunStats );
|
||||
virtual void skipTest( TestCaseInfo const& );
|
||||
|
||||
private:
|
||||
Ptr<IReporter> m_legacyReporter;
|
||||
|
@ -77,6 +77,8 @@ namespace Catch
|
||||
void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
|
||||
m_legacyReporter->EndTesting( testRunStats.totals );
|
||||
}
|
||||
void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
|
||||
|
@ -23,9 +23,9 @@ namespace Catch {
|
||||
|
||||
TestSpec testSpec = config.testSpec();
|
||||
if( config.testSpec().hasFilters() )
|
||||
std::cout << "Matching test cases:\n";
|
||||
Catch::cout() << "Matching test cases:\n";
|
||||
else {
|
||||
std::cout << "All available test cases:\n";
|
||||
Catch::cout() << "All available test cases:\n";
|
||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
||||
}
|
||||
|
||||
@ -46,15 +46,15 @@ namespace Catch {
|
||||
: Colour::None;
|
||||
Colour colourGuard( colour );
|
||||
|
||||
std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
|
||||
Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
|
||||
if( !testCaseInfo.tags.empty() )
|
||||
std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
|
||||
Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
|
||||
}
|
||||
|
||||
if( !config.testSpec().hasFilters() )
|
||||
std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
|
||||
Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
|
||||
else
|
||||
std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
|
||||
Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
|
||||
return matchedTests;
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ namespace Catch {
|
||||
++it ) {
|
||||
matchedTests++;
|
||||
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
||||
std::cout << testCaseInfo.name << std::endl;
|
||||
Catch::cout() << testCaseInfo.name << std::endl;
|
||||
}
|
||||
return matchedTests;
|
||||
}
|
||||
@ -96,9 +96,9 @@ namespace Catch {
|
||||
inline std::size_t listTags( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
if( config.testSpec().hasFilters() )
|
||||
std::cout << "Tags for matching test cases:\n";
|
||||
Catch::cout() << "Tags for matching test cases:\n";
|
||||
else {
|
||||
std::cout << "All available tags:\n";
|
||||
Catch::cout() << "All available tags:\n";
|
||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
||||
}
|
||||
|
||||
@ -132,14 +132,14 @@ namespace Catch {
|
||||
.setInitialIndent( 0 )
|
||||
.setIndent( oss.str().size() )
|
||||
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
|
||||
std::cout << oss.str() << wrapper << "\n";
|
||||
Catch::cout() << oss.str() << wrapper << "\n";
|
||||
}
|
||||
std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
|
||||
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
|
||||
return tagCounts.size();
|
||||
}
|
||||
|
||||
inline std::size_t listReporters( Config const& /*config*/ ) {
|
||||
std::cout << "Available reports:\n";
|
||||
Catch::cout() << "Available reporters:\n";
|
||||
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
|
||||
IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
|
||||
std::size_t maxNameLen = 0;
|
||||
@ -151,13 +151,13 @@ namespace Catch {
|
||||
.setInitialIndent( 0 )
|
||||
.setIndent( 7+maxNameLen )
|
||||
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
|
||||
std::cout << " "
|
||||
Catch::cout() << " "
|
||||
<< it->first
|
||||
<< ":"
|
||||
<< std::string( maxNameLen - it->first.size() + 2, ' ' )
|
||||
<< wrapper << "\n";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
Catch::cout() << std::endl;
|
||||
return factories.size();
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
// NB. Any general catch headers included here must be included
|
||||
// in catch.hpp first to make sure they are included by the single
|
||||
// header for non obj-usage
|
||||
#include "internal/catch_test_case_info.h"
|
||||
#include "catch_test_case_info.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This protocol is really only here for (self) documenting purposes, since
|
||||
|
@ -9,9 +9,13 @@
|
||||
#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
# ifdef __ICC // icpc defines the __clang__ macro
|
||||
# pragma warning(pop)
|
||||
# else
|
||||
# pragma clang diagnostic pop
|
||||
# endif
|
||||
#elif defined __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
|
||||
|
@ -25,7 +25,9 @@ namespace Catch {
|
||||
Exception = 0x100 | FailureBit,
|
||||
|
||||
ThrewException = Exception | 1,
|
||||
DidntThrowException = Exception | 2
|
||||
DidntThrowException = Exception | 2,
|
||||
|
||||
FatalErrorCondition = 0x200 | FailureBit
|
||||
|
||||
}; };
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "catch_test_case_tracker.hpp"
|
||||
#include "catch_timer.h"
|
||||
#include "catch_result_builder.h"
|
||||
#include "catch_fatal_condition.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
@ -209,6 +210,37 @@ namespace Catch {
|
||||
return &m_lastResult;
|
||||
}
|
||||
|
||||
virtual void handleFatalErrorCondition( std::string const& message ) {
|
||||
ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
|
||||
resultBuilder.setResultType( ResultWas::FatalErrorCondition );
|
||||
resultBuilder << message;
|
||||
resultBuilder.captureExpression();
|
||||
|
||||
handleUnfinishedSections();
|
||||
|
||||
// Recreate section for test case (as we will lose the one that was in scope)
|
||||
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
||||
SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
|
||||
|
||||
Counts assertions;
|
||||
assertions.failed = 1;
|
||||
SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
|
||||
m_reporter->sectionEnded( testCaseSectionStats );
|
||||
|
||||
TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
|
||||
|
||||
Totals deltaTotals;
|
||||
deltaTotals.testCases.failed = 1;
|
||||
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||
deltaTotals,
|
||||
"",
|
||||
"",
|
||||
false ) );
|
||||
m_totals.testCases.failed++;
|
||||
testGroupEnded( "", m_totals, 1, 1 );
|
||||
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
|
||||
}
|
||||
|
||||
public:
|
||||
// !TBD We need to do this another way!
|
||||
bool aborting() const {
|
||||
@ -230,12 +262,12 @@ namespace Catch {
|
||||
Timer timer;
|
||||
timer.start();
|
||||
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
||||
StreamRedirect coutRedir( std::cout, redirectedCout );
|
||||
StreamRedirect cerrRedir( std::cerr, redirectedCerr );
|
||||
m_activeTestCase->invoke();
|
||||
StreamRedirect coutRedir( Catch::cout(), redirectedCout );
|
||||
StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
|
||||
invokeActiveTestCase();
|
||||
}
|
||||
else {
|
||||
m_activeTestCase->invoke();
|
||||
invokeActiveTestCase();
|
||||
}
|
||||
duration = timer.getElapsedSeconds();
|
||||
}
|
||||
@ -243,20 +275,9 @@ namespace Catch {
|
||||
// This just means the test was aborted due to failure
|
||||
}
|
||||
catch(...) {
|
||||
ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(),
|
||||
m_lastAssertionInfo.lineInfo,
|
||||
m_lastAssertionInfo.capturedExpression.c_str(),
|
||||
m_lastAssertionInfo.resultDisposition );
|
||||
exResult.useActiveException();
|
||||
makeUnexpectedResultBuilder().useActiveException();
|
||||
}
|
||||
// If sections ended prematurely due to an exception we stored their
|
||||
// infos here so we can tear them down outside the unwind process.
|
||||
for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
|
||||
itEnd = m_unfinishedSections.rend();
|
||||
it != itEnd;
|
||||
++it )
|
||||
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
|
||||
m_unfinishedSections.clear();
|
||||
handleUnfinishedSections();
|
||||
m_messages.clear();
|
||||
|
||||
Counts assertions = m_totals.assertions - prevAssertions;
|
||||
@ -272,7 +293,32 @@ namespace Catch {
|
||||
m_reporter->sectionEnded( testCaseSectionStats );
|
||||
}
|
||||
|
||||
void invokeActiveTestCase() {
|
||||
FatalConditionHandler fatalConditionHandler; // Handle signals
|
||||
m_activeTestCase->invoke();
|
||||
fatalConditionHandler.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
ResultBuilder makeUnexpectedResultBuilder() const {
|
||||
return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
|
||||
m_lastAssertionInfo.lineInfo,
|
||||
m_lastAssertionInfo.capturedExpression.c_str(),
|
||||
m_lastAssertionInfo.resultDisposition );
|
||||
}
|
||||
|
||||
void handleUnfinishedSections() {
|
||||
// If sections ended prematurely due to an exception we stored their
|
||||
// infos here so we can tear them down outside the unwind process.
|
||||
for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
|
||||
itEnd = m_unfinishedSections.rend();
|
||||
it != itEnd;
|
||||
++it )
|
||||
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
|
||||
m_unfinishedSections.clear();
|
||||
}
|
||||
|
||||
struct UnfinishedSections {
|
||||
UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
|
||||
: info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class Section {
|
||||
class Section : NonCopyable {
|
||||
public:
|
||||
Section( SectionInfo const& info );
|
||||
~Section();
|
||||
@ -25,15 +25,6 @@ namespace Catch {
|
||||
operator bool() const;
|
||||
|
||||
private:
|
||||
#ifdef CATCH_CPP11_OR_GREATER
|
||||
Section( Section const& ) = delete;
|
||||
Section( Section && ) = delete;
|
||||
Section& operator = ( Section const& ) = delete;
|
||||
Section& operator = ( Section && ) = delete;
|
||||
#else
|
||||
Section( Section const& info );
|
||||
Section& operator = ( Section const& );
|
||||
#endif
|
||||
SectionInfo m_info;
|
||||
|
||||
std::string m_name;
|
||||
|
@ -28,6 +28,9 @@ namespace Catch {
|
||||
private:
|
||||
bool isOwned;
|
||||
};
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@ -78,6 +79,15 @@ namespace Catch {
|
||||
isOwned = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
|
||||
std::ostream& cout() {
|
||||
return std::cout;
|
||||
}
|
||||
std::ostream& cerr() {
|
||||
return std::cerr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
|
||||
|
@ -9,19 +9,24 @@
|
||||
#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||
#pragma clang diagnostic ignored "-Wvariadic-macros"
|
||||
#pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
|
||||
# ifdef __ICC // icpc defines the __clang__ macro
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 161 1682)
|
||||
# else // __ICC
|
||||
# pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||
# pragma clang diagnostic ignored "-Wvariadic-macros"
|
||||
# pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
# pragma clang diagnostic ignored "-Wunused-variable"
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wpadded"
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
|
||||
# endif
|
||||
#elif defined __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wvariadic-macros"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpadded"
|
||||
# pragma GCC diagnostic ignored "-Wvariadic-macros"
|
||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
|
||||
|
@ -73,7 +73,7 @@ namespace Catch {
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
Colour colourGuard( Colour::Red );
|
||||
std::cerr << ex.what() << std::endl;
|
||||
Catch::cerr() << ex.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace Catch {
|
||||
|
||||
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
|
||||
if( tag == "." ||
|
||||
if( startsWith( tag, "." ) ||
|
||||
tag == "hide" ||
|
||||
tag == "!hide" )
|
||||
return TestCaseInfo::IsHidden;
|
||||
@ -36,13 +36,13 @@ namespace Catch {
|
||||
if( isReservedTag( tag ) ) {
|
||||
{
|
||||
Colour colourGuard( Colour::Red );
|
||||
std::cerr
|
||||
Catch::cerr()
|
||||
<< "Tag name [" << tag << "] not allowed.\n"
|
||||
<< "Tag names starting with non alpha-numeric characters are reserved\n";
|
||||
}
|
||||
{
|
||||
Colour colourGuard( Colour::FileName );
|
||||
std::cerr << _lineInfo << std::endl;
|
||||
Catch::cerr() << _lineInfo << std::endl;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
@ -70,14 +70,15 @@ namespace Catch {
|
||||
}
|
||||
else {
|
||||
if( c == ']' ) {
|
||||
enforceNotReservedTag( tag, _lineInfo );
|
||||
|
||||
inTag = false;
|
||||
if( tag == "hide" || tag == "." )
|
||||
TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
|
||||
if( prop == TestCaseInfo::IsHidden )
|
||||
isHidden = true;
|
||||
else
|
||||
tags.insert( tag );
|
||||
else if( prop == TestCaseInfo::None )
|
||||
enforceNotReservedTag( tag, _lineInfo );
|
||||
|
||||
tags.insert( tag );
|
||||
tag.clear();
|
||||
inTag = false;
|
||||
}
|
||||
else
|
||||
tag += c;
|
||||
|
@ -17,10 +17,18 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class TestRegistry : public ITestCaseRegistry {
|
||||
struct LexSort {
|
||||
bool operator() (TestCase i,TestCase j) const { return (i<j);}
|
||||
};
|
||||
struct RandomNumberGenerator {
|
||||
int operator()( int n ) const { return std::rand() % n; }
|
||||
};
|
||||
|
||||
public:
|
||||
TestRegistry() : m_unnamedCount( 0 ) {}
|
||||
virtual ~TestRegistry();
|
||||
@ -43,7 +51,7 @@ namespace Catch {
|
||||
TestCase const& prev = *m_functions.find( testCase );
|
||||
{
|
||||
Colour colourGuard( Colour::Red );
|
||||
std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
|
||||
Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
|
||||
<< "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
|
||||
<< "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
|
||||
}
|
||||
@ -59,18 +67,38 @@ namespace Catch {
|
||||
return m_nonHiddenFunctions;
|
||||
}
|
||||
|
||||
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
|
||||
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const {
|
||||
|
||||
for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
|
||||
itEnd = m_functionsInOrder.end();
|
||||
it != itEnd;
|
||||
++it ) {
|
||||
if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) )
|
||||
bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
|
||||
if( includeTest != negated )
|
||||
matchingTestCases.push_back( *it );
|
||||
}
|
||||
sortTests( config, matchingTestCases );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void sortTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) {
|
||||
|
||||
switch( config.runOrder() ) {
|
||||
case RunTests::InLexicographicalOrder:
|
||||
std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() );
|
||||
break;
|
||||
case RunTests::InRandomOrder:
|
||||
{
|
||||
RandomNumberGenerator rng;
|
||||
std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng );
|
||||
}
|
||||
break;
|
||||
case RunTests::InDeclarationOrder:
|
||||
// already in declaration order
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::set<TestCase> m_functions;
|
||||
std::vector<TestCase> m_functionsInOrder;
|
||||
std::vector<TestCase> m_nonHiddenFunctions;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "catch_common.h"
|
||||
#include "catch_interfaces_testcase.h"
|
||||
#include "internal/catch_compiler_capabilities.h"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace Catch {
|
||||
public:
|
||||
Timer() : m_ticks( 0 ) {}
|
||||
void start();
|
||||
unsigned int getElapsedNanoseconds() const;
|
||||
unsigned int getElapsedMicroseconds() const;
|
||||
unsigned int getElapsedMilliseconds() const;
|
||||
double getElapsedSeconds() const;
|
||||
|
||||
|
@ -27,11 +27,11 @@ namespace Catch {
|
||||
uint64_t getCurrentTicks() {
|
||||
static uint64_t hz=0, hzo=0;
|
||||
if (!hz) {
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
|
||||
QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
|
||||
QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
|
||||
}
|
||||
uint64_t t;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&t);
|
||||
QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
|
||||
return ((t-hzo)*1000000)/hz;
|
||||
}
|
||||
#else
|
||||
@ -46,14 +46,14 @@ namespace Catch {
|
||||
void Timer::start() {
|
||||
m_ticks = getCurrentTicks();
|
||||
}
|
||||
unsigned int Timer::getElapsedNanoseconds() const {
|
||||
unsigned int Timer::getElapsedMicroseconds() const {
|
||||
return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
|
||||
}
|
||||
unsigned int Timer::getElapsedMilliseconds() const {
|
||||
return static_cast<unsigned int>((getCurrentTicks() - m_ticks)/1000);
|
||||
return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
|
||||
}
|
||||
double Timer::getElapsedSeconds() const {
|
||||
return (getCurrentTicks() - m_ticks)/1000000.0;
|
||||
return getElapsedMicroseconds()/1000000.0;
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
@ -21,9 +21,50 @@
|
||||
#include "catch_objc_arc.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef CATCH_CPP11_OR_GREATER
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// Why we're here.
|
||||
template<typename T>
|
||||
std::string toString( T const& value );
|
||||
|
||||
// Built in overloads
|
||||
|
||||
std::string toString( std::string const& value );
|
||||
std::string toString( std::wstring const& value );
|
||||
std::string toString( const char* const value );
|
||||
std::string toString( char* const value );
|
||||
std::string toString( const wchar_t* const value );
|
||||
std::string toString( wchar_t* const value );
|
||||
std::string toString( int value );
|
||||
std::string toString( unsigned long value );
|
||||
std::string toString( unsigned int value );
|
||||
std::string toString( const double value );
|
||||
std::string toString( const float value );
|
||||
std::string toString( bool value );
|
||||
std::string toString( char value );
|
||||
std::string toString( signed char value );
|
||||
std::string toString( unsigned char value );
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
||||
std::string toString( std::nullptr_t );
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
std::string toString( NSString const * const& nsstring );
|
||||
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
|
||||
std::string toString( NSObject* const& nsObject );
|
||||
#endif
|
||||
|
||||
|
||||
namespace Detail {
|
||||
|
||||
extern std::string unprintableString;
|
||||
|
||||
// SFINAE is currently disabled by default for all compilers.
|
||||
// If the non SFINAE version of IsStreamInsertable is ambiguous for you
|
||||
// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
|
||||
@ -64,10 +105,38 @@ namespace Detail {
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CPP11_OR_GREATER)
|
||||
template<typename T,
|
||||
bool IsEnum = std::is_enum<T>::value
|
||||
>
|
||||
struct EnumStringMaker
|
||||
{
|
||||
static std::string convert( T const& ) { return unprintableString; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EnumStringMaker<T,true>
|
||||
{
|
||||
static std::string convert( T const& v )
|
||||
{
|
||||
return ::Catch::toString(
|
||||
static_cast<typename std::underlying_type<T>::type>(v)
|
||||
);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
template<bool C>
|
||||
struct StringMakerBase {
|
||||
#if defined(CATCH_CPP11_OR_GREATER)
|
||||
template<typename T>
|
||||
static std::string convert( T const& ) { return "{?}"; }
|
||||
static std::string convert( T const& v )
|
||||
{
|
||||
return EnumStringMaker<T>::convert( v );
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string convert( T const& ) { return unprintableString; }
|
||||
#endif
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -89,9 +158,6 @@ namespace Detail {
|
||||
|
||||
} // end namespace Detail
|
||||
|
||||
template<typename T>
|
||||
std::string toString( T const& value );
|
||||
|
||||
template<typename T>
|
||||
struct StringMaker :
|
||||
Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
|
||||
@ -122,12 +188,60 @@ namespace Detail {
|
||||
std::string rangeToString( InputIterator first, InputIterator last );
|
||||
}
|
||||
|
||||
//template<typename T, typename Allocator>
|
||||
//struct StringMaker<std::vector<T, Allocator> > {
|
||||
// static std::string convert( std::vector<T,Allocator> const& v ) {
|
||||
// return Detail::rangeToString( v.begin(), v.end() );
|
||||
// }
|
||||
//};
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
struct StringMaker<std::vector<T, Allocator> > {
|
||||
static std::string convert( std::vector<T,Allocator> const& v ) {
|
||||
return Detail::rangeToString( v.begin(), v.end() );
|
||||
std::string toString( std::vector<T,Allocator> const& v ) {
|
||||
return Detail::rangeToString( v.begin(), v.end() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef CATCH_CPP11_OR_GREATER
|
||||
|
||||
// toString for tuples
|
||||
namespace TupleDetail {
|
||||
template<
|
||||
typename Tuple,
|
||||
std::size_t N = 0,
|
||||
bool = (N < std::tuple_size<Tuple>::value)
|
||||
>
|
||||
struct ElementPrinter {
|
||||
static void print( const Tuple& tuple, std::ostream& os )
|
||||
{
|
||||
os << ( N ? ", " : " " )
|
||||
<< Catch::toString(std::get<N>(tuple));
|
||||
ElementPrinter<Tuple,N+1>::print(tuple,os);
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
typename Tuple,
|
||||
std::size_t N
|
||||
>
|
||||
struct ElementPrinter<Tuple,N,false> {
|
||||
static void print( const Tuple&, std::ostream& ) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename ...Types>
|
||||
struct StringMaker<std::tuple<Types...>> {
|
||||
|
||||
static std::string convert( const std::tuple<Types...>& tuple )
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << '{';
|
||||
TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
|
||||
os << " }";
|
||||
return os.str();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace Detail {
|
||||
template<typename T>
|
||||
@ -148,33 +262,6 @@ std::string toString( T const& value ) {
|
||||
return StringMaker<T>::convert( value );
|
||||
}
|
||||
|
||||
// Built in overloads
|
||||
|
||||
std::string toString( std::string const& value );
|
||||
std::string toString( std::wstring const& value );
|
||||
std::string toString( const char* const value );
|
||||
std::string toString( char* const value );
|
||||
std::string toString( const wchar_t* const value );
|
||||
std::string toString( wchar_t* const value );
|
||||
std::string toString( int value );
|
||||
std::string toString( unsigned long value );
|
||||
std::string toString( unsigned int value );
|
||||
std::string toString( const double value );
|
||||
std::string toString( const float value );
|
||||
std::string toString( bool value );
|
||||
std::string toString( char value );
|
||||
std::string toString( signed char value );
|
||||
std::string toString( unsigned char value );
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
||||
std::string toString( std::nullptr_t );
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
std::string toString( NSString const * const& nsstring );
|
||||
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
|
||||
std::string toString( NSObject* const& nsObject );
|
||||
#endif
|
||||
|
||||
namespace Detail {
|
||||
template<typename InputIterator>
|
||||
@ -182,10 +269,9 @@ std::string toString( std::nullptr_t );
|
||||
std::ostringstream oss;
|
||||
oss << "{ ";
|
||||
if( first != last ) {
|
||||
oss << toString( *first );
|
||||
for( ++first ; first != last ; ++first ) {
|
||||
oss << ", " << toString( *first );
|
||||
}
|
||||
oss << Catch::toString( *first );
|
||||
for( ++first ; first != last ; ++first )
|
||||
oss << ", " << Catch::toString( *first );
|
||||
}
|
||||
oss << " }";
|
||||
return oss.str();
|
||||
|
@ -15,6 +15,8 @@ namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
std::string unprintableString = "{?}";
|
||||
|
||||
namespace {
|
||||
struct Endianness {
|
||||
enum Arch { Big, Little };
|
||||
@ -73,7 +75,7 @@ std::string toString( std::wstring const& value ) {
|
||||
s.reserve( value.size() );
|
||||
for(size_t i = 0; i < value.size(); ++i )
|
||||
s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
|
||||
return toString( s );
|
||||
return Catch::toString( s );
|
||||
}
|
||||
|
||||
std::string toString( const char* const value ) {
|
||||
@ -96,7 +98,10 @@ std::string toString( wchar_t* const value )
|
||||
|
||||
std::string toString( int value ) {
|
||||
std::ostringstream oss;
|
||||
oss << value;
|
||||
if( value > 8192 )
|
||||
oss << "0x" << std::hex << value;
|
||||
else
|
||||
oss << value;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@ -110,7 +115,7 @@ std::string toString( unsigned long value ) {
|
||||
}
|
||||
|
||||
std::string toString( unsigned int value ) {
|
||||
return toString( static_cast<unsigned long>( value ) );
|
||||
return Catch::toString( static_cast<unsigned long>( value ) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -35,6 +35,9 @@ namespace Catch {
|
||||
bool allPassed() const {
|
||||
return failed == 0 && failedButOk == 0;
|
||||
}
|
||||
bool allOk() const {
|
||||
return failed == 0;
|
||||
}
|
||||
|
||||
std::size_t passed;
|
||||
std::size_t failed;
|
||||
|
@ -13,7 +13,7 @@
|
||||
namespace Catch {
|
||||
|
||||
// These numbers are maintained by a script
|
||||
Version libraryVersion( 1, 0, 53, "master" );
|
||||
Version libraryVersion( 1, 1, 14, "develop" );
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
|
||||
|
@ -8,8 +8,9 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||
|
||||
#include "../internal/catch_stream.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -52,7 +53,7 @@ namespace Catch {
|
||||
XmlWriter()
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( &std::cout )
|
||||
m_os( &Catch::cout() )
|
||||
{}
|
||||
|
||||
XmlWriter( std::ostream& os )
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "../internal/catch_interfaces_reporter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
|
||||
@ -42,7 +44,6 @@ namespace Catch {
|
||||
}
|
||||
virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
|
||||
currentTestCaseInfo.reset();
|
||||
assert( m_sectionStack.empty() );
|
||||
}
|
||||
virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
|
||||
currentGroupInfo.reset();
|
||||
@ -53,6 +54,11 @@ namespace Catch {
|
||||
currentTestRunInfo.reset();
|
||||
}
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& ) {
|
||||
// Don't do anything with this by default.
|
||||
// It can optionally be overridden in the derived class.
|
||||
}
|
||||
|
||||
Ptr<IConfig> m_config;
|
||||
std::ostream& stream;
|
||||
|
||||
@ -183,6 +189,8 @@ namespace Catch {
|
||||
}
|
||||
virtual void testRunEndedCumulative() = 0;
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& ) {}
|
||||
|
||||
Ptr<IConfig> m_config;
|
||||
std::ostream& stream;
|
||||
std::vector<AssertionStats> m_assertions;
|
||||
@ -198,6 +206,16 @@ namespace Catch {
|
||||
|
||||
};
|
||||
|
||||
template<char C>
|
||||
char const* getLineOfChars() {
|
||||
static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
|
||||
if( !*line ) {
|
||||
memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
|
||||
line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||
|
@ -109,6 +109,13 @@ namespace Catch {
|
||||
printExpressionWas();
|
||||
printRemainingMessages();
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
printResultType( Colour::Error, failedString() );
|
||||
printIssue( "fatal error condition with message:" );
|
||||
printMessage();
|
||||
printExpressionWas();
|
||||
printRemainingMessages();
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
printResultType( Colour::Error, failedString() );
|
||||
printIssue( "expected exception, got none" );
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "../internal/catch_console_colour.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct ConsoleReporter : StreamingReporterBase {
|
||||
@ -149,6 +147,11 @@ namespace Catch {
|
||||
passOrFail = "FAILED";
|
||||
messageLabel = "due to unexpected exception with message";
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED";
|
||||
messageLabel = "due to a fatal error condition";
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED";
|
||||
@ -266,6 +269,9 @@ namespace Catch {
|
||||
stream << " host application.\n"
|
||||
<< "Run with -? for options\n\n";
|
||||
|
||||
if( m_config->rngSeed() != 0 )
|
||||
stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
|
||||
|
||||
currentTestRunInfo.used = true;
|
||||
}
|
||||
void lazyPrintGroupInfo() {
|
||||
@ -437,15 +443,6 @@ namespace Catch {
|
||||
void printSummaryDivider() {
|
||||
stream << getLineOfChars<'-'>() << "\n";
|
||||
}
|
||||
template<char C>
|
||||
static char const* getLineOfChars() {
|
||||
static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
|
||||
if( !*line ) {
|
||||
memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
|
||||
line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_headerPrinted;
|
||||
|
@ -135,7 +135,7 @@ namespace Catch {
|
||||
xml.writeAttribute( "classname", className );
|
||||
xml.writeAttribute( "name", name );
|
||||
}
|
||||
xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) );
|
||||
xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
|
||||
|
||||
writeAssertions( sectionNode );
|
||||
|
||||
@ -168,6 +168,7 @@ namespace Catch {
|
||||
std::string elementName;
|
||||
switch( result.getResultType() ) {
|
||||
case ResultWas::ThrewException:
|
||||
case ResultWas::FatalErrorCondition:
|
||||
elementName = "error";
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
|
222
include/reporters/catch_reporter_teamcity.hpp
Normal file
222
include/reporters/catch_reporter_teamcity.hpp
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Created by Phil Nash on 19th December 2014
|
||||
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
|
||||
|
||||
// Don't #include any Catch headers here - we can assume they are already
|
||||
// included before this header.
|
||||
// This is not good practice in general but is necessary in this case so this
|
||||
// file can be distributed as a single header that works with the main
|
||||
// Catch single header.
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct TeamCityReporter : StreamingReporterBase {
|
||||
TeamCityReporter( ReporterConfig const& _config )
|
||||
: StreamingReporterBase( _config ),
|
||||
m_headerPrintedForThisSection( false )
|
||||
{}
|
||||
|
||||
static std::string escape( std::string const& str ) {
|
||||
std::string escaped = str;
|
||||
replaceInPlace( escaped, "|", "||" );
|
||||
replaceInPlace( escaped, "'", "|'" );
|
||||
replaceInPlace( escaped, "\n", "|n" );
|
||||
replaceInPlace( escaped, "\r", "|r" );
|
||||
replaceInPlace( escaped, "[", "|[" );
|
||||
replaceInPlace( escaped, "]", "|]" );
|
||||
return escaped;
|
||||
}
|
||||
virtual ~TeamCityReporter();
|
||||
|
||||
static std::string getDescription() {
|
||||
return "Reports test results as TeamCity service messages";
|
||||
}
|
||||
virtual ReporterPreferences getPreferences() const {
|
||||
ReporterPreferences prefs;
|
||||
prefs.shouldRedirectStdOut = true;
|
||||
return prefs;
|
||||
}
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& testInfo ) {
|
||||
stream << "##teamcity[testIgnored name='"
|
||||
<< escape( testInfo.name ) << "'";
|
||||
if( testInfo.isHidden() )
|
||||
stream << " message='hidden test'";
|
||||
else
|
||||
stream << " message='test skipped because it didn|'t match the test spec'";
|
||||
stream << "]\n";
|
||||
}
|
||||
|
||||
virtual void noMatchingTestCases( std::string const& /* spec */ ) {}
|
||||
|
||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) {
|
||||
StreamingReporterBase::testGroupStarting( groupInfo );
|
||||
stream << "##teamcity[testSuiteStarted name='"
|
||||
<< escape( groupInfo.name ) << "']\n";
|
||||
}
|
||||
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
|
||||
StreamingReporterBase::testGroupEnded( testGroupStats );
|
||||
stream << "##teamcity[testSuiteFinished name='"
|
||||
<< escape( testGroupStats.groupInfo.name ) << "']\n";
|
||||
}
|
||||
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) {
|
||||
}
|
||||
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
|
||||
AssertionResult const& result = assertionStats.assertionResult;
|
||||
if( !result.isOk() ) {
|
||||
|
||||
std::ostringstream msg;
|
||||
if( !m_headerPrintedForThisSection )
|
||||
printSectionHeader( msg );
|
||||
m_headerPrintedForThisSection = true;
|
||||
|
||||
msg << result.getSourceInfo() << "\n";
|
||||
|
||||
switch( result.getResultType() ) {
|
||||
case ResultWas::ExpressionFailed:
|
||||
msg << "expression failed";
|
||||
break;
|
||||
case ResultWas::ThrewException:
|
||||
msg << "unexpected exception";
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
msg << "fatal error condition";
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
msg << "no exception was thrown where one was expected";
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
msg << "explicit failure";
|
||||
break;
|
||||
|
||||
// We shouldn't get here because of the isOk() test
|
||||
case ResultWas::Ok:
|
||||
case ResultWas::Info:
|
||||
case ResultWas::Warning:
|
||||
|
||||
// These cases are here to prevent compiler warnings
|
||||
case ResultWas::Unknown:
|
||||
case ResultWas::FailureBit:
|
||||
case ResultWas::Exception:
|
||||
CATCH_NOT_IMPLEMENTED;
|
||||
}
|
||||
if( assertionStats.infoMessages.size() == 1 )
|
||||
msg << " with message:";
|
||||
if( assertionStats.infoMessages.size() > 1 )
|
||||
msg << " with messages:";
|
||||
for( std::vector<MessageInfo>::const_iterator
|
||||
it = assertionStats.infoMessages.begin(),
|
||||
itEnd = assertionStats.infoMessages.end();
|
||||
it != itEnd;
|
||||
++it )
|
||||
msg << "\n \"" << it->message << "\"";
|
||||
|
||||
|
||||
if( result.hasExpression() ) {
|
||||
msg <<
|
||||
"\n " << result.getExpressionInMacro() << "\n"
|
||||
"with expansion:\n" <<
|
||||
" " << result.getExpandedExpression() << "\n";
|
||||
}
|
||||
|
||||
stream << "##teamcity[testFailed"
|
||||
<< " name='" << escape( currentTestCaseInfo->name )<< "'"
|
||||
<< " message='" << escape( msg.str() ) << "'"
|
||||
<< "]\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void sectionStarting( SectionInfo const& sectionInfo ) {
|
||||
m_headerPrintedForThisSection = false;
|
||||
StreamingReporterBase::sectionStarting( sectionInfo );
|
||||
}
|
||||
|
||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
|
||||
StreamingReporterBase::testCaseStarting( testInfo );
|
||||
stream << "##teamcity[testStarted name='"
|
||||
<< escape( testInfo.name ) << "']\n";
|
||||
}
|
||||
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
|
||||
StreamingReporterBase::testCaseEnded( testCaseStats );
|
||||
if( !testCaseStats.stdOut.empty() )
|
||||
stream << "##teamcity[testStdOut name='"
|
||||
<< escape( testCaseStats.testInfo.name )
|
||||
<< "' out='" << escape( testCaseStats.stdOut ) << "']\n";
|
||||
if( !testCaseStats.stdErr.empty() )
|
||||
stream << "##teamcity[testStdErr name='"
|
||||
<< escape( testCaseStats.testInfo.name )
|
||||
<< "' out='" << escape( testCaseStats.stdErr ) << "']\n";
|
||||
stream << "##teamcity[testFinished name='"
|
||||
<< escape( testCaseStats.testInfo.name ) << "']\n";
|
||||
}
|
||||
|
||||
private:
|
||||
void printSectionHeader( std::ostream& os ) {
|
||||
assert( !m_sectionStack.empty() );
|
||||
|
||||
if( m_sectionStack.size() > 1 ) {
|
||||
os << getLineOfChars<'-'>() << "\n";
|
||||
|
||||
std::vector<SectionInfo>::const_iterator
|
||||
it = m_sectionStack.begin()+1, // Skip first section (test case)
|
||||
itEnd = m_sectionStack.end();
|
||||
for( ; it != itEnd; ++it )
|
||||
printHeaderString( os, it->name );
|
||||
os << getLineOfChars<'-'>() << "\n";
|
||||
}
|
||||
|
||||
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
||||
|
||||
if( !lineInfo.empty() )
|
||||
os << lineInfo << "\n";
|
||||
os << getLineOfChars<'.'>() << "\n\n";
|
||||
}
|
||||
|
||||
// if string has a : in first line will set indent to follow it on
|
||||
// subsequent lines
|
||||
void printHeaderString( std::ostream& os, std::string const& _string, std::size_t indent = 0 ) {
|
||||
std::size_t i = _string.find( ": " );
|
||||
if( i != std::string::npos )
|
||||
i+=2;
|
||||
else
|
||||
i = 0;
|
||||
os << Text( _string, TextAttributes()
|
||||
.setIndent( indent+i)
|
||||
.setInitialIndent( indent ) ) << "\n";
|
||||
}
|
||||
private:
|
||||
bool m_headerPrintedForThisSection;
|
||||
|
||||
};
|
||||
|
||||
#ifdef CATCH_IMPL
|
||||
TeamCityReporter::~TeamCityReporter() {}
|
||||
#endif
|
||||
|
||||
INTERNAL_CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter )
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
|
@ -13,83 +13,93 @@
|
||||
#include "../internal/catch_capture.hpp"
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "../internal/catch_xmlwriter.hpp"
|
||||
#include "../internal/catch_timer.h"
|
||||
|
||||
namespace Catch {
|
||||
class XmlReporter : public SharedImpl<IReporter> {
|
||||
class XmlReporter : public StreamingReporterBase {
|
||||
public:
|
||||
XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {}
|
||||
XmlReporter( ReporterConfig const& _config )
|
||||
: StreamingReporterBase( _config ),
|
||||
m_sectionDepth( 0 )
|
||||
{}
|
||||
|
||||
virtual ~XmlReporter();
|
||||
|
||||
static std::string getDescription() {
|
||||
return "Reports test results as an XML document";
|
||||
}
|
||||
virtual ~XmlReporter();
|
||||
|
||||
private: // IReporter
|
||||
|
||||
virtual bool shouldRedirectStdout() const {
|
||||
return true;
|
||||
public: // StreamingReporterBase
|
||||
virtual ReporterPreferences getPreferences() const {
|
||||
ReporterPreferences prefs;
|
||||
prefs.shouldRedirectStdOut = true;
|
||||
return prefs;
|
||||
}
|
||||
|
||||
virtual void StartTesting() {
|
||||
m_xml.setStream( m_config.stream() );
|
||||
virtual void noMatchingTestCases( std::string const& s ) {
|
||||
StreamingReporterBase::noMatchingTestCases( s );
|
||||
}
|
||||
|
||||
virtual void testRunStarting( TestRunInfo const& testInfo ) {
|
||||
StreamingReporterBase::testRunStarting( testInfo );
|
||||
m_xml.setStream( stream );
|
||||
m_xml.startElement( "Catch" );
|
||||
if( !m_config.fullConfig()->name().empty() )
|
||||
m_xml.writeAttribute( "name", m_config.fullConfig()->name() );
|
||||
if( !m_config->name().empty() )
|
||||
m_xml.writeAttribute( "name", m_config->name() );
|
||||
}
|
||||
|
||||
virtual void EndTesting( const Totals& totals ) {
|
||||
m_xml.scopedElement( "OverallResults" )
|
||||
.writeAttribute( "successes", totals.assertions.passed )
|
||||
.writeAttribute( "failures", totals.assertions.failed )
|
||||
.writeAttribute( "expectedFailures", totals.assertions.failedButOk );
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
virtual void StartGroup( const std::string& groupName ) {
|
||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) {
|
||||
StreamingReporterBase::testGroupStarting( groupInfo );
|
||||
m_xml.startElement( "Group" )
|
||||
.writeAttribute( "name", groupName );
|
||||
.writeAttribute( "name", groupInfo.name );
|
||||
}
|
||||
|
||||
virtual void EndGroup( const std::string&, const Totals& totals ) {
|
||||
m_xml.scopedElement( "OverallResults" )
|
||||
.writeAttribute( "successes", totals.assertions.passed )
|
||||
.writeAttribute( "failures", totals.assertions.failed )
|
||||
.writeAttribute( "expectedFailures", totals.assertions.failedButOk );
|
||||
m_xml.endElement();
|
||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
|
||||
StreamingReporterBase::testCaseStarting(testInfo);
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
m_testCaseTimer.start();
|
||||
}
|
||||
|
||||
virtual void StartSection( const std::string& sectionName, const std::string& description ) {
|
||||
virtual void sectionStarting( SectionInfo const& sectionInfo ) {
|
||||
StreamingReporterBase::sectionStarting( sectionInfo );
|
||||
if( m_sectionDepth++ > 0 ) {
|
||||
m_xml.startElement( "Section" )
|
||||
.writeAttribute( "name", trim( sectionName ) )
|
||||
.writeAttribute( "description", description );
|
||||
}
|
||||
}
|
||||
virtual void NoAssertionsInSection( const std::string& ) {}
|
||||
virtual void NoAssertionsInTestCase( const std::string& ) {}
|
||||
|
||||
virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
|
||||
if( --m_sectionDepth > 0 ) {
|
||||
m_xml.scopedElement( "OverallResults" )
|
||||
.writeAttribute( "successes", assertions.passed )
|
||||
.writeAttribute( "failures", assertions.failed )
|
||||
.writeAttribute( "expectedFailures", assertions.failedButOk );
|
||||
m_xml.endElement();
|
||||
.writeAttribute( "name", trim( sectionInfo.name ) )
|
||||
.writeAttribute( "description", sectionInfo.description );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
|
||||
m_currentTestSuccess = true;
|
||||
}
|
||||
virtual void assertionStarting( AssertionInfo const& ) { }
|
||||
|
||||
virtual void Result( const Catch::AssertionResult& assertionResult ) {
|
||||
if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
|
||||
return;
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
|
||||
const AssertionResult& assertionResult = assertionStats.assertionResult;
|
||||
|
||||
// Print any info messages in <Info> tags.
|
||||
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
|
||||
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
|
||||
it != itEnd;
|
||||
++it ) {
|
||||
if( it->type == ResultWas::Info ) {
|
||||
m_xml.scopedElement( "Info" )
|
||||
.writeText( it->message );
|
||||
} else if ( it->type == ResultWas::Warning ) {
|
||||
m_xml.scopedElement( "Warning" )
|
||||
.writeText( it->message );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop out if result was successful but we're not printing them.
|
||||
if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
|
||||
return true;
|
||||
|
||||
// Print the expression if there is one.
|
||||
if( assertionResult.hasExpression() ) {
|
||||
m_xml.startElement( "Expression" )
|
||||
.writeAttribute( "success", assertionResult.succeeded() )
|
||||
.writeAttribute( "type", assertionResult.getTestMacroName() )
|
||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||
.writeAttribute( "line", assertionResult.getSourceInfo().line );
|
||||
|
||||
@ -97,58 +107,96 @@ namespace Catch {
|
||||
.writeText( assertionResult.getExpression() );
|
||||
m_xml.scopedElement( "Expanded" )
|
||||
.writeText( assertionResult.getExpandedExpression() );
|
||||
m_currentTestSuccess &= assertionResult.succeeded();
|
||||
}
|
||||
|
||||
// And... Print a result applicable to each result type.
|
||||
switch( assertionResult.getResultType() ) {
|
||||
case ResultWas::ThrewException:
|
||||
m_xml.scopedElement( "Exception" )
|
||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
||||
.writeText( assertionResult.getMessage() );
|
||||
m_currentTestSuccess = false;
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
m_xml.scopedElement( "Fatal Error Condition" )
|
||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
||||
.writeText( assertionResult.getMessage() );
|
||||
break;
|
||||
case ResultWas::Info:
|
||||
m_xml.scopedElement( "Info" )
|
||||
.writeText( assertionResult.getMessage() );
|
||||
break;
|
||||
case ResultWas::Warning:
|
||||
m_xml.scopedElement( "Warning" )
|
||||
.writeText( assertionResult.getMessage() );
|
||||
// Warning will already have been written
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
m_xml.scopedElement( "Failure" )
|
||||
.writeText( assertionResult.getMessage() );
|
||||
m_currentTestSuccess = false;
|
||||
break;
|
||||
case ResultWas::Unknown:
|
||||
case ResultWas::Ok:
|
||||
case ResultWas::FailureBit:
|
||||
case ResultWas::ExpressionFailed:
|
||||
case ResultWas::Exception:
|
||||
case ResultWas::DidntThrowException:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( assertionResult.hasExpression() )
|
||||
m_xml.endElement();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Aborted() {
|
||||
// !TBD
|
||||
virtual void sectionEnded( SectionStats const& sectionStats ) {
|
||||
StreamingReporterBase::sectionEnded( sectionStats );
|
||||
if( --m_sectionDepth > 0 ) {
|
||||
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
|
||||
e.writeAttribute( "successes", sectionStats.assertions.passed );
|
||||
e.writeAttribute( "failures", sectionStats.assertions.failed );
|
||||
e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
|
||||
|
||||
m_xml.endElement();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
|
||||
m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
|
||||
StreamingReporterBase::testCaseEnded( testCaseStats );
|
||||
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
|
||||
e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
|
||||
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
|
||||
StreamingReporterBase::testGroupEnded( testGroupStats );
|
||||
// TODO: Check testGroupStats.aborting and act accordingly.
|
||||
m_xml.scopedElement( "OverallResults" )
|
||||
.writeAttribute( "successes", testGroupStats.totals.assertions.passed )
|
||||
.writeAttribute( "failures", testGroupStats.totals.assertions.failed )
|
||||
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
virtual void testRunEnded( TestRunStats const& testRunStats ) {
|
||||
StreamingReporterBase::testRunEnded( testRunStats );
|
||||
m_xml.scopedElement( "OverallResults" )
|
||||
.writeAttribute( "successes", testRunStats.totals.assertions.passed )
|
||||
.writeAttribute( "failures", testRunStats.totals.assertions.failed )
|
||||
.writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
private:
|
||||
ReporterConfig m_config;
|
||||
bool m_currentTestSuccess;
|
||||
Timer m_testCaseTimer;
|
||||
XmlWriter m_xml;
|
||||
int m_sectionDepth;
|
||||
};
|
||||
|
||||
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
|
||||
|
@ -6,6 +6,11 @@ project(Catch)
|
||||
get_filename_component(CATCH_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
|
||||
get_filename_component(CATCH_DIR "${CATCH_DIR}" PATH)
|
||||
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
||||
if(USE_CPP11)
|
||||
## We can't turn this on by default, since it breaks on travis
|
||||
message(STATUS "Enabling C++11")
|
||||
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
# define the sources of the self test
|
||||
set(SOURCES
|
||||
@ -21,6 +26,11 @@ set(SOURCES
|
||||
${SELF_TEST_DIR}/TestMain.cpp
|
||||
${SELF_TEST_DIR}/TrickyTests.cpp
|
||||
${SELF_TEST_DIR}/VariadicMacrosTests.cpp
|
||||
${SELF_TEST_DIR}/EnumToString.cpp
|
||||
${SELF_TEST_DIR}/ToStringPair.cpp
|
||||
${SELF_TEST_DIR}/ToStringVector.cpp
|
||||
${SELF_TEST_DIR}/ToStringWhich.cpp
|
||||
${SELF_TEST_DIR}/ToStringTuple.cpp
|
||||
)
|
||||
|
||||
# configure the executable
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CatchSelfTest is a <version> host application.
|
||||
CatchSelfTest is a <version> (develop) host application.
|
||||
Run with -? for options
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@ -737,7 +737,7 @@ with expansion:
|
||||
hello
|
||||
hello
|
||||
-------------------------------------------------------------------------------
|
||||
Where the is more to the expression after the RHS[failing]
|
||||
Where there is more to the expression after the RHS
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -748,7 +748,7 @@ warning:
|
||||
error
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Where the LHS is not a simple value[failing]
|
||||
Where the LHS is not a simple value
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -759,7 +759,7 @@ warning:
|
||||
error
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A failing expression with a non streamable type is still captured[failing]
|
||||
A failing expression with a non streamable type is still captured
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -775,7 +775,7 @@ with expansion:
|
||||
{?} == {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
string literals of different sizes can be compared[failing]
|
||||
string literals of different sizes can be compared
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -786,6 +786,6 @@ with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 130 | 91 passed | 38 failed | 1 failed as expected
|
||||
assertions: 709 | 617 passed | 79 failed | 13 failed as expected
|
||||
test cases: 155 | 116 passed | 38 failed | 1 failed as expected
|
||||
assertions: 765 | 673 passed | 79 failed | 13 failed as expected
|
||||
|
||||
|
@ -1,8 +1,88 @@
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CatchSelfTest is a <version> host application.
|
||||
CatchSelfTest is a <version> (develop) host application.
|
||||
Run with -? for options
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "0" )
|
||||
with expansion:
|
||||
"0" == "0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "1" )
|
||||
with expansion:
|
||||
"1" == "1"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum w/operator<<)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "E2{0}" )
|
||||
with expansion:
|
||||
"E2{0}" == "E2{0}"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "E2{1}" )
|
||||
with expansion:
|
||||
"E2{1}" == "E2{1}"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum class)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "0" )
|
||||
with expansion:
|
||||
"0" == "0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "1" )
|
||||
with expansion:
|
||||
"1" == "1"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum class w/operator<<)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "E2/V0" )
|
||||
with expansion:
|
||||
"E2/V0" == "E2/V0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "E2/V1" )
|
||||
with expansion:
|
||||
"E2/V1" == "E2/V1"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e3) == "Unknown enum value 10" )
|
||||
with expansion:
|
||||
"Unknown enum value 10"
|
||||
==
|
||||
"Unknown enum value 10"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Some simple comparisons between doubles
|
||||
-------------------------------------------------------------------------------
|
||||
@ -3318,7 +3398,7 @@ MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Factorial(10) == 3628800 )
|
||||
with expansion:
|
||||
0x<hex digits> == 3628800
|
||||
0x<hex digits> == 0x<hex digits>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
An empty test with no assertions
|
||||
@ -3985,6 +4065,42 @@ PASSED:
|
||||
with expansion:
|
||||
true == true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
force-colour
|
||||
--force-colour
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK_NOTHROW( parseIntoConfig( argv, config ) )
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( config.forceColour )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
force-colour
|
||||
without --force-colour
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK_NOTHROW( parseIntoConfig( argv, config ) )
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( !config.forceColour )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Long strings can be wrapped
|
||||
plain string
|
||||
@ -4438,6 +4554,139 @@ with expansion:
|
||||
five
|
||||
six"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
replace single char
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( replaceInPlace( letters, "b", "z" ) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( letters == "azcdefcg" )
|
||||
with expansion:
|
||||
"azcdefcg" == "azcdefcg"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
replace two chars
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( replaceInPlace( letters, "c", "z" ) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( letters == "abzdefzg" )
|
||||
with expansion:
|
||||
"abzdefzg" == "abzdefzg"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
replace first char
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( replaceInPlace( letters, "a", "z" ) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( letters == "zbcdefcg" )
|
||||
with expansion:
|
||||
"zbcdefcg" == "zbcdefcg"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
replace last char
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( replaceInPlace( letters, "g", "z" ) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( letters == "abcdefcz" )
|
||||
with expansion:
|
||||
"abcdefcz" == "abcdefcz"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
replace all chars
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( replaceInPlace( letters, letters, "replaced" ) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( letters == "replaced" )
|
||||
with expansion:
|
||||
"replaced" == "replaced"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
replace no chars
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK_FALSE( replaceInPlace( letters, "x", "z" ) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( letters == letters )
|
||||
with expansion:
|
||||
"abcdefcg" == "abcdefcg"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
replaceInPlace
|
||||
escape '
|
||||
-------------------------------------------------------------------------------
|
||||
TestMain.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( replaceInPlace( s, "'", "|'" ) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( s == "didn|'t" )
|
||||
with expansion:
|
||||
"didn|'t" == "didn|'t"
|
||||
|
||||
hello
|
||||
hello
|
||||
-------------------------------------------------------------------------------
|
||||
@ -5496,7 +5745,7 @@ with expansion:
|
||||
std::pair( 1, 2 ) == std::pair( 1, 2 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Where the is more to the expression after the RHS[failing]
|
||||
Where there is more to the expression after the RHS
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -5507,10 +5756,10 @@ warning:
|
||||
error
|
||||
|
||||
|
||||
No assertions in test case 'Where the is more to the expression after the RHS[failing]'
|
||||
No assertions in test case 'Where there is more to the expression after the RHS'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Where the LHS is not a simple value[failing]
|
||||
Where the LHS is not a simple value
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -5521,10 +5770,10 @@ warning:
|
||||
error
|
||||
|
||||
|
||||
No assertions in test case 'Where the LHS is not a simple value[failing]'
|
||||
No assertions in test case 'Where the LHS is not a simple value'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A failing expression with a non streamable type is still captured[failing]
|
||||
A failing expression with a non streamable type is still captured
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -5540,7 +5789,7 @@ with expansion:
|
||||
{?} == {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
string literals of different sizes can be compared[failing]
|
||||
string literals of different sizes can be compared
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -5905,6 +6154,234 @@ TrickyTests.cpp:<line number>
|
||||
TrickyTests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( has_toString )
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( item ) == "toString( has_toString )" )
|
||||
with expansion:
|
||||
"toString( has_toString )"
|
||||
==
|
||||
"toString( has_toString )"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( has_maker )
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( item ) == "StringMaker<has_maker>" )
|
||||
with expansion:
|
||||
"StringMaker<has_maker>"
|
||||
==
|
||||
"StringMaker<has_maker>"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( has_maker_and_toString )
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" )
|
||||
with expansion:
|
||||
"toString( has_maker_and_toString )"
|
||||
==
|
||||
"toString( has_maker_and_toString )"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( vectors<has_toString )
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( v ) == "{ {?} }" )
|
||||
with expansion:
|
||||
"{ {?} }" == "{ {?} }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( vectors<has_maker )
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker> }" )
|
||||
with expansion:
|
||||
"{ StringMaker<has_maker> }"
|
||||
==
|
||||
"{ StringMaker<has_maker> }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( vectors<has_maker_and_toString )
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" )
|
||||
with expansion:
|
||||
"{ StringMaker<has_maker_and_toString> }"
|
||||
==
|
||||
"{ StringMaker<has_maker_and_toString> }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
std::pair<int,std::string> -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringPair.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringPair.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" )
|
||||
with expansion:
|
||||
"{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
std::pair<int,const std::string> -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringPair.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringPair.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" )
|
||||
with expansion:
|
||||
"{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
std::vector<std::pair<std::string,int> > -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringPair.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringPair.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" )
|
||||
with expansion:
|
||||
"{ { "green", 55 } }"
|
||||
==
|
||||
"{ { "green", 55 } }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
pair<pair<int,const char *,pair<std::string,int> > -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringPair.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringPair.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" )
|
||||
with expansion:
|
||||
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
==
|
||||
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
vector<int> -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringVector.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ }" )
|
||||
with expansion:
|
||||
"{ }" == "{ }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ 42 }" )
|
||||
with expansion:
|
||||
"{ 42 }" == "{ 42 }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ 42, 512 }" )
|
||||
with expansion:
|
||||
"{ 42, 512 }" == "{ 42, 512 }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
vector<string> -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringVector.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ }" )
|
||||
with expansion:
|
||||
"{ }" == "{ }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ \"hello\" }" )
|
||||
with expansion:
|
||||
"{ "hello" }" == "{ "hello" }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" )
|
||||
with expansion:
|
||||
"{ "hello", "world" }"
|
||||
==
|
||||
"{ "hello", "world" }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
vector<int,allocator> -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringVector.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ }" )
|
||||
with expansion:
|
||||
"{ }" == "{ }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ 42 }" )
|
||||
with expansion:
|
||||
"{ 42 }" == "{ 42 }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(vv) == "{ 42, 512 }" )
|
||||
with expansion:
|
||||
"{ 42, 512 }" == "{ 42, 512 }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
vec<vec<string,alloc>> -> toString
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringVector.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(v) == "{ }" )
|
||||
with expansion:
|
||||
"{ }" == "{ }"
|
||||
|
||||
ToStringVector.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" )
|
||||
with expansion:
|
||||
"{ { "hello" }, { "world" } }"
|
||||
==
|
||||
"{ { "hello" }, { "world" } }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Parse test names and tags
|
||||
Empty test spec should have no filters
|
||||
@ -6932,6 +7409,96 @@ PASSED:
|
||||
with expansion:
|
||||
true == true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
tuple<>
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringTuple.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ }" == Catch::toString(type{}) )
|
||||
with expansion:
|
||||
"{ }" == "{ }"
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ }" == Catch::toString(value) )
|
||||
with expansion:
|
||||
"{ }" == "{ }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
tuple<int>
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringTuple.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ 0 }" == Catch::toString(type{0}) )
|
||||
with expansion:
|
||||
"{ 0 }" == "{ 0 }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
tuple<float,int>
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringTuple.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "1.2f" == Catch::toString(float(1.2)) )
|
||||
with expansion:
|
||||
"1.2f" == "1.2f"
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) )
|
||||
with expansion:
|
||||
"{ 1.2f, 0 }" == "{ 1.2f, 0 }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
tuple<string,string>
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringTuple.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) )
|
||||
with expansion:
|
||||
"{ "hello", "world" }"
|
||||
==
|
||||
"{ "hello", "world" }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
tuple<tuple<int>,tuple<>,float>
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringTuple.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) )
|
||||
with expansion:
|
||||
"{ { 42 }, { }, 1.2f }"
|
||||
==
|
||||
"{ { 42 }, { }, 1.2f }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
tuple<nullptr,int,const char *>
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringTuple.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringTuple.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) )
|
||||
with expansion:
|
||||
"{ nullptr, 42, "Catch me" }"
|
||||
==
|
||||
"{ nullptr, 42, "Catch me" }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Tag alias can be registered against tag patterns
|
||||
The same tag alias can only be registered once
|
||||
@ -7375,6 +7942,6 @@ with expansion:
|
||||
true
|
||||
|
||||
===============================================================================
|
||||
test cases: 130 | 75 passed | 54 failed | 1 failed as expected
|
||||
assertions: 729 | 617 passed | 99 failed | 13 failed as expected
|
||||
test cases: 155 | 100 passed | 54 failed | 1 failed as expected
|
||||
assertions: 785 | 673 passed | 99 failed | 13 failed as expected
|
||||
|
||||
|
@ -1,8 +1,88 @@
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CatchSelfTest is a <version> host application.
|
||||
CatchSelfTest is a <version> (develop) host application.
|
||||
Run with -? for options
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "0" )
|
||||
with expansion:
|
||||
"0" == "0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "1" )
|
||||
with expansion:
|
||||
"1" == "1"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum w/operator<<)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "E2{0}" )
|
||||
with expansion:
|
||||
"E2{0}" == "E2{0}"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "E2{1}" )
|
||||
with expansion:
|
||||
"E2{1}" == "E2{1}"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum class)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "0" )
|
||||
with expansion:
|
||||
"0" == "0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "1" )
|
||||
with expansion:
|
||||
"1" == "1"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum class w/operator<<)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "E2/V0" )
|
||||
with expansion:
|
||||
"E2/V0" == "E2/V0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "E2/V1" )
|
||||
with expansion:
|
||||
"E2/V1" == "E2/V1"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e3) == "Unknown enum value 10" )
|
||||
with expansion:
|
||||
"Unknown enum value 10"
|
||||
==
|
||||
"Unknown enum value 10"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Some simple comparisons between doubles
|
||||
-------------------------------------------------------------------------------
|
||||
@ -406,6 +486,6 @@ with expansion:
|
||||
9.1f != Approx( 9.1000003815 )
|
||||
|
||||
===============================================================================
|
||||
test cases: 15 | 11 passed | 3 failed | 1 failed as expected
|
||||
assertions: 53 | 47 passed | 4 failed | 2 failed as expected
|
||||
test cases: 19 | 15 passed | 3 failed | 1 failed as expected
|
||||
assertions: 62 | 56 passed | 4 failed | 2 failed as expected
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
<testsuites>
|
||||
<testsuite name="all tests" errors="12" failures="87" tests="729" hostname="tbd" time="{duration}" timestamp="tbd">
|
||||
<testsuite name="all tests" errors="12" failures="87" tests="785" hostname="tbd" time="{duration}" timestamp="tbd">
|
||||
<testcase classname="global" name="toString(enum)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum class)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum class w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with different epsilons" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with floats" time="{duration}"/>
|
||||
@ -469,6 +473,8 @@ MiscTests.cpp:<line number>
|
||||
<testcase classname="Process can be configured on command line" name="output filename/-o filename" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="output filename/--out" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="combinations/Single character flags can be combined" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="force-colour/--force-colour" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="force-colour/without --force-colour" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/No wrapping" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped once" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped twice" time="{duration}"/>
|
||||
@ -481,6 +487,13 @@ MiscTests.cpp:<line number>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Wrapped once" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Wrapped twice" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With tabs" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace single char" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace two chars" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace first char" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace last char" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace all chars" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace no chars" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="escape '" time="{duration}"/>
|
||||
<testcase classname="global" name="Strings can be rendered with colour" time="{duration}">
|
||||
<system-out>
|
||||
hello
|
||||
@ -490,9 +503,9 @@ hello
|
||||
<testcase classname="global" name="Text can be formatted using the Text class" time="{duration}"/>
|
||||
<testcase classname="global" name="Long text is truncted" time="{duration}"/>
|
||||
<testcase classname="global" name="Parsing a std::pair" time="{duration}"/>
|
||||
<testcase classname="global" name="Where the is more to the expression after the RHS[failing]" time="{duration}"/>
|
||||
<testcase classname="global" name="Where the LHS is not a simple value[failing]" time="{duration}"/>
|
||||
<testcase classname="global" name="A failing expression with a non streamable type is still captured[failing]" time="{duration}">
|
||||
<testcase classname="global" name="Where there is more to the expression after the RHS" time="{duration}"/>
|
||||
<testcase classname="global" name="Where the LHS is not a simple value" time="{duration}"/>
|
||||
<testcase classname="global" name="A failing expression with a non streamable type is still captured" time="{duration}">
|
||||
<failure message="0x<hex digits> == 0x<hex digits>" type="CHECK">
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
@ -500,7 +513,7 @@ TrickyTests.cpp:<line number>
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="string literals of different sizes can be compared[failing]" time="{duration}">
|
||||
<testcase classname="global" name="string literals of different sizes can be compared" time="{duration}">
|
||||
<failure message=""first" == "second"" type="REQUIRE">
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
@ -529,6 +542,20 @@ TrickyTests.cpp:<line number>
|
||||
<testcase classname="global" name="X/level/0/b" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/1/a" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/1/b" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_maker )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_maker_and_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( vectors<has_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( vectors<has_maker )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( vectors<has_maker_and_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="std::pair<int,std::string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="std::pair<int,const std::string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="std::vector<std::pair<std::string,int> > -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="pair<pair<int,const char *,pair<std::string,int> > -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vector<int> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vector<string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vector<int,allocator> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vec<vec<string,alloc>> -> toString" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Empty test spec should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from empty string should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from just a comma should have no filters" time="{duration}"/>
|
||||
@ -560,6 +587,12 @@ TrickyTests.cpp:<line number>
|
||||
<testcase classname="Parse test names and tags" name="empty tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="empty quoted name" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="quoted string followed by tag exclusion" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<int>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<float,int>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<string,string>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<tuple<int>,tuple<>,float>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<nullptr,int,const char *>" time="{duration}"/>
|
||||
<testcase classname="Tag alias can be registered against tag patterns" name="The same tag alias can only be registered once" time="{duration}"/>
|
||||
<testcase classname="Tag alias can be registered against tag patterns" name="Tag aliases must be of the form [@name]" time="{duration}"/>
|
||||
<testcase classname="global" name="Anonymous test case 1" time="{duration}"/>
|
||||
|
File diff suppressed because it is too large
Load Diff
76
projects/SelfTest/EnumToString.cpp
Normal file
76
projects/SelfTest/EnumToString.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
/*
|
||||
TODO: maybe ought to check that user-provided specialisations of
|
||||
Catch::toString also do the right thing
|
||||
*/
|
||||
|
||||
// Enum without user-provided stream operator
|
||||
enum Enum1 { Enum1Value0, Enum1Value1 };
|
||||
|
||||
TEST_CASE( "toString(enum)", "[toString][enum]" ) {
|
||||
Enum1 e0 = Enum1Value0;
|
||||
CHECK( Catch::toString(e0) == "0" );
|
||||
Enum1 e1 = Enum1Value1;
|
||||
CHECK( Catch::toString(e1) == "1" );
|
||||
}
|
||||
|
||||
// Enum with user-provided stream operator
|
||||
enum Enum2 { Enum2Value0, Enum2Value1 };
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& os, Enum2 v ) {
|
||||
return os << "E2{" << static_cast<int>(v) << "}";
|
||||
}
|
||||
|
||||
TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) {
|
||||
Enum2 e0 = Enum2Value0;
|
||||
CHECK( Catch::toString(e0) == "E2{0}" );
|
||||
Enum2 e1 = Enum2Value1;
|
||||
CHECK( Catch::toString(e1) == "E2{1}" );
|
||||
}
|
||||
|
||||
#if defined(CATCH_CPP11_OR_GREATER)
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
|
||||
// Enum class without user-provided stream operator
|
||||
enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 };
|
||||
|
||||
TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) {
|
||||
EnumClass1 e0 = EnumClass1::EnumClass1Value0;
|
||||
CHECK( Catch::toString(e0) == "0" );
|
||||
EnumClass1 e1 = EnumClass1::EnumClass1Value1;
|
||||
CHECK( Catch::toString(e1) == "1" );
|
||||
}
|
||||
|
||||
// Enum class with user-provided stream operator
|
||||
enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 };
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
|
||||
switch( static_cast<int>( e2 ) ) {
|
||||
case static_cast<int>( EnumClass2::EnumClass2Value0 ):
|
||||
return os << "E2/V0";
|
||||
case static_cast<int>( EnumClass2::EnumClass2Value1 ):
|
||||
return os << "E2/V1";
|
||||
default:
|
||||
return os << "Unknown enum value " << static_cast<int>( e2 );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) {
|
||||
EnumClass2 e0 = EnumClass2::EnumClass2Value0;
|
||||
CHECK( Catch::toString(e0) == "E2/V0" );
|
||||
EnumClass2 e1 = EnumClass2::EnumClass2Value1;
|
||||
CHECK( Catch::toString(e1) == "E2/V1" );
|
||||
|
||||
EnumClass2 e3 = static_cast<EnumClass2>(10);
|
||||
CHECK( Catch::toString(e3) == "Unknown enum value 10" );
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif // CATCH_CPP11_OR_GREATER
|
||||
|
@ -380,3 +380,9 @@ TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
|
||||
std::string result = Catch::toString( s );
|
||||
CHECK( result == "\"wide load\"" );
|
||||
}
|
||||
|
||||
//TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) {
|
||||
// int i = 0;
|
||||
// int x = 10/i; // This should cause the signal to fire
|
||||
// CHECK( x == 0 );
|
||||
//}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "reporters/catch_reporter_teamcity.hpp"
|
||||
|
||||
// Some example tag aliases
|
||||
CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
|
||||
@ -181,7 +182,23 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
CHECK( config.shouldDebugBreak );
|
||||
CHECK( config.noThrow == true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "force-colour", "") {
|
||||
SECTION( "--force-colour", "" ) {
|
||||
const char* argv[] = { "test", "--force-colour" };
|
||||
CHECK_NOTHROW( parseIntoConfig( argv, config ) );
|
||||
|
||||
REQUIRE( config.forceColour );
|
||||
}
|
||||
|
||||
SECTION( "without --force-colour", "" ) {
|
||||
const char* argv[] = { "test" };
|
||||
CHECK_NOTHROW( parseIntoConfig( argv, config ) );
|
||||
|
||||
REQUIRE( !config.forceColour );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -347,22 +364,55 @@ private:
|
||||
std::vector<ColourIndex> colours;
|
||||
};
|
||||
|
||||
TEST_CASE( "replaceInPlace", "" ) {
|
||||
std::string letters = "abcdefcg";
|
||||
SECTION( "replace single char" ) {
|
||||
CHECK( replaceInPlace( letters, "b", "z" ) );
|
||||
CHECK( letters == "azcdefcg" );
|
||||
}
|
||||
SECTION( "replace two chars" ) {
|
||||
CHECK( replaceInPlace( letters, "c", "z" ) );
|
||||
CHECK( letters == "abzdefzg" );
|
||||
}
|
||||
SECTION( "replace first char" ) {
|
||||
CHECK( replaceInPlace( letters, "a", "z" ) );
|
||||
CHECK( letters == "zbcdefcg" );
|
||||
}
|
||||
SECTION( "replace last char" ) {
|
||||
CHECK( replaceInPlace( letters, "g", "z" ) );
|
||||
CHECK( letters == "abcdefcz" );
|
||||
}
|
||||
SECTION( "replace all chars" ) {
|
||||
CHECK( replaceInPlace( letters, letters, "replaced" ) );
|
||||
CHECK( letters == "replaced" );
|
||||
}
|
||||
SECTION( "replace no chars" ) {
|
||||
CHECK_FALSE( replaceInPlace( letters, "x", "z" ) );
|
||||
CHECK( letters == letters );
|
||||
}
|
||||
SECTION( "escape '" ) {
|
||||
std::string s = "didn't";
|
||||
CHECK( replaceInPlace( s, "'", "|'" ) );
|
||||
CHECK( s == "didn|'t" );
|
||||
}
|
||||
}
|
||||
|
||||
// !TBD: This will be folded into Text class
|
||||
TEST_CASE( "Strings can be rendered with colour", "[colour][.]" ) {
|
||||
TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) {
|
||||
|
||||
{
|
||||
ColourString cs( "hello" );
|
||||
cs .addColour( Colour::Red, 0 )
|
||||
.addColour( Colour::Green, -1 );
|
||||
|
||||
std::cout << cs << std::endl;
|
||||
Catch::cout() << cs << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
ColourString cs( "hello" );
|
||||
cs .addColour( Colour::Blue, 1, -2 );
|
||||
|
||||
std::cout << cs << std::endl;
|
||||
Catch::cout() << cs << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
47
projects/SelfTest/ToStringPair.cpp
Normal file
47
projects/SelfTest/ToStringPair.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
// === Pair ===
|
||||
namespace Catch {
|
||||
// Note: If we put this in the right place in catch_tostring, then
|
||||
// we can make it an overload of Catch::toString
|
||||
template<typename T1, typename T2>
|
||||
struct StringMaker<std::pair<T1,T2> > {
|
||||
static std::string convert( const std::pair<T1,T2>& pair ) {
|
||||
std::ostringstream oss;
|
||||
oss << "{ "
|
||||
<< toString( pair.first )
|
||||
<< ", "
|
||||
<< toString( pair.second )
|
||||
<< " }";
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) {
|
||||
std::pair<int,std::string> value( 34, "xyzzy" );
|
||||
REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::pair<int,const std::string> -> toString", "[toString][pair]" ) {
|
||||
std::pair<int,const std::string> value( 34, "xyzzy" );
|
||||
REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::vector<std::pair<std::string,int> > -> toString", "[toString][pair]" ) {
|
||||
std::vector<std::pair<std::string,int> > pr;
|
||||
pr.push_back( std::make_pair("green", 55 ) );
|
||||
REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" );
|
||||
}
|
||||
|
||||
// This is pretty contrived - I figure if this works, anything will...
|
||||
TEST_CASE( "pair<pair<int,const char *,pair<std::string,int> > -> toString", "[toString][pair]" ) {
|
||||
typedef std::pair<int,const char *> left_t;
|
||||
typedef std::pair<std::string,int> right_t;
|
||||
|
||||
left_t left( 42, "Arthur" );
|
||||
right_t right( "Ford", 24 );
|
||||
|
||||
std::pair<left_t,right_t> pair( left, right );
|
||||
REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" );
|
||||
}
|
48
projects/SelfTest/ToStringTuple.cpp
Normal file
48
projects/SelfTest/ToStringTuple.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#ifdef CATCH_CPP11_OR_GREATER
|
||||
|
||||
TEST_CASE( "tuple<>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<> type;
|
||||
CHECK( "{ }" == Catch::toString(type{}) );
|
||||
type value {};
|
||||
CHECK( "{ }" == Catch::toString(value) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<int>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<int> type;
|
||||
CHECK( "{ 0 }" == Catch::toString(type{0}) );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "tuple<float,int>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<float,int> type;
|
||||
CHECK( "1.2f" == Catch::toString(float(1.2)) );
|
||||
CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<string,string>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::string,std::string> type;
|
||||
CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<tuple<int>,tuple<>,float>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::tuple<int>,std::tuple<>,float> type;
|
||||
type value { std::tuple<int>{42}, {}, 1.2f };
|
||||
CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<nullptr,int,const char *>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::nullptr_t,int,const char *> type;
|
||||
type value { nullptr, 42, "Catch me" };
|
||||
CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) );
|
||||
}
|
||||
|
||||
#endif /* #ifdef CATCH_CPP11_OR_GREATER */
|
||||
|
77
projects/SelfTest/ToStringVector.cpp
Normal file
77
projects/SelfTest/ToStringVector.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "catch.hpp"
|
||||
#include <vector>
|
||||
|
||||
|
||||
// vedctor
|
||||
TEST_CASE( "vector<int> -> toString", "[toString][vector]" )
|
||||
{
|
||||
std::vector<int> vv;
|
||||
REQUIRE( Catch::toString(vv) == "{ }" );
|
||||
vv.push_back( 42 );
|
||||
REQUIRE( Catch::toString(vv) == "{ 42 }" );
|
||||
vv.push_back( 512 );
|
||||
REQUIRE( Catch::toString(vv) == "{ 42, 512 }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "vector<string> -> toString", "[toString][vector]" )
|
||||
{
|
||||
std::vector<std::string> vv;
|
||||
REQUIRE( Catch::toString(vv) == "{ }" );
|
||||
vv.push_back( "hello" );
|
||||
REQUIRE( Catch::toString(vv) == "{ \"hello\" }" );
|
||||
vv.push_back( "world" );
|
||||
REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" );
|
||||
}
|
||||
|
||||
#if defined(CATCH_CPP11_OR_GREATER)
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
|
||||
/*
|
||||
Note: These tests *can* be made to work with C++ < 11, but the
|
||||
allocator is a lot more work...
|
||||
*/
|
||||
namespace {
|
||||
/* Minimal Allocator */
|
||||
template<typename T>
|
||||
struct minimal_allocator {
|
||||
typedef T value_type;
|
||||
typedef std::size_t size_type;
|
||||
T *allocate( size_type n ) {
|
||||
return static_cast<T *>( ::operator new( n * sizeof(T) ) );
|
||||
}
|
||||
void deallocate( T *p, size_type /*n*/ ) {
|
||||
::operator delete( static_cast<void *>(p) );
|
||||
}
|
||||
template<typename U>
|
||||
bool operator==( const minimal_allocator<U>& ) const { return true; }
|
||||
template<typename U>
|
||||
bool operator!=( const minimal_allocator<U>& ) const { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE( "vector<int,allocator> -> toString", "[toString][vector,allocator]" ) {
|
||||
std::vector<int,minimal_allocator<int> > vv;
|
||||
REQUIRE( Catch::toString(vv) == "{ }" );
|
||||
vv.push_back( 42 );
|
||||
REQUIRE( Catch::toString(vv) == "{ 42 }" );
|
||||
vv.push_back( 512 );
|
||||
REQUIRE( Catch::toString(vv) == "{ 42, 512 }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "vec<vec<string,alloc>> -> toString", "[toString][vector,allocator]" ) {
|
||||
typedef std::vector<std::string,minimal_allocator<std::string> > inner;
|
||||
typedef std::vector<inner> vector;
|
||||
vector v;
|
||||
REQUIRE( Catch::toString(v) == "{ }" );
|
||||
v.push_back( inner { "hello" } );
|
||||
v.push_back( inner { "world" } );
|
||||
REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" );
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif // CATCH_CPP11_OR_GREATER
|
68
projects/SelfTest/ToStringWhich.cpp
Normal file
68
projects/SelfTest/ToStringWhich.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "catch.hpp"
|
||||
/*
|
||||
Demonstrate which version of toString/StringMaker is being used
|
||||
for various types
|
||||
*/
|
||||
|
||||
|
||||
struct has_toString { };
|
||||
struct has_maker {};
|
||||
struct has_maker_and_toString {};
|
||||
|
||||
namespace Catch {
|
||||
inline std::string toString( const has_toString& ) {
|
||||
return "toString( has_toString )";
|
||||
}
|
||||
inline std::string toString( const has_maker_and_toString& ) {
|
||||
return "toString( has_maker_and_toString )";
|
||||
}
|
||||
template<>
|
||||
struct StringMaker<has_maker> {
|
||||
static std::string convert( const has_maker& ) {
|
||||
return "StringMaker<has_maker>";
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct StringMaker<has_maker_and_toString> {
|
||||
static std::string convert( const has_maker_and_toString& ) {
|
||||
return "StringMaker<has_maker_and_toString>";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Call the overload
|
||||
TEST_CASE( "toString( has_toString )", "[toString]" ) {
|
||||
has_toString item;
|
||||
REQUIRE( Catch::toString( item ) == "toString( has_toString )" );
|
||||
}
|
||||
|
||||
// Call the overload
|
||||
TEST_CASE( "toString( has_maker )", "[toString]" ) {
|
||||
has_maker item;
|
||||
REQUIRE( Catch::toString( item ) == "StringMaker<has_maker>" );
|
||||
}
|
||||
|
||||
// Call the overload
|
||||
TEST_CASE( "toString( has_maker_and_toString )", "[toString]" ) {
|
||||
has_maker_and_toString item;
|
||||
REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" );
|
||||
}
|
||||
|
||||
// Vectors...
|
||||
TEST_CASE( "toString( vectors<has_toString )", "[toString]" ) {
|
||||
std::vector<has_toString> v(1);
|
||||
// This invokes template<T> toString which actually gives us '{ ? }'
|
||||
REQUIRE( Catch::toString( v ) == "{ {?} }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "toString( vectors<has_maker )", "[toString]" ) {
|
||||
std::vector<has_maker> v(1);
|
||||
REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker> }" );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "toString( vectors<has_maker_and_toString )", "[toString]" ) {
|
||||
std::vector<has_maker_and_toString> v(1);
|
||||
// Note: This invokes the template<T> toString -> StringMaker
|
||||
REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" );
|
||||
}
|
@ -44,7 +44,7 @@ TEST_CASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Where the is more to the expression after the RHS[failing]",
|
||||
"Where there is more to the expression after the RHS",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
@ -55,7 +55,7 @@ TEST_CASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Where the LHS is not a simple value[failing]",
|
||||
"Where the LHS is not a simple value",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
@ -81,7 +81,7 @@ struct Opaque
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"A failing expression with a non streamable type is still captured[failing]",
|
||||
"A failing expression with a non streamable type is still captured",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
@ -97,7 +97,7 @@ TEST_CASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"string literals of different sizes can be compared[failing]",
|
||||
"string literals of different sizes can be compared",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
|
@ -1,14 +1,30 @@
|
||||
SOURCES = ApproxTests.cpp \
|
||||
ClassTests.cpp \
|
||||
ConditionTests.cpp \
|
||||
ExceptionTests.cpp \
|
||||
GeneratorTests.cpp \
|
||||
MessageTests.cpp \
|
||||
MiscTests.cpp \
|
||||
TestMain.cpp \
|
||||
TrickyTests.cpp \
|
||||
BDDTests.cpp \
|
||||
VariadicMacrosTests.cpp \
|
||||
EnumToString.cpp \
|
||||
ToStringPair.cpp \
|
||||
ToStringVector.cpp \
|
||||
ToStringWhich.cpp
|
||||
|
||||
EXEC=CatchSelfTest
|
||||
SOURCES = $(wildcard *.cpp)
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
||||
OBJECTS = $(patsubst %.cpp, %.o, $(SOURCES))
|
||||
CXX = g++
|
||||
CXXFLAGS = -I../../include -I../../include/internal
|
||||
CXXFLAGS = -I../../include -std=c++11
|
||||
|
||||
$(EXEC): $(OBJECTS)
|
||||
CatchSelfTest: $(OBJECTS)
|
||||
$(CXX) -o $@ $^
|
||||
|
||||
test: CatchSelfTest
|
||||
./CatchSelfTest
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJECTS)
|
||||
$(RM) $(EXEC)
|
||||
rm -f $(OBJECTS) CatchSelfTest
|
||||
|
||||
|
@ -7,11 +7,16 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */; };
|
||||
263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */; };
|
||||
263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */; };
|
||||
263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */; };
|
||||
2656C2211925E7330040DB02 /* catch_test_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2656C2201925E7330040DB02 /* catch_test_spec.cpp */; };
|
||||
266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */; };
|
||||
266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266ECD73170F3C620030D735 /* BDDTests.cpp */; };
|
||||
26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */; };
|
||||
26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; };
|
||||
2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2691574B1A532A280054F1ED /* ToStringTuple.cpp */; };
|
||||
26948286179A9AB900ED166E /* SectionTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */; };
|
||||
2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; };
|
||||
26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E1B7D119213BC900812682 /* CmdLineTests.cpp */; };
|
||||
@ -66,6 +71,11 @@
|
||||
2627F7061935B55F009BCE2D /* catch_result_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_result_builder.hpp; sourceTree = "<group>"; };
|
||||
262E7399184673A800CAC268 /* catch_reporter_bases.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_bases.hpp; sourceTree = "<group>"; };
|
||||
262E739A1846759000CAC268 /* catch_common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_common.hpp; sourceTree = "<group>"; };
|
||||
263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_fatal_condition.hpp; sourceTree = "<group>"; };
|
||||
263F7A4619B6FCBF009474C2 /* EnumToString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EnumToString.cpp; path = ../../../SelfTest/EnumToString.cpp; sourceTree = "<group>"; };
|
||||
263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringPair.cpp; path = ../../../SelfTest/ToStringPair.cpp; sourceTree = "<group>"; };
|
||||
263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringVector.cpp; path = ../../../SelfTest/ToStringVector.cpp; sourceTree = "<group>"; };
|
||||
263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringWhich.cpp; path = ../../../SelfTest/ToStringWhich.cpp; sourceTree = "<group>"; };
|
||||
263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = "<group>"; };
|
||||
263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = "<group>"; };
|
||||
2656C21F1925E5100040DB02 /* catch_test_spec_parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec_parser.hpp; sourceTree = "<group>"; };
|
||||
@ -87,6 +97,8 @@
|
||||
26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; };
|
||||
26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; };
|
||||
268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = "<group>"; };
|
||||
2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_teamcity.hpp; sourceTree = "<group>"; };
|
||||
2691574B1A532A280054F1ED /* ToStringTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringTuple.cpp; path = ../../../SelfTest/ToStringTuple.cpp; sourceTree = "<group>"; };
|
||||
26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = "<group>"; };
|
||||
26926E8418D77809004E10F2 /* tbc_text_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/external/tbc_text_format.h; sourceTree = "<group>"; };
|
||||
26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = "<group>"; };
|
||||
@ -246,6 +258,11 @@
|
||||
4A6D0C40149B3DAB00DB3EAA /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2691574B1A532A280054F1ED /* ToStringTuple.cpp */,
|
||||
263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */,
|
||||
263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */,
|
||||
263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */,
|
||||
263F7A4619B6FCBF009474C2 /* EnumToString.cpp */,
|
||||
266ECD73170F3C620030D735 /* BDDTests.cpp */,
|
||||
4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */,
|
||||
4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */,
|
||||
@ -300,6 +317,7 @@
|
||||
4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */,
|
||||
4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */,
|
||||
4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */,
|
||||
2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */,
|
||||
);
|
||||
name = reporters;
|
||||
path = ../../../../include/reporters;
|
||||
@ -453,6 +471,7 @@
|
||||
268F47B018A93F7800D8C14F /* catch_clara.h */,
|
||||
2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */,
|
||||
2656C227192A78410040DB02 /* catch_reenable_warnings.h */,
|
||||
263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */,
|
||||
);
|
||||
name = Infrastructure;
|
||||
sourceTree = "<group>";
|
||||
@ -492,7 +511,7 @@
|
||||
4A6D0C17149B3D3B00DB3EAA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0500;
|
||||
LastUpgradeCheck = 0600;
|
||||
};
|
||||
buildConfigurationList = 4A6D0C1A149B3D3B00DB3EAA /* Build configuration list for PBXProject "CatchSelfTest" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@ -516,6 +535,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */,
|
||||
4A6D0C37149B3D9E00DB3EAA /* ApproxTests.cpp in Sources */,
|
||||
4A6D0C38149B3D9E00DB3EAA /* ClassTests.cpp in Sources */,
|
||||
4A6D0C39149B3D9E00DB3EAA /* ConditionTests.cpp in Sources */,
|
||||
@ -525,7 +545,10 @@
|
||||
4A6D0C3D149B3D9E00DB3EAA /* MiscTests.cpp in Sources */,
|
||||
4A6D0C3E149B3D9E00DB3EAA /* TestMain.cpp in Sources */,
|
||||
4A6D0C3F149B3D9E00DB3EAA /* TrickyTests.cpp in Sources */,
|
||||
263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */,
|
||||
263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */,
|
||||
4AEE032016142F910071E950 /* catch_common.cpp in Sources */,
|
||||
263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */,
|
||||
4AEE032316142FC70071E950 /* catch_debugger.cpp in Sources */,
|
||||
4AEE032516142FF10071E950 /* catch_stream.cpp in Sources */,
|
||||
4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */,
|
||||
@ -538,6 +561,7 @@
|
||||
4A45DA2D16161FA2004F8D6B /* catch_interfaces_capture.cpp in Sources */,
|
||||
4A45DA3116161FFC004F8D6B /* catch_interfaces_reporter.cpp in Sources */,
|
||||
4A45DA3316162047004F8D6B /* catch_interfaces_exception.cpp in Sources */,
|
||||
2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */,
|
||||
26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */,
|
||||
4A45DA3516162071004F8D6B /* catch_interfaces_runner.cpp in Sources */,
|
||||
4AB3D99D1616216500C9A0F8 /* catch_interfaces_testcase.cpp in Sources */,
|
||||
@ -564,9 +588,11 @@
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
@ -613,10 +639,12 @@
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = NO;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
|
@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>034502BF-F920-4DB6-82F5-71E61E50118C</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>CatchSelfTest</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>01DD8CA9-7DC3-46BC-B998-EFF40EA3485F</key>
|
||||
<string>ssh://github.com/philsquared/Catch.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>01DD8CA9-7DC3-46BC-B998-EFF40EA3485F</key>
|
||||
<string>../../../../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>ssh://github.com/philsquared/Catch.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>110</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>01DD8CA9-7DC3-46BC-B998-EFF40EA3485F</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>01DD8CA9-7DC3-46BC-B998-EFF40EA3485F</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>Catch</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -9,8 +9,9 @@ from scriptCommon import catchPath
|
||||
|
||||
rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' )
|
||||
|
||||
filenameParser = re.compile( r'.*/(.*\..pp:)(.*)' )
|
||||
filenameParser = re.compile( r'(.*)/(.*\..pp:)(.*)' )
|
||||
filelineParser = re.compile( r'(.*\..pp:)([0-9]*)(.*)' )
|
||||
pathParser = re.compile( r'(.*?)/(.*\..pp)(.*)' )
|
||||
lineNumberParser = re.compile( r'(.*)line="[0-9]*"(.*)' )
|
||||
hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' )
|
||||
durationsParser = re.compile( r'(.*)time="[0-9]*\.[0-9]*"(.*)' )
|
||||
@ -26,14 +27,20 @@ overallResult = 0
|
||||
def filterLine( line ):
|
||||
m = filenameParser.match( line )
|
||||
if m:
|
||||
line = m.group(1) + m.group(2)
|
||||
m = filelineParser.match( line )
|
||||
if m:
|
||||
line = m.group(1) + "<line number>" + m.group(3)
|
||||
line = m.group(2) + m.group(3)
|
||||
m2 = filelineParser.match( line )
|
||||
if m2:
|
||||
line = m2.group(1) + "<line number>" + m2.group(3)
|
||||
else:
|
||||
m = lineNumberParser.match( line )
|
||||
if m:
|
||||
line = m.group(1) + m.group(2)
|
||||
m2 = lineNumberParser.match( line )
|
||||
if m2:
|
||||
line = m2.group(1) + m2.group(2)
|
||||
m = pathParser.match( line )
|
||||
if m:
|
||||
path = "/" + m.group(2)
|
||||
if path.startswith( catchPath ):
|
||||
path = path[1+len(catchPath):]
|
||||
line = m.group(1) + path + m.group(3)
|
||||
m = versionParser.match( line )
|
||||
if m:
|
||||
line = m.group(1) + "<version>" + m.group(2)
|
||||
@ -52,6 +59,8 @@ def filterLine( line ):
|
||||
def approve( baseName, args ):
|
||||
global overallResult
|
||||
args[0:0] = [cmdPath]
|
||||
if not os.path.exists( cmdPath ):
|
||||
raise Exception( "Executable doesn't exist at " + cmdPath )
|
||||
baselinesPath = os.path.join( rootPath, '{0}.approved.txt'.format( baseName ) )
|
||||
rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) )
|
||||
filteredResultsPath = os.path.join( rootPath, '{0}.unapproved.txt'.format( baseName ) )
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user