Compare commits

...

224 Commits

Author SHA1 Message Date
9a56609569 v1.6.1 build 2017-01-20 12:49:59 +01:00
81159838a5 Python scripts can now be run directly from bash 2017-01-20 12:28:40 +01:00
78a2866dc7 Approval tests are now mostly Windows compatible
There are some differences in output between Catch on Windows and
Catch on Linux, that indicate a minor bug, but those have to be fixed separately.
2017-01-19 23:56:31 +01:00
9acc6b9673 Approval tests now use Python std lib instead of call to diff
This needed to change to let it run on Windows as well as on the Unices
2017-01-19 22:52:47 +01:00
c4b5057094 Approval tests now uses path relative to cwd, not the catch folder.
This means that bash's autocompletion is actually helpful.
2017-01-19 22:08:51 +01:00
d38b9266e7 simplify output filtering in approvalTests.py 2017-01-19 22:04:29 +01:00
227598af47 use sizeof(expr) for unevaluated syntax check 2017-01-19 21:25:27 +01:00
cfaf906417 Changed documentation to use standard main function signature 2017-01-19 17:05:01 +01:00
ee0ca512ea Force short-circuited evaluation for types that have overloaded &&.
This fixes #574.
2017-01-17 23:31:03 +01:00
b71a06cf98 JUnit reporter outputs timestamps now
Also extended approval tests script to support the change
2017-01-16 20:21:43 +01:00
531d26739f Added the new proxy header to CMakeLists.txt 2017-01-16 19:56:57 +01:00
2e87f8e328 Merge branch 'windows-header-defines' of https://github.com/horenmar/Catch 2017-01-16 17:00:43 +01:00
afe46ff270 Extracted NOMINMAX and WIN32_LEAN_AND_MEAN guards into a proxy header 2017-01-16 16:52:44 +01:00
c65aeaf25f Clean up generator state 2017-01-16 10:34:16 +00:00
750b52b814 suppress use of __COUNTER__ when being parsed by CLion (or AppCode). 2017-01-16 10:34:16 +00:00
e12fc4aca0 Fix missing CATCH_ for CHECK_THAT in prefixed macro version 2017-01-15 22:11:43 +01:00
99cdc62fef Enabled CMake dev warnings in travis. 2017-01-15 22:08:12 +01:00
e6ef60a2c4 CMake will now warn if a file is in folder, but not in variable 2017-01-15 22:07:36 +01:00
e1c4a4bd9b Use inline assembly with gcc under Linux for CATCH_TRAP
This is more convenient than using the generic portable raise(SIGTRAP) as it
avoids having another stack frame in the debugger when the break happens.
2017-01-15 19:29:34 +01:00
25d017763b Refactor CATCH_BREAK_INTO_DEBUGGER() to avoid repetition
Don't duplicate Catch::isDebuggerActive() check many times, do it just once
in CATCH_BREAK_INTO_DEBUGGER() definition and use a separate CATCH_TRAP()
macro for the really platform-dependent part.
2017-01-15 19:29:34 +01:00
b634e592da Add support for breaking into debugger for Linux
Use Linux-specific /proc/$PID/status file to check whether we're being
debugged and a generic raise(SIGTRAP) to actually break into the debugger.
2017-01-15 19:29:34 +01:00
e3659cdddd Added single char version of logo 2017-01-13 18:49:49 +00:00
b3907a78e1 Added NOMINMAX and WIN32_LEAN_AND_MEAN defines before including windows.h
This stops the `windows.h` header from defining `min` and `max` macros
and including lot of Windows APIs that are not needed by Catch.
2017-01-12 16:00:02 +01:00
d5360e8e29 Sorted file lists in CMakeLists.txt for easier maintainence 2017-01-12 11:54:53 +00:00
9062ebe390 Removed make file (now generated from CMake) 2017-01-12 11:22:30 +00:00
e6aa1f4e4e Added note on escaping names on command line to docs 2017-01-11 17:14:28 +00:00
1ff0acfe22 Tweaked release notes page with better formatting 2017-01-11 16:50:35 +00:00
713ec400e8 Fixed type in “Release Notes” link 2017-01-11 16:46:09 +00:00
3b2f206191 v1.6.0 build - including release notes 2017-01-11 16:44:36 +00:00
4e4d733f90 Added \ as escape character in test names on the command line - so you can run tests by name when they contain , or [ 2017-01-11 16:27:16 +00:00
b68e8f9a24 Added missing #include so CATCH_CONFIG_COUNTER properly takes into account the current compiler.
May address #677 and #435 and others.
2017-01-11 16:27:16 +00:00
a7cda91d4d Merge pull request #775 from philsquared/standardizing-feature-toggles
Standardize C++11 feature toggles to follow documentation
2017-01-11 16:27:05 +00:00
a1bed572be Standardize C++11 feature toggles to follow documentation
Closes #774
2017-01-10 22:54:57 +01:00
737f4ea77c Added missing C++11 feature toggle to docs 2017-01-10 22:43:58 +01:00
b0de6c938a Updated docs for contributing 2017-01-10 07:36:06 +00:00
6991549457 Fixed compile error under VS2015 /c++:latest, caused by using random_shuffle
Now if we detect C++11 compiler, or MSVC in version corresponding to VS2015,
we switch from using `std::random_shuffle` to `std::shuffle`.

`std::random_shuffle` was officially deprecated in C++14, and removed in C++17.

Also removed guarded inclusion of `<random>` header, as there was nothing
in the header that used it.
2017-01-09 23:29:13 +01:00
b50572bbfd Renamed missing project explainer filename 2017-01-09 21:59:53 +00:00
5b00fd40ba Merge pull request #767 from hmich/xml-encoder-extended-ascii
Do not encode extended ASCII characters in XML reporter
2017-01-09 18:37:52 +00:00
7bb3e859aa Removed all manually maintained project files in favour of instructions on how to use CMake to generate them 2017-01-09 17:38:42 +00:00
0bcae64d3d Set project name in CMakeLists.txt to CatchSelfTest 2017-01-09 17:38:42 +00:00
8abe17a393 CMake project groups test files separately from surrogate impl files for nicer rendering as XCode/ VS projects 2017-01-09 17:38:42 +00:00
10c44847f4 Make backticks symmetric in markdown 2017-01-09 18:03:40 +01:00
0cde0e90a6 Added approvals for “Greater-than inequalities with different epsilons” test 2017-01-09 14:40:09 +00:00
0f0dcd31eb Excluded two more C++11 tests from Approval tests 2017-01-09 14:37:28 +00:00
62cbde369e Exclude test name from approval tests 2017-01-09 14:37:28 +00:00
1ae84897d4 Marked tests that use C++11 features with [c++11] tag and exclude them from approval tests 2017-01-09 14:37:28 +00:00
976a655496 Approval tests can use Catch path fixed in env. var, and convert nullptr and __null to 0 for comparison 2017-01-09 14:37:28 +00:00
37e1e24309 add support for inequalities 2017-01-08 22:28:53 +01:00
5a4dde4b5d Changed build status to be always taken from master
Before it was taken from whatever last build happened, which led it show
a build error because I took PR against wrong branch.

This should be fixed now.
2017-01-08 21:49:14 +01:00
8d326424f3 Minor typo fix 2017-01-07 22:05:18 +01:00
ccc34b63b6 URL fixed 2017-01-07 14:51:13 +01:00
7255be28cc remove concatenation of m_exprComponents.op in if-branch where op has tested empty in previous line 2017-01-07 13:37:08 +01:00
7d2668fa15 add missing argument to CATCH_CHECK_THROWS (closes #602) 2017-01-07 12:16:06 +01:00
2a4dba177f Merge branch 'philipp-classen-master'
Removed changes to the single-include header.
2017-01-07 10:31:36 +01:00
8d1e240700 Fixed shell color code of "Blue" 2017-01-07 10:30:43 +01:00
e273a3dc88 Fix grammar error in tutorial.md
It's = it is
In the sentence "In fact it is usually a good idea to put the block with the ```#define``` [in it's own source file](slow-compiles.md).", the correct usage is "its", not "it's".
2017-01-07 09:56:21 +01:00
7bff9cb451 own-main.md: fix typo 2017-01-07 09:55:27 +01:00
fd1da4a1d1 Fixing a couple of typos
I tried to make sure I wasn't changing any British spellings so I apologize
if I've mixed any up.
2017-01-07 09:45:38 +01:00
e1fbbe1590 Added headers to CMake project (for CLion) 2017-01-06 16:59:18 +00:00
c8fefc4670 Fixed Travis and CMake after moving CMakeLists.txt 2017-01-06 16:19:20 +00:00
64193078bc Moved CMake into root folder (where it’s much happier - especially for CLion) 2017-01-06 16:00:00 +00:00
8d16d95a99 Do not encode extended ASCII characters in XML reporter 2016-12-26 11:39:19 +00:00
2be372710e Build 1.5.9 2016-11-29 12:15:50 +00:00
0c093bee38 Removed now redundant xml stream initialisation 2016-11-29 12:13:55 +00:00
dedc7c56ce Merge branch 'horenmar-xml-reporter-fix' 2016-11-29 12:11:05 +00:00
a9561ecb31 Merge branch 'xml-reporter-fix' of https://github.com/horenmar/Catch into horenmar-xml-reporter-fix 2016-11-29 12:10:46 +00:00
e4df006568 Merge branch 'horenmar-missing-include-fix' 2016-11-29 12:05:35 +00:00
fb99cc556d Merge branch 'missing-include-fix' of https://github.com/horenmar/Catch into horenmar-missing-include-fix 2016-11-29 12:05:11 +00:00
862d13138c Explicitly convert int to char during transform on string (equivalent of PR #756) 2016-11-29 12:04:09 +00:00
79acc0504b Sort test ordering during Approval testing 2016-11-29 11:32:16 +00:00
f9afa2a68d Ignore CMake and CLion generated files 2016-11-29 11:27:22 +00:00
0c8c6b347a Fixes build error caused by missing include. 2016-11-28 15:47:20 +01:00
40b6ad73df Fix XmlReporter always writing first line to stdout 2016-11-26 12:11:23 +01:00
30cebd6177 Added some missing source files (including all SurrogateCpps) to CMake project.
Fixed up relative include paths to make this work.
2016-11-09 22:55:32 +00:00
e27c4ee042 Build 1.5.8 2016-10-26 12:08:26 +01:00
072114293b Merge branch 'BillyONeal-master' 2016-10-26 12:06:35 +01:00
f90ee9fb37 Merge branch 'master' of https://github.com/BillyONeal/Catch into BillyONeal-master 2016-10-26 12:04:38 +01:00
c17ba0870a Fix transform without a lambda
Catch apparently supports targeting C++03, so use an inline function
instead.
2016-10-14 14:28:15 -07:00
79f01100e3 Fix transform narrowing warnings
Catch passes ::tolower into std::transform with string iterators.
::tolower has the signature int(int), which triggers a stealth narrowing
warning inside std::transform, because transform calls
*_Dest = _Fn(*_First), which implicitly narrows an int to a char.

For this particular application the narrowing is fine, so explicitly
narrow in a lambda.
2016-10-14 14:16:21 -07:00
ccf7f2842a Fix random_shuffle narrowing warnings
Catch passes an RNG which accepts int to random_shuffle. Inside
random_shuffle, the STL tries to call that RNG with the difference_type
of the user provided iterators. For std::vector, this is ptrdiff_t,
which on amd64 builds is wider than int. This triggers a narrowing
warning because the 64 bit difference is being truncated to 32 bits.

Note that this RNG implementation still does not produce a correctly
uniformly shuffled result -- it's currently asserting that std::rand
can produce 1000000 which is false -- but I don't know enough about
how much repeatable shuffles are necessary here, so I'm leaving that
alone for now.
2016-10-14 14:06:45 -07:00
e0302db4a6 Rename element for Fatal Error Condition so it doesn't have spaces
Fixes: #685
2016-10-14 18:45:08 +01:00
88732e85b2 Merge pull request #716 from jbcoe/master
Quick fix for failing travis builds on OS X
2016-10-04 15:57:10 +01:00
1c9a6cab88 Removed XCode6 builds (which were erroring anyway) and added XCode8 builds 2016-09-27 11:20:33 +01:00
40f6068d52 Build 1.5.7 2016-09-27 10:46:22 +01:00
21cbfc107e --list-test-names quotes test names that start with #
- completes #717
2016-09-27 10:43:03 +01:00
31861bbd46 rebased following recent changes 2016-09-27 10:28:11 +01:00
b1eeec7c69 -f supports quoted test names (test name surrounded with " characters).
This is the first part to resolving #717
2016-09-27 10:27:28 +01:00
c23b374f3d Added braces to emphasise the return logic 2016-09-27 09:58:12 +01:00
916317bd81 Merge pull request #680 from nabijaczleweli/master
Fix misindent in internal/catch_test_spec.hpp:70
2016-09-27 09:49:37 +01:00
8c459dd207 Fix misindent
Closes #679
2016-09-27 00:35:26 +02:00
fd7d35464b quick fix for failing travis builds on os x 2016-09-24 19:38:43 +01:00
c47c1797d2 Merge pull request #701 from razeh/master
Fixes for XML encoding.
2016-09-22 17:44:14 +01:00
f5d2b2dce8 Merge pull request #705 from hmich/xml-reporter-trim
Do not trim test case names in the XML reporter.
2016-09-22 17:28:46 +01:00
02c7e41c7c Do not trim test case names in the XML reporter.
SCENARIO does not add leading spaces to the test name (only BDD-style section
names are modified), so the trimming is not necessary. But if the name is
trimmed, it makes it harder to correlate the output of XML reporter with tests
that have leading spaces in their name: e.g. these tests will have the same name
attribute:

TEST_CASE("Test") {}
TEST_CASE(" Test") {}
2016-08-30 11:15:19 +01:00
5095619955 Fixes for XML encoding.
This commit fixes the following scenario:
  * You have a test that compares strings with embedded control
  characters.
  * The test fails.
  * You are using JUnit tests within TeamCity.

Before this commit, the JUnit report watcher fails on parsing the XML
for two reasons: the control characters are missing a semicolon at the
end, and the XML document doesn't specify that it is XML 1.1.

XML 1.0 --- what we get if we don't specify an XML version --- doesn't support embedding control characters --- see
http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml
for all of the gory details.

This is based on PR #588 by @mrpi
2016-08-24 09:38:24 -05:00
35f510545d v1.5.6 2016-06-09 19:21:09 +01:00
742457cbcf Use Clara v0.0.2.4 (updated) - fix for string lengths 2016-06-09 19:19:55 +01:00
1aa6c91e64 Fixed RNG issue with pre C++14 compilers 2016-06-09 19:07:05 +01:00
ac220289a6 v1.5.5:
Deal with auto_ptr and random_shuffle hard deprecations in C++14
2016-06-09 08:19:23 +01:00
be3570ef22 Use std::shuffle instead of (deprecated) std::random_shuffle if C++14 detected 2016-06-09 08:15:57 +01:00
a74d760d74 Switched remaining std::auto_ptrs to use CATCH_AUTO_PTR 2016-06-08 19:14:54 +01:00
f666f5f0ae v1.5.4 2016-05-12 19:18:04 +01:00
7940d58a2f "test" expression using !! instead of static_cast to bool.
This addresses #657 while (hopefully) maintaining fix for #574
2016-05-12 19:17:55 +01:00
ebf9f3bb9d v1.5.3 2016-05-10 19:09:59 +01:00
1ebebd4ab8 Merge branch 'rcdailey-throw-on-duplicate-tests' 2016-05-10 19:07:07 +01:00
b57e734eb4 Merge branch 'throw-on-duplicate-tests' of git://github.com/rcdailey/Catch into rcdailey-throw-on-duplicate-tests 2016-05-10 19:06:47 +01:00
5aa2b82b17 Merge pull request #656 from daniel-j-h/better_travis
Pins LLVM 3.8 (stable) instead of tracking the nightly repository
2016-05-07 23:19:26 +01:00
5c198d85e6 v1.5.2 2016-05-07 23:14:04 +01:00
5a6b291878 Using Clara 0.0.2.4 - fixes issue with spaces in quoted arguments 2016-05-07 23:12:46 +01:00
1706dd4f11 Pins LLVM 3.8 (stable) instead of tracking the nightly repository 2016-05-07 18:55:12 +02:00
92b141ee53 v1.5.1 2016-04-28 08:13:00 +01:00
4f1263d6b4 Removed use of dynamic_cast from test_case_tracker.
(Thanks to #631 and #648)
2016-04-28 08:11:12 +01:00
3b19458fed Removed use of dynamic_cast for MultipleReporters
(Thanks to #630, #636 and #648)
2016-04-28 08:11:12 +01:00
e5537842d0 Regenerated single include
(forgot for previously tagged release)
2016-04-25 18:56:50 +01:00
0fe303b6b7 v1.5.0 (due to new embedded Clara) 2016-04-23 13:25:51 +01:00
1c47fe023a Updated embedded Clara to 0.0.2.3
- has all new, more robust, token parsing.
- eliminates issue with unreachable code
- allows use of forward slashes to introduce short args on Windows
2016-04-23 13:21:29 +01:00
6f3bc629be Merge branch 'AzCopey-hotfix/override-warning' 2016-04-23 13:14:08 +01:00
6de7142d1f Merge pull request #634 from rafaeleyng/patch-1
Update tutorial.md
2016-04-05 18:23:22 +01:00
7544644bb4 Update tutorial.md
Closes #633
2016-04-04 23:04:45 -03:00
86c0ea2999 [#608] Don't use exit() on duplicate test descriptions
Instead of `exit(1)`, it now throws `std::runtime_error` with the details
of the failure. This exception is handled in `run()` at a higher level where
the log is printed to cerr and the test gracefully exits.
2016-04-01 11:56:51 -05:00
7075b7defb Added missing CATCH_OVERRIDE to CumulativeReporterBase::assertionEnded(). This fixes a warning when building in Xcode 7.2+ with default warning settings. 2016-03-29 17:03:09 +01:00
c984fc3ecd v1.4.0
- use __COUNTER__ for unique IDS instead of __LINE__ (where possible)
+ bug fixes
2016-03-15 07:24:26 +00:00
447f53e9e3 Fixed !shouldfail 2016-03-14 19:13:34 +00:00
13a887ad24 Use __COUNTER__ when generating unique names instead of __LINE__, if available.
Based on PR #351
2016-03-14 07:55:00 +00:00
02af70ed0b build v1.3.6 (include's David Grayson's fix for the gcc pragma) 2016-03-11 18:31:52 +00:00
c362894565 Merge branch 'DavidEGrayson-pr_gcc_pragma_typo' 2016-03-11 07:59:20 +00:00
97e335437e Fix CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS: GCC needs to be capitalized.
Fixes issue #600.
2016-03-04 19:24:10 -08:00
ae5ee2cf63 v1.3.5 2016-02-29 08:17:18 +00:00
f895e0d95f Rebased approvals following colour changes 2016-02-29 08:13:27 +00:00
458f37ed57 Merge branch 'explicit-bool-conversion' of git://github.com/seanmiddleditch/Catch into seanmiddleditch-explicit-bool-conversion 2016-02-29 08:05:46 +00:00
91bfe68a75 Suppress parentheses warnings on clang and gcc
- should address #593, #528, #521, #496 (and possibly others)
2016-02-29 08:03:48 +00:00
8ccb18daa9 Added --use-colour option to give finer control over colourisation.
--force-colour is still present but deprecated (will remove in v2)
2016-02-29 08:03:48 +00:00
dce2154474 Merge pull request #598 from luxe/patch-1
removes link to missing readme file
2016-02-27 17:06:57 +00:00
e52ad48fb7 removes link to missing readme file 2016-02-26 10:29:23 -05:00
776247af81 Support explicit operator bool
Fix for issue 596
2016-02-25 00:34:09 -08:00
3b4edd7a48 Build for v1.3.4 2016-02-10 19:24:48 +00:00
880a2046d9 Use Clara v0.0.1.1 2016-02-10 19:21:09 +00:00
ffad3a0a39 Fix as suggested in #574
Cast expression to bool to prevent custom && from defeating short-circuiting
2016-02-10 05:49:56 +00:00
3bd20bf2cd Removed reference to pre 1.0 release from README 2016-01-22 07:59:06 +00:00
c7243562b0 v1.3.3 2016-01-22 07:59:06 +00:00
b84e08ad6f Fix EndsWith Matcher (and refactored EndsWith and StartsWith in terms of endsWith and startsWith) (see Issue #573) 2016-01-22 07:59:06 +00:00
aca16a0f99 Fixed CATCH_REGISTER_TEST_CASE too 2016-01-22 07:50:10 +00:00
f294c98472 Fixed REGISTER_TEST_CASE for VS2013 (hopefully)
- see #549
2016-01-05 08:19:16 +00:00
7424b23bfb v1.3.1 2015-12-28 15:07:32 +00:00
dbd3a84d92 Fixed catch_with_main.hpp (no longer references deleted catch_runner.hpp) 2015-12-28 15:06:04 +00:00
5262e61e9d Approvals for Matcher change (added comma) 2015-12-10 18:43:29 +00:00
a5fba672e1 Add missing comma when in captured expression for matchers
Such that
CHECK_THAT( hex_encode(outbuf) Equals("B5D4045C") )
becomes
CHECK_THAT( hex_encode(outbuf), Equals("B5D4045C") )
2015-12-10 08:09:10 +00:00
2106d82881 Fixed non-variadic version of REGISTER_TEST_CASE 2015-12-09 18:24:29 +00:00
981347b6e4 patch build to include last two fixes 2015-12-09 18:11:48 +00:00
9e341231ba main takes args by non-const char*
- see #548
2015-12-09 06:22:15 +00:00
2b688e1cef Initialise m_currentSortOrder
- as reported in #545
2015-12-09 06:15:52 +00:00
84d1c080d6 Keep Xcode 7.1 happy 2015-12-04 10:21:07 +00:00
722315a1f5 Removed some trailing whitespace 2015-12-04 10:20:33 +00:00
fdc42d0af4 Merged from develop branch
- now v1.3.0
2015-12-04 10:19:08 +00:00
d274fc571c Added noexcept to CustomStdException destructor 2015-11-20 17:09:48 +00:00
7e15d9b20b dev build 4 2015-11-20 16:59:14 +00:00
0e64973f55 Added support for manually registering test functions.
As discussed in #421
2015-11-20 16:58:16 +00:00
e4fa62a14e dev build 3 2015-11-18 08:39:54 +00:00
a49f088032 exception translators considered even for types deriving from std::exception, now
- also added docs for exception translators
- updated approvals
2015-11-18 08:39:21 +00:00
ed6e9128a4 Session's argv now taken by char const* const*
- see #427
2015-11-18 07:57:24 +00:00
92356769f1 dev build 2 2015-11-06 18:07:29 +00:00
d10b73f9f1 changed Not struct to a class.
- it was forward declared as a class, which caused warnings on some compilers. It should really have been a class anyway.
- this addresses the same issue as PR #534, albeit from the other angle.
2015-11-06 18:07:29 +00:00
71fd2c2fdf Fixed test names mentioning the new Matcher combinator operators 2015-11-06 18:07:28 +00:00
08844e7e57 build 1.3.0-develop.1
I've incremented the minor release number. This is a slight abuse of semantic versioning so let me explain:
I've slightly changed how matchers are used. The matcher macro (REQUIRE_THAT/ CHECK_THAT) used to introduce the Catch::Matchers namespace before the macro token for the matcher, to save you having import the namespace yourself.
The trouble is if the matcher token is not a simple matcher (can now be an expression) this breaks!
So I've removed that qualification. Now if you use Matchers you'll have to do somethings like using namespace Catch::Matchers to bring them in.
This is a breaking change - but, OTTOH, Matchers are an undocumented "beta' feature that I've stated in the past is not guaranteed to have a stable API - so I don't think this warrants a major version change - but I did want to make it significant enough that people do notice that something is going on - and perhaps lead them to this commit message.
2015-11-05 18:52:18 +00:00
054e3c5b43 Added &&, || and ! operator overloads for matchers
(syntactic sugar for AllOf, AnyOf and Not compositional matchers, respectively)
2015-11-05 18:46:00 +00:00
f3e7722cc6 Don't introduce Catch::Matchers namespace in macro
- this could be a breaking change - fixed up self-test code to compensate
2015-11-05 18:10:33 +00:00
315c83ad87 Removed unnecessary parentheses 2015-11-04 18:49:19 +00:00
9576ad9108 Removed unused parameter
- as per PR #530
2015-11-04 18:11:54 +00:00
e91738103c Stripped trailing whitespace from all source code lines
(replaces need for PRs #310 and #504)
2015-11-04 18:04:15 +00:00
8c32b49d5f Added script to strip trailing whitespace from source files 2015-11-04 07:33:39 +00:00
ece529ae7c Fixed noexcept destructors issue 2015-11-03 17:37:43 +00:00
9e42153fe5 dev build 16 2015-11-03 17:06:54 +00:00
c81778ecd0 Fixed CMake file
(changed SectionTrackerTests.cpp - now deleted - to the new PartTrackerTests.cpp)
2015-11-03 17:06:24 +00:00
f5642be7b4 Fixed reversed logic of NoAssertions warning check
(that explains the previous regressions)
2015-11-03 17:05:08 +00:00
7e34619f03 v1.2.1-develop.15
- includes all new section tracker
2015-11-03 08:01:27 +00:00
4636be9744 Merge branch 'NewSectionTracking' into develop
* NewSectionTracking:
  Added SUCCEEDs to empty leaf sections to avoid failing due to no assertions
  Removed deprecated section tracking implementation and tests
  Approved changes due to "No assertions" warnings now firing correctly on inner sections
  perform startRun() at the start of each test case
  Fitted new section tracking
  Converted all new part tracking tests/ sections to non variadic form
  Moved all new tracking impl into catch_test_case_tracker.pp
  Removed the "part" component of the tracker names
  More minor tweaks
  Added tests for failing a section within a generator - small fixes to implementation to make it work
  more minor clean-ups
  Cleaned tests up a bit
  Added IndexTracker and got it working with a single generator - made some simplifications to state machine
  More name changes
  Tweaks
  First cut of new section/ part tracking
  Refactored stream related stuff - simpler, polymorphic hierarchy-based, approach - less bitty conditionals spread across the code - all resolved up-front so now config class is immutable (it had evolved the way it was and in need of a clean-up sweep for a long time)
  Some small clean-ups and refactorings - removed previous instance saves in RunContext (they were a hang-over from embedded contexts) - started cleaning up config usage
2015-11-03 07:55:29 +00:00
015e07100e Added SUCCEEDs to empty leaf sections to avoid failing due to no assertions 2015-11-03 07:46:37 +00:00
bc8840cbb8 Removed deprecated section tracking implementation and tests 2015-11-03 07:38:14 +00:00
471bd2556a Approved changes due to "No assertions" warnings now firing correctly on inner sections 2015-11-03 07:33:43 +00:00
aa49823bc0 perform startRun() at the start of each test case 2015-11-03 07:29:23 +00:00
52a417df7b Fitted new section tracking 2015-11-02 19:21:46 +00:00
0b523db6b9 Converted all new part tracking tests/ sections to non variadic form 2015-11-02 06:16:09 +00:00
b8515929b8 Moved all new tracking impl into catch_test_case_tracker.pp 2015-11-02 06:14:52 +00:00
3deb3e010f Removed the "part" component of the tracker names 2015-10-29 19:41:50 +00:00
73a140fb9e More minor tweaks 2015-10-29 19:33:25 +00:00
ef62b578e2 Added tests for failing a section within a generator
- small fixes to implementation to make it work
2015-10-29 19:25:27 +00:00
f4389b4fdb more minor clean-ups 2015-10-29 08:33:50 +00:00
4b99be6a9a Cleaned tests up a bit 2015-10-29 08:17:55 +00:00
293e54dcbe Added IndexTracker and got it working with a single generator
- made some simplifications to state machine
2015-10-29 08:02:40 +00:00
d758428fe2 Merge pull request #523 from nabijaczleweli/patch-1
Fix typo in catch_stream.hpp
2015-10-26 14:47:29 +00:00
9a6a0865f2 More name changes 2015-10-23 18:44:48 +01:00
2c6411e70a Tweaks 2015-10-23 18:34:16 +01:00
1cb993970a First cut of new section/ part tracking 2015-10-23 18:20:33 +01:00
bc00d59a4e Fix typo in catch_stream.hpp 2015-10-22 21:49:32 +02:00
b3b2352045 Fixed some missing sentence structure
Thanks to #517
2015-10-19 09:16:16 +01:00
c9a188df45 Merge pull request #512 from daniel-j-h/better_travis
Improves the Travis CI integration
2015-10-07 15:12:17 +01:00
e904aa7f6e Improve the Travis CI integration.
Adding several improvements, such as:

- making use of the container based infrastructure
- using ccache for faster building
- builds for linux, osx
- builds for verious gcc, clang versions
- recent cmake installation
2015-10-06 12:28:18 +02:00
d43a47efca Refactored stream related stuff
- simpler, polymorphic hierarchy-based, approach
- less bitty conditionals spread across the code
- all resolved up-front so now config class is immutable
(it had evolved the way it was and in need of a clean-up sweep for a long time)
2015-09-29 19:23:06 +01:00
a0de07d45b Some small clean-ups and refactorings
- removed previous instance saves in RunContext (they were a hang-over from embedded contexts)
- started cleaning up config usage
2015-09-28 01:09:06 -07:00
0c1c9fa922 dev build 14
- workaround for uncaught_exception issue
- avoid mutating vector while iterating it (due to re-entrancy)
2015-09-27 03:28:14 -07:00
166ca2e819 Do uncaught_exception checking before calling sectionEnded
- split the uncaught handling (adding to unfinishedSections) into separate method
2015-09-26 18:12:21 -07:00
15317632f3 Revert "Fix parentheses warning on expression evaluation when using ccache"
This reverts commit 7da777a4b7.
2015-09-26 18:06:53 -07:00
a28d40e941 Merge pull request #496 from segalaj/master
Fix parentheses warning on expression evaluation when using ccache
2015-09-18 08:12:56 +01:00
7da777a4b7 Fix parentheses warning on expression evaluation when using ccache 2015-09-14 14:28:34 +02:00
d234ed1a67 dev build 13 2015-08-24 06:28:25 +01:00
7fd7c5b8c8 Merge branch 'matcher-not' into develop
* matcher-not:
  Add matcher: Not()
2015-08-24 06:22:03 +01:00
312b94e532 Add matcher: Not() 2015-08-12 11:07:55 +02:00
40d0d2f656 Added unique_ptr detection to compiler_capabilities
- as well as use by C++11 conformant compilers now enabled for VS2013 on too (see #479)
- updated docs with this (and long long and override support)
2015-08-11 08:09:41 +01:00
19520157fb regen single header 2015-08-10 07:32:48 +01:00
ad7edd0680 Replaced some stray overrides with CATCH_OVERRIDE 2015-08-10 07:32:21 +01:00
8a05f46a37 Removed use of std::copy_if (as it's limited to c++11) 2015-08-07 17:53:29 +01:00
e73583d556 dev build 12 2015-08-07 17:30:34 +01:00
afcc38efc5 Fixes for single include 2015-08-07 17:28:48 +01:00
368714e7aa Added Listeners (programatically provided extra reporters) 2015-08-07 08:20:56 +01:00
4cb74761d9 Support for multiple reporters
- can't (yet) specify different targets for each reporter (e.g. different files)
2015-08-05 19:02:17 +01:00
c06e1909ae Refactored test filtering and sorting 2015-08-04 23:11:56 +01:00
8b1b7cd66e dev build 11 2015-08-03 07:40:52 +01:00
34fa25ed2f Removed Runner class
- it served no purpose - split into functions instead
2015-07-28 18:55:11 +01:00
85c8074784 Set group name to -n parameter (or exe name)
- As discussed in #469
2015-07-28 18:26:09 +01:00
0edebf41b0 approvals rebase
- I *think* this fixes an earlier regression, but I'm not 100% sure where that came from!
2015-07-28 18:24:20 +01:00
f3308ed7c4 Let gcc use __cplusplus identifier to decide if nullptr supported
- or, for 4.6, continue to check __GX_EXPERIMENTAL_CXX0X__
See GitHb issue #445 and PR #471
2015-07-27 18:42:36 +01:00
74eef52644 dev build 10 2015-07-24 08:13:52 +01:00
e085d4811a Qualified path to xmlwriter to fix travis error 2015-07-24 08:13:07 +01:00
1dd0d4c61a Force cout/ cerr to be initialised before errors in test registry are printed
- see #461
2015-07-10 07:46:19 +01:00
168 changed files with 17828 additions and 16683 deletions

8
.gitignore vendored
View File

@ -14,9 +14,15 @@ Breakpoints.xcbkptlist
projects/VS2010/TestCatch/_UpgradeReport_Files/
projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters
projects/VisualStudio/TestCatch/UpgradeLog.XML
projects/CMake/.idea
projects/CMake/cmake-build-debug
UpgradeLog.XML
Resources/DWARF
projects/XCode/iOSTest/Build
projects/Generated
*.pyc
DerivedData
*.xccheckout
Build
.idea
cmake-build-debug
cmake-build-release

View File

@ -1,19 +1,163 @@
language: cpp
sudo: false
compiler:
- clang
- gcc
cache:
ccache: true
directories:
- $HOME/.ccache
env:
- BUILD_TYPE=Debug
- BUILD_TYPE=Release
global:
- USE_CCACHE=1
- CCACHE_COMPRESS=1
- CCACHE_MAXSIZE=200M
- CCACHE_CPP2=1
matrix:
include:
# 1/ Linux Clang Builds
- os: linux
compiler: clang
addons: &clang35
apt:
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test']
packages: ['clang-3.5']
env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Release'
- os: linux
compiler: clang
addons: *clang35
env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang36
apt:
sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test']
packages: ['clang-3.6']
env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Release'
- os: linux
compiler: clang
addons: *clang36
env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang37
apt:
sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test']
packages: ['clang-3.7']
env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Release'
- os: linux
compiler: clang
addons: *clang37
env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang38
apt:
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
packages: ['clang-3.8']
env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Release'
- os: linux
compiler: clang
addons: *clang38
env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Debug'
# 2/ Linux GCC Builds
- os: linux
compiler: gcc
addons: &gcc48
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8']
env: COMPILER='ccache g++-4.8' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: *gcc48
env: COMPILER='ccache g++-4.8' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc49
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9']
env: COMPILER='ccache g++-4.9' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: *gcc49
env: COMPILER='ccache g++-4.9' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env: COMPILER='ccache g++-5' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: *gcc5
env: COMPILER='ccache g++-5' BUILD_TYPE='Debug'
# 3/ OSX Clang Builds
- os: osx
osx_image: xcode7
compiler: clang
env: COMPILER='ccache clang++' BUILD_TYPE='Debug'
- os: osx
osx_image: xcode7
compiler: clang
env: COMPILER='ccache clang++' BUILD_TYPE='Release'
- os: osx
osx_image: xcode8
compiler: clang
env: COMPILER='ccache clang++' BUILD_TYPE='Debug'
- os: osx
osx_image: xcode8
compiler: clang
env: COMPILER='ccache clang++' BUILD_TYPE='Release'
install:
- cmake -Hprojects/CMake -BBuild -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz"
mkdir cmake && travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
which cmake || brew install cmake
which ccache || brew install ccache
fi
before_script:
- export CXX=${COMPILER}
- cd ${TRAVIS_BUILD_DIR}
- cmake -H. -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -Wdev
- cd Build
- make
- cd ..
script:
- cd Build
- ctest -V
- make -j 2
- ctest -V -j 2

239
CMakeLists.txt Normal file
View File

@ -0,0 +1,239 @@
cmake_minimum_required(VERSION 2.8)
project(CatchSelfTest)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# define some folders
set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
set(HEADER_DIR ${CATCH_DIR}/include)
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}")
elseif(USE_CPP14)
message(STATUS "Enabling C++14")
set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
endif()
#checks that the given hard-coded list contains all headers + sources in the given folder
function(CheckFileList LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
function(CheckFileListRec LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
# define the sources of the self test
# Please keep these ordered alphabetically
set(TEST_SOURCES
${SELF_TEST_DIR}/ApproxTests.cpp
${SELF_TEST_DIR}/BDDTests.cpp
${SELF_TEST_DIR}/ClassTests.cpp
${SELF_TEST_DIR}/CmdLineTests.cpp
${SELF_TEST_DIR}/ConditionTests.cpp
${SELF_TEST_DIR}/EnumToString.cpp
${SELF_TEST_DIR}/ExceptionTests.cpp
${SELF_TEST_DIR}/GeneratorTests.cpp
${SELF_TEST_DIR}/MessageTests.cpp
${SELF_TEST_DIR}/MiscTests.cpp
${SELF_TEST_DIR}/PartTrackerTests.cpp
${SELF_TEST_DIR}/TagAliasTests.cpp
${SELF_TEST_DIR}/TestMain.cpp
${SELF_TEST_DIR}/ToStringPair.cpp
${SELF_TEST_DIR}/ToStringTuple.cpp
${SELF_TEST_DIR}/ToStringVector.cpp
${SELF_TEST_DIR}/ToStringWhich.cpp
${SELF_TEST_DIR}/TrickyTests.cpp
${SELF_TEST_DIR}/VariadicMacrosTests.cpp
)
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
# A set of impl files that just #include a single header
# Please keep these ordered alphabetically
set(IMPL_SOURCES
${SELF_TEST_DIR}/SurrogateCpps/catch_common.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_generators.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_registry_hub.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_message.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_ptr.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
)
CheckFileList(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
# Please keep these ordered alphabetically
set(TOP_LEVEL_HEADERS
${HEADER_DIR}/catch.hpp
${HEADER_DIR}/catch_session.hpp
${HEADER_DIR}/catch_with_main.hpp
)
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
# Please keep these ordered alphabetically
set(EXTERNAL_HEADERS
${HEADER_DIR}/external/clara.h
${HEADER_DIR}/external/tbc_text_format.h
)
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
# Please keep these ordered alphabetically
set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_approx.hpp
${HEADER_DIR}/internal/catch_assertionresult.h
${HEADER_DIR}/internal/catch_assertionresult.hpp
${HEADER_DIR}/internal/catch_capture.hpp
${HEADER_DIR}/internal/catch_clara.h
${HEADER_DIR}/internal/catch_commandline.hpp
${HEADER_DIR}/internal/catch_common.h
${HEADER_DIR}/internal/catch_common.hpp
${HEADER_DIR}/internal/catch_compiler_capabilities.h
${HEADER_DIR}/internal/catch_config.hpp
${HEADER_DIR}/internal/catch_console_colour.hpp
${HEADER_DIR}/internal/catch_console_colour_impl.hpp
${HEADER_DIR}/internal/catch_context.h
${HEADER_DIR}/internal/catch_context_impl.hpp
${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_debugger.hpp
${HEADER_DIR}/internal/catch_default_main.hpp
${HEADER_DIR}/internal/catch_evaluate.hpp
${HEADER_DIR}/internal/catch_exception_translator_registry.hpp
${HEADER_DIR}/internal/catch_expression_lhs.hpp
${HEADER_DIR}/internal/catch_fatal_condition.hpp
${HEADER_DIR}/internal/catch_generators.hpp
${HEADER_DIR}/internal/catch_generators_impl.hpp
${HEADER_DIR}/internal/catch_impl.hpp
${HEADER_DIR}/internal/catch_interfaces_capture.h
${HEADER_DIR}/internal/catch_interfaces_config.h
${HEADER_DIR}/internal/catch_interfaces_exception.h
${HEADER_DIR}/internal/catch_interfaces_generators.h
${HEADER_DIR}/internal/catch_interfaces_registry_hub.h
${HEADER_DIR}/internal/catch_interfaces_reporter.h
${HEADER_DIR}/internal/catch_interfaces_runner.h
${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h
${HEADER_DIR}/internal/catch_interfaces_testcase.h
${HEADER_DIR}/internal/catch_legacy_reporter_adapter.h
${HEADER_DIR}/internal/catch_legacy_reporter_adapter.hpp
${HEADER_DIR}/internal/catch_list.hpp
${HEADER_DIR}/internal/catch_matchers.hpp
${HEADER_DIR}/internal/catch_message.h
${HEADER_DIR}/internal/catch_message.hpp
${HEADER_DIR}/internal/catch_notimplemented_exception.h
${HEADER_DIR}/internal/catch_notimplemented_exception.hpp
${HEADER_DIR}/internal/catch_objc.hpp
${HEADER_DIR}/internal/catch_objc_arc.hpp
${HEADER_DIR}/internal/catch_option.hpp
${HEADER_DIR}/internal/catch_platform.h
${HEADER_DIR}/internal/catch_ptr.hpp
${HEADER_DIR}/internal/catch_reenable_warnings.h
${HEADER_DIR}/internal/catch_registry_hub.hpp
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
${HEADER_DIR}/internal/catch_reporter_registry.hpp
${HEADER_DIR}/internal/catch_result_builder.h
${HEADER_DIR}/internal/catch_result_builder.hpp
${HEADER_DIR}/internal/catch_result_type.h
${HEADER_DIR}/internal/catch_run_context.hpp
${HEADER_DIR}/internal/catch_section.h
${HEADER_DIR}/internal/catch_section.hpp
${HEADER_DIR}/internal/catch_section_info.h
${HEADER_DIR}/internal/catch_section_info.hpp
${HEADER_DIR}/internal/catch_stream.h
${HEADER_DIR}/internal/catch_stream.hpp
${HEADER_DIR}/internal/catch_streambuf.h
${HEADER_DIR}/internal/catch_suppress_warnings.h
${HEADER_DIR}/internal/catch_tag_alias.h
${HEADER_DIR}/internal/catch_tag_alias_registry.h
${HEADER_DIR}/internal/catch_tag_alias_registry.hpp
${HEADER_DIR}/internal/catch_test_case_info.h
${HEADER_DIR}/internal/catch_test_case_info.hpp
${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp
${HEADER_DIR}/internal/catch_test_case_tracker.hpp
${HEADER_DIR}/internal/catch_test_registry.hpp
${HEADER_DIR}/internal/catch_test_spec.hpp
${HEADER_DIR}/internal/catch_test_spec_parser.hpp
${HEADER_DIR}/internal/catch_text.h
${HEADER_DIR}/internal/catch_timer.h
${HEADER_DIR}/internal/catch_timer.hpp
${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_tostring.hpp
${HEADER_DIR}/internal/catch_totals.hpp
${HEADER_DIR}/internal/catch_version.h
${HEADER_DIR}/internal/catch_version.hpp
${HEADER_DIR}/internal/catch_wildcard_pattern.hpp
${HEADER_DIR}/internal/catch_windows_h_proxy.h
${HEADER_DIR}/internal/catch_xmlwriter.hpp
)
CheckFileList(INTERNAL_HEADERS ${HEADER_DIR}/internal)
# Please keep these ordered alphabetically
set(REPORTER_HEADERS
${HEADER_DIR}/reporters/catch_reporter_bases.hpp
${HEADER_DIR}/reporters/catch_reporter_compact.hpp
${HEADER_DIR}/reporters/catch_reporter_console.hpp
${HEADER_DIR}/reporters/catch_reporter_junit.hpp
${HEADER_DIR}/reporters/catch_reporter_multi.hpp
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
${HEADER_DIR}/reporters/catch_reporter_xml.hpp
)
CheckFileList(REPORTER_HEADERS ${HEADER_DIR}/reporters)
# Specify the headers, too, so CLion recognises them as project files
set(HEADERS
${TOP_LEVEL_HEADERS}
${EXTERNAL_HEADERS}
${INTERNAL_HEADERS}
${REPORTER_HEADERS}
)
# Provide some groupings for IDEs
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
SOURCE_GROUP("Surrogates" FILES ${IMPL_SOURCES})
# configure the executable
include_directories(${HEADER_DIR})
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${HEADERS})
# configure unit tests via CTest
enable_testing()
add_test(NAME RunTests COMMAND SelfTest)
add_test(NAME ListTests COMMAND SelfTest --list-tests)
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
add_test(NAME ListTags COMMAND SelfTest --list-tags)
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")

View File

@ -1,12 +1,10 @@
![catch logo](catch-logo-small.png)
*v1.2.1-develop.9*
*v1.6.1*
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch)
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](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/master/single_include/catch.hpp">[The latest, single header, version can be downloaded directly using this link]</a>
<a href="https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
## What's the Catch?
@ -19,8 +17,6 @@ This documentation comprises these three parts:
* [Tutorial](docs/tutorial.md) - getting started
* [Reference section](docs/Readme.md) - all the details
The documentation will continue until morale improves
## More
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)

BIN
catch-logo-tiny.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -16,5 +16,5 @@ Before looking at this material be sure to read the [tutorial](tutorial.md)
Other
* [Why Catch?](why-catch.md)
* [What's changed](whats-changed.md)
* [Contributing](contributing.md)
* [Release Notes](release-notes.md)

View File

@ -66,6 +66,8 @@ A series of tags form an AND expression wheras a comma-separated sequence forms
<pre>[one][two],[three]</pre>
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
Test names containing special characters, such as `,` or `[` can specify them on the command line using `\`.
`\` also escapes itself.
<a id="choosing-a-reporter-to-use"></a>
## Choosing a reporter to use
@ -115,7 +117,7 @@ Sometimes this results in a flood of failure messages and you'd rather just see
--list-reporters
</pre>
```-l``` or ```--list-tests`` will list all registered tests, along with any tags.
```-l``` or ```--list-tests``` will list all registered tests, along with any tags.
If one or more test-specs have been supplied too then only the matching tests will be listed.
```-t``` or ```--list-tags``` lists all available tags, along with the number of test cases they match. Again, supplying test specs limits the tags that match.
@ -217,4 +219,4 @@ Prints the command line arguments to stdout
---
[Home](Readme.md)
[Home](Readme.md)

View File

@ -58,6 +58,10 @@ This can be useful on certain platforms that do not provide ```std::cout``` and
CATCH_CONFIG_CPP11_IS_ENUM // std::is_enum is supported?
CATCH_CONFIG_CPP11_TUPLE // std::tuple is supported
CATCH_CONFIG_VARIADIC_MACROS // Usually pre-C++11 compiler extensions are sufficient
CATCH_CONFIG_CPP11_LONG_LONG // generates overloads for the long long type
CATCH_CONFIG_CPP11_OVERRIDE // CATCH_OVERRIDE expands to override (for virtual function implementations)
CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr
CATCH_CONFIG_CPP11_SHUFFLE // Use std::shuffle instead of std::random_shuffle
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.
@ -65,6 +69,13 @@ You may also suppress any of these features by using the `_NO_` form, e.g. `CATC
All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11`
# Windows header clutter
On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros:
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
---
[Home](Readme.md)
[Home](Readme.md)

View File

@ -1,22 +1,40 @@
# Contributing to Catch
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated. Of course so are bug reports and other comments and questions.
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated.
Of course so are bug reports and other comments and questions.
If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull request for this file, if you notice that.
If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to
help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull
request for this file, if you notice that.
## Branches
Ongoing development is on the "develop" branch (if there is one, currently), or on feature branches that are branched off of develop. Please target any pull requests at develop, or, for larger chunks of work, a branch off of develop.
Ongoing development is currently on _master_. At some point an integration branch will be set-up and PRs should target
that - but for now it's all against master. You may see feature branches come and go from time to time, too.
## Directory structure
Users of Catch primarily use the single header version. Maintainers should work with the full source (which is still, primarily, in headers). This can be found in the ```include``` folder, but you may prefer to use one of the IDE project files (for MSVC or XCode). These can be found under ```projects/```*IDE Name*```/```*project name*. A number of contributors have proposed make files, and submitted their own versions. At some point these should be made available too.
_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still,
primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under
`projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate
project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion
that can work with the CMake file directly.
In addition to the include files and IDE projects there are a number of tests in cpp files. These can all be found in ```projects/SelfTest```. You'll also see a ```SurrogateCpps``` directory in there. This contains a set of cpp files that each ```#include``` a single header. While these files are not essential to compilation they help to keep the implementation headers self-contained. At time of writing this set is not complete but has reasonable coverage. If you add additional headers please try to remember to add a surrogate cpp for it.
As well as the runtime test files you'll also see a `SurrogateCpps` directory under `projects/SelfTest`.
This contains a set of .cpp files that each `#include` a single header.
While these files are not essential to compilation they help to keep the implementation headers self-contained.
At time of writing this set is not complete but has reasonable coverage.
If you add additional headers please try to remember to add a surrogate cpp for it.
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.
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 in-progress...*
__When submitting a pull request please do not include changes to the single include, or to the version number file
as these are managed by the scripts!__
*this document is still in-progress...*
---

View File

@ -16,7 +16,7 @@ If you just need to have code that executes before and/ or after Catch this is t
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
int main( int argc, char* const argv[] )
int main( int argc, char* argv[] )
{
// global setup...
@ -36,9 +36,9 @@ If you still want Catch to process the command line, but you want to programatic
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
int main( int argc, char* const argv[] )
int main( int argc, char* argv[] )
{
Catch::Session session; // There must be exactly once instance
Catch::Session session; // There must be exactly one instance
// writing to session.configData() here sets defaults
// this is the preferred way to set them
@ -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)

48
docs/release-notes.md Normal file
View File

@ -0,0 +1,48 @@
# 1.6.1
### Features/ Changes:
* Catch now supports breaking into debugger on Linux
### Fixes:
* Generators no longer leak memory (generators are still unsupported in general)
* JUnit reporter now reports UTC timestamps, instead of "tbd"
* `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros
### Other:
* Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
* The use of `__COUNTER__` is supressed when Catch is parsed by CLion
* This change is not active when compiling a binary
* Approval tests can now be run on Windows
* CMake will now warn if a file is present in the `include` folder but not is not enumerated as part of the project
* Catch now defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including `windows.h`
* This can be disabled if needed, see [documentation](docs/configuration.md) for details.
# Older versions
Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
## 1.6.0
### Cmake/ projects:
* Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects.
### Features/ Changes:
* Approx now supports `>=` and `<=`
* Can now use `\` to escape chars in test names on command line
* Standardize C++11 feature toggles
### Fixes:
* Blue shell colour
* Missing argument to `CATCH_CHECK_THROWS`
* Don't encode extended ASCII in XML
* use `std::shuffle` on more compilers (fixes deprecation warning/error)
* Use `__COUNTER__` more consistently (where available)
### Other:
* Tweaks and changes to scripts - particularly for Approval test - to make them more portable
---
[Home](Readme.md)

View File

@ -2,7 +2,7 @@
While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style.
Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#testCasesAndSections).
Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#test-cases-and-sections).
Test cases and sections are very easy to use in practice:
@ -34,9 +34,9 @@ Tag names are not case sensitive.
All tag names beginning with non-alphanumeric characters are reserved by Catch. Catch defines a number of "special" tags, which have meaning to the test runner itself. These special tags all begin with a symbol character. Following is a list of currently defined special tags and their meanings.
* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them.
* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them.
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be exluded when running with `-e` or `--nothrow`.
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
* `[!shouldfail]` - reverse the failing logic of the test: if the test is successful if it fails, and vice-versa.
@ -52,7 +52,7 @@ Between tag expressions and wildcarded test names (as well as combinations of th
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
Aliases must begining with the `@` character. An example of a tag alias is:
Aliases must begin with the `@` character. An example of a tag alias is:
CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
@ -83,4 +83,4 @@ Other than the additional prefixes and the formatting in the console reporter th
---
[Home](Readme.md)
[Home](Readme.md)

View File

@ -1,4 +1,4 @@
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:
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:
```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)

View File

@ -55,6 +55,16 @@ namespace Catch {
}
```
## Exceptions
By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example:
```
CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
return ex.message();
}
```
---
[Home](Readme.md)

View File

@ -1,6 +1,6 @@
# Getting Catch
The simplest way to get Catch is to download the single header version from [http://builds.catch-lib.net](http://builds.catch-lib.net). Don't be put off by the word "builds" there. The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
The simplest way to get Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
The full source for Catch, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
@ -96,7 +96,7 @@ Although this was a simple test it's been enough to demonstrate a few things abo
Most test frameworks have a class-based fixture mechanism. That is, test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages, like C++, that support deterministic destruction).
While Catch fully supports this way of working there are a few problems with the approach. In particular, the way your code must be split up and the blunt granularity of cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>).
While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>).
Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example:
@ -233,7 +233,7 @@ The requirement is that the following block of code ([or equivalent](own-main.md
appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```!
In fact it is usually a good idea to put the block with the ```#define``` [in it's own source file](slow-compiles.md).
In fact it is usually a good idea to put the block with the ```#define``` [in its own source file](slow-compiles.md).
Do not write your tests in header files!

View File

@ -1,24 +0,0 @@
## What's new in Catch for 1.0
After a long "developer preview" state Catch turned 1.0 in mid-2013. Just prior to this a large number of changes, some of them breaking, where merged from the integration branch and now form part of the 1.0 code-base. If this might affect you please read this summary through so you know what to expect.
* Calling Catch from your own ```main()``` has changed - please review [the updated docs](own-main.md)
* The command line has changed. The biggest change is that test case names and tags should now only be supplied as primary arguments - in fact the ```-t``` option has been repurposed to mean "list tags". There are [updated docs for this too](command-line.md)
* There is a new reporter interface. If you have written a custom reporter you can use the ```LegacyReporterAdapter``` to minimise any differences. Ideally you should update to the new interface - especially as it has been designed to be more robust in the face of future changes (which should be minimal).
* The docs have moved from the wiki to the repository itself. They consist of a set of markdown files in the docs folder and are referenced directly from the README in the root. You can still read them online from GitHub.
* Lots of new goodness - more documentation for which is coming. The existing docs have been updated to account for some of the changes already (e.g. variadic macros). A quick rundown:
* Variadic macros are used, where possible, so that, e.g. you can write a ```TEST_CASE``` with just a name - or even no name at all (making it an anonymous test case).
* The hierarchical naming convention is deprecated in favour of using tags (see next)
* ```TEST_CASE```s (but not ```SECTION```s) can now be tagged by placing keywords in square brackets in the second argument - e.g.: ```TEST_CASE( "A nice name", "[tag1][tag2]")```. The old style is still supported but please consider using this new style.
* Tests can still be "hidden" using the ```./``` prefix as before, but the preferred way now is to give it the ```[hide]``` tag (hidden tests are skipped if you run the test process without specifying any test specs).
* As well as ```TEST_CASE```s and ```SECTION```s you can now also use BDD-style ```SCENARIO``` (in place of ```TEST_CASE```) and ```GIVEN```, ```WHEN``` and ```THEN``` macros (in place of ```SECTION```s).
* New command line parser. Under the hood it is a complete rewrite - now powered by a command line library that will soon be spun out as a separate project: Clara. The options themselves are largely the same but there are some notable differences (as already discussed).
* Completely overhauled output from the textual reporter (now the Console reporter). This now features a much clearer, cleaner format, including good use of indentation.
More information can be found in [this blog post](http://www.levelofindirection.com/journal/2013/6/28/catch-10.html).
If you find any issues please raise issue tickets on the [issue tracker on GitHub](https://github.com/philsquared/Catch/issues) as before. For general questions, comments and suggestions, though, please use the [new forums on Google Groups](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
---
[Home](Readme.md)

View File

@ -81,12 +81,12 @@
#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
@ -99,6 +99,7 @@
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
@ -106,6 +107,7 @@
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
@ -166,6 +168,7 @@
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
@ -173,6 +176,7 @@
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )

View File

@ -10,7 +10,7 @@
#include "internal/catch_commandline.hpp"
#include "internal/catch_list.hpp"
#include "internal/catch_runner_impl.hpp"
#include "internal/catch_run_context.hpp"
#include "internal/catch_test_spec.hpp"
#include "internal/catch_version.h"
#include "internal/catch_text.h"
@ -21,96 +21,75 @@
namespace Catch {
class Runner {
Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
if( !reporter ) {
std::ostringstream oss;
oss << "No reporter registered with name: '" << reporterName << "'";
throw std::domain_error( oss.str() );
}
return reporter;
}
public:
Runner( Ptr<Config> const& config )
: m_config( config )
{
openStream();
makeReporter();
Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
std::vector<std::string> reporters = config->getReporterNames();
if( reporters.empty() )
reporters.push_back( "console" );
Ptr<IStreamingReporter> reporter;
for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
it != itEnd;
++it )
reporter = addReporter( reporter, createReporter( *it, config ) );
return reporter;
}
Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
it != itEnd;
++it )
reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
return reporters;
}
Totals runTests( Ptr<Config> const& config ) {
Ptr<IConfig const> iconfig = config.get();
Ptr<IStreamingReporter> reporter = makeReporter( config );
reporter = addListeners( iconfig, reporter );
RunContext context( iconfig, reporter );
Totals totals;
context.testGroupStarting( config->name(), 1, 1 );
TestSpec testSpec = config->testSpec();
if( !testSpec.hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
it != itEnd;
++it ) {
if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
totals += context.runTest( *it );
else
reporter->skipTest( *it );
}
Totals runTests() {
context.testGroupEnded( iconfig->name(), totals, 1, 1 );
return totals;
}
RunContext context( m_config.get(), m_reporter );
Totals totals;
context.testGroupStarting( "all tests", 1, 1 ); // deprecated?
TestSpec testSpec = m_config->testSpec();
if( !testSpec.hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
std::vector<TestCase> testCases;
getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
int testsRunForGroup = 0;
for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
it != itEnd;
++it ) {
testsRunForGroup++;
if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
if( context.aborting() )
break;
totals += context.runTest( *it );
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;
}
private:
void openStream() {
// Open output file, if specified
if( !m_config->getFilename().empty() ) {
m_ofs.open( m_config->getFilename().c_str() );
if( m_ofs.fail() ) {
std::ostringstream oss;
oss << "Unable to open file: '" << m_config->getFilename() << "'";
throw std::domain_error( oss.str() );
}
m_config->setStreamBuf( m_ofs.rdbuf() );
}
}
void makeReporter() {
std::string reporterName = m_config->getReporterName().empty()
? "console"
: m_config->getReporterName();
m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
if( !m_reporter ) {
std::ostringstream oss;
oss << "No reporter registered with name: '" << reporterName << "'";
throw std::domain_error( oss.str() );
}
}
private:
Ptr<Config> m_config;
std::ofstream m_ofs;
Ptr<IStreamingReporter> m_reporter;
std::set<TestCase> m_testsAlreadyRun;
};
void applyFilenamesAsTags() {
std::vector<TestCase> const& tests = getRegistryHub().getTestCaseRegistry().getAllTests();
void applyFilenamesAsTags( IConfig const& config ) {
std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
for(std::size_t i = 0; i < tests.size(); ++i ) {
TestCase& test = const_cast<TestCase&>( tests[i] );
std::set<std::string> tags = test.tags;
std::string filename = test.lineInfo.file;
std::string::size_type lastSlash = filename.find_last_of( "\\/" );
if( lastSlash != std::string::npos )
@ -119,7 +98,7 @@ namespace Catch {
std::string::size_type lastDot = filename.find_last_of( "." );
if( lastDot != std::string::npos )
filename = filename.substr( 0, lastDot );
tags.insert( "#" + filename );
setTags( test, tags );
}
@ -152,10 +131,10 @@ namespace Catch {
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 ) {
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try {
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
if( m_configData.showHelp )
showHelp( m_configData.processName );
m_config.reset();
@ -179,7 +158,7 @@ namespace Catch {
m_config.reset();
}
int run( int argc, char* const argv[] ) {
int run( int argc, char const* const* const argv ) {
int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 )
@ -195,18 +174,16 @@ namespace Catch {
{
config(); // Force config to be constructed
if( m_configData.filenamesAsTags )
applyFilenamesAsTags();
seedRng( *m_config );
Runner runner( m_config );
if( m_configData.filenamesAsTags )
applyFilenamesAsTags( *m_config );
// Handle list request
if( Option<std::size_t> listed = list( config() ) )
return static_cast<int>( *listed );
return static_cast<int>( runner.runTests().assertions.failed );
return static_cast<int>( runTests( m_config ).assertions.failed );
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;
@ -228,7 +205,6 @@ namespace Catch {
m_config = new Config( m_configData );
return *m_config;
}
private:
Clara::CommandLine<ConfigData> m_cli;
std::vector<Clara::Parser::Token> m_unusedTokens;

View File

@ -8,8 +8,7 @@
#ifndef TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED
#include "catch_runner.hpp"
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "internal/catch_default_main.hpp"
#endif // TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED

View File

@ -6,6 +6,8 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
// Version 0.0.2.4
// Only use header guard if we are not using an outer namespace
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
@ -38,6 +40,7 @@
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
// Use optional outer namespace
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
@ -172,16 +175,179 @@ namespace Tbc {
#endif // TBC_TEXT_FORMAT_H_INCLUDED
// ----------- end of #include from tbc_text_format.h -----------
// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
// ........... back in clara.h
#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
// ----------- #included from clara_compilers.h -----------
/*
* Created by Phil on 10/02/2016.
* Copyright 2016 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_CLARA_COMPILERS_H_INCLUDED
#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
// The following features are defined:
//
// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// In general each macro has a _NO_<feature name> form
// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
// Many features, at point of detection, define an _INTERNAL_ macro, so they
// can be combined, en-mass, with the _NO_ forms later.
// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
#ifdef __clang__
#if __has_feature(cxx_nullptr)
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
#endif
#if __has_feature(cxx_noexcept)
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
#endif
#endif // __clang__
////////////////////////////////////////////////////////////////////////////////
// GCC
#ifdef __GNUC__
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
#endif
// - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below
#endif // __GNUC__
////////////////////////////////////////////////////////////////////////////////
// Visual C++
#ifdef _MSC_VER
#if (_MSC_VER >= 1600)
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
#endif
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
#endif
#endif // _MSC_VER
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
// catch all support for C++11
#if defined(__cplusplus) && __cplusplus >= 201103L
#define CLARA_CPP11_OR_GREATER
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
#endif
#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
#endif
#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
#endif
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
#endif
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
#endif
#endif // __cplusplus >= 201103L
// Now set the actual defines based on the above + anything the user has configured
#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
#define CLARA_CONFIG_CPP11_NULLPTR
#endif
#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
#define CLARA_CONFIG_CPP11_NOEXCEPT
#endif
#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
#define CLARA_CONFIG_CPP11_GENERATED_METHODS
#endif
#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
#define CLARA_CONFIG_CPP11_OVERRIDE
#endif
#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
#define CLARA_CONFIG_CPP11_UNIQUE_PTR
#endif
// noexcept support:
#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
#define CLARA_NOEXCEPT noexcept
# define CLARA_NOEXCEPT_IS(x) noexcept(x)
#else
#define CLARA_NOEXCEPT throw()
# define CLARA_NOEXCEPT_IS(x)
#endif
// nullptr support
#ifdef CLARA_CONFIG_CPP11_NULLPTR
#define CLARA_NULL nullptr
#else
#define CLARA_NULL NULL
#endif
// override support
#ifdef CLARA_CONFIG_CPP11_OVERRIDE
#define CLARA_OVERRIDE override
#else
#define CLARA_OVERRIDE
#endif
// unique_ptr support
#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
#else
# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
#endif
#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
// ----------- end of #include from clara_compilers.h -----------
// ........... back in clara.h
#include <map>
#include <algorithm>
#include <stdexcept>
#include <memory>
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#define CLARA_PLATFORM_WINDOWS
#endif
// Use optional outer namespace
#ifdef STITCH_CLARA_OPEN_NAMESPACE
STITCH_CLARA_OPEN_NAMESPACE
@ -230,9 +396,12 @@ namespace Clara {
inline void convertInto( std::string const& _source, std::string& _dest ) {
_dest = _source;
}
char toLowerCh(char c) {
return static_cast<char>( ::tolower( c ) );
}
inline void convertInto( std::string const& _source, bool& _dest ) {
std::string sourceLC = _source;
std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
_dest = true;
else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
@ -240,23 +409,16 @@ namespace Clara {
else
throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
}
inline void convertInto( bool _source, bool& _dest ) {
_dest = _source;
}
template<typename T>
inline void convertInto( bool, T& ) {
throw std::runtime_error( "Invalid conversion" );
}
template<typename ConfigT>
struct IArgFunction {
virtual ~IArgFunction() {}
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
IArgFunction() = default;
IArgFunction( IArgFunction const& ) = default;
# endif
#endif
virtual void set( ConfigT& config, std::string const& value ) const = 0;
virtual void setFlag( ConfigT& config ) const = 0;
virtual bool takesArg() const = 0;
virtual IArgFunction* clone() const = 0;
};
@ -264,11 +426,11 @@ namespace Clara {
template<typename ConfigT>
class BoundArgFunction {
public:
BoundArgFunction() : functionObj( CATCH_NULL ) {}
BoundArgFunction() : functionObj( CLARA_NULL ) {}
BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {}
BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
BoundArgFunction& operator = ( BoundArgFunction const& other ) {
IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL;
IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
delete functionObj;
functionObj = newFunctionObj;
return *this;
@ -278,13 +440,10 @@ namespace Clara {
void set( ConfigT& config, std::string const& value ) const {
functionObj->set( config, value );
}
void setFlag( ConfigT& config ) const {
functionObj->setFlag( config );
}
bool takesArg() const { return functionObj->takesArg(); }
bool isSet() const {
return functionObj != CATCH_NULL;
return functionObj != CLARA_NULL;
}
private:
IArgFunction<ConfigT>* functionObj;
@ -294,7 +453,6 @@ namespace Clara {
template<typename C>
struct NullBinder : IArgFunction<C>{
virtual void set( C&, std::string const& ) const {}
virtual void setFlag( C& ) const {}
virtual bool takesArg() const { return true; }
virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
};
@ -305,9 +463,6 @@ namespace Clara {
virtual void set( C& p, std::string const& stringValue ) const {
convertInto( stringValue, p.*member );
}
virtual void setFlag( C& p ) const {
convertInto( true, p.*member );
}
virtual bool takesArg() const { return !IsBool<M>::value; }
virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
M C::* member;
@ -320,11 +475,6 @@ namespace Clara {
convertInto( stringValue, value );
(p.*member)( value );
}
virtual void setFlag( C& p ) const {
typename RemoveConstRef<M>::type value;
convertInto( true, value );
(p.*member)( value );
}
virtual bool takesArg() const { return !IsBool<M>::value; }
virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
void (C::*member)( M );
@ -338,9 +488,6 @@ namespace Clara {
if( value )
(p.*member)();
}
virtual void setFlag( C& p ) const {
(p.*member)();
}
virtual bool takesArg() const { return false; }
virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
void (C::*member)();
@ -355,9 +502,6 @@ namespace Clara {
if( value )
function( obj );
}
virtual void setFlag( C& p ) const {
function( p );
}
virtual bool takesArg() const { return false; }
virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
void (*function)( C& );
@ -371,11 +515,6 @@ namespace Clara {
convertInto( stringValue, value );
function( obj, value );
}
virtual void setFlag( C& obj ) const {
typename RemoveConstRef<T>::type value;
convertInto( true, value );
function( obj, value );
}
virtual bool takesArg() const { return !IsBool<T>::value; }
virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
void (*function)( C&, T );
@ -383,8 +522,20 @@ namespace Clara {
} // namespace Detail
struct Parser {
Parser() : separators( " \t=:" ) {}
inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
std::vector<std::string> args( static_cast<std::size_t>( argc ) );
for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
args[i] = argv[i];
return args;
}
class Parser {
enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
Mode mode;
std::size_t from;
bool inQuotes;
public:
struct Token {
enum Type { Positional, ShortOpt, LongOpt };
@ -393,38 +544,75 @@ namespace Clara {
std::string data;
};
void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
Parser() : mode( None ), from( 0 ), inQuotes( false ){}
void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
const std::string doubleDash = "--";
for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
parseIntoTokens( argv[i] , tokens);
for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
parseIntoTokens( args[i], tokens);
}
void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
while( !arg.empty() ) {
Parser::Token token( Parser::Token::Positional, arg );
arg = "";
if( token.data[0] == '-' ) {
if( token.data.size() > 1 && token.data[1] == '-' ) {
token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
}
else {
token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
arg = "-" + token.data.substr( 1 );
token.data = token.data.substr( 0, 1 );
}
}
}
if( token.type != Parser::Token::Positional ) {
std::size_t pos = token.data.find_first_of( separators );
if( pos != std::string::npos ) {
arg = token.data.substr( pos+1 );
token.data = token.data.substr( 0, pos );
}
}
tokens.push_back( token );
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
for( std::size_t i = 0; i <= arg.size(); ++i ) {
char c = arg[i];
if( c == '"' )
inQuotes = !inQuotes;
mode = handleMode( i, c, arg, tokens );
}
}
std::string separators;
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
switch( mode ) {
case None: return handleNone( i, c );
case MaybeShortOpt: return handleMaybeShortOpt( i, c );
case ShortOpt:
case LongOpt:
case SlashOpt: return handleOpt( i, c, arg, tokens );
case Positional: return handlePositional( i, c, arg, tokens );
default: throw std::logic_error( "Unknown mode" );
}
}
Mode handleNone( std::size_t i, char c ) {
if( inQuotes ) {
from = i;
return Positional;
}
switch( c ) {
case '-': return MaybeShortOpt;
#ifdef CLARA_PLATFORM_WINDOWS
case '/': from = i+1; return SlashOpt;
#endif
default: from = i; return Positional;
}
}
Mode handleMaybeShortOpt( std::size_t i, char c ) {
switch( c ) {
case '-': from = i+1; return LongOpt;
default: from = i; return ShortOpt;
}
}
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
return mode;
std::string optName = arg.substr( from, i-from );
if( mode == ShortOpt )
for( std::size_t j = 0; j < optName.size(); ++j )
tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
else if( mode == SlashOpt && optName.size() == 1 )
tokens.push_back( Token( Token::ShortOpt, optName ) );
else
tokens.push_back( Token( Token::LongOpt, optName ) );
return None;
}
Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
return mode;
std::string data = arg.substr( from, i-from );
tokens.push_back( Token( Token::Positional, data ) );
return None;
}
};
template<typename ConfigT>
@ -503,12 +691,7 @@ namespace Clara {
}
};
// NOTE: std::auto_ptr is deprecated in c++11/c++0x
#if defined(__cplusplus) && __cplusplus > 199711L
typedef std::unique_ptr<Arg> ArgAutoPtr;
#else
typedef std::auto_ptr<Arg> ArgAutoPtr;
#endif
typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
friend void addOptName( Arg& arg, std::string const& optName )
{
@ -585,8 +768,8 @@ namespace Clara {
m_arg->description = description;
return *this;
}
ArgBuilder& detail( std::string const& _detail ) {
m_arg->detail = _detail;
ArgBuilder& detail( std::string const& detail ) {
m_arg->detail = detail;
return *this;
}
@ -670,14 +853,14 @@ namespace Clara {
maxWidth = (std::max)( maxWidth, it->commands().size() );
for( it = itBegin; it != itEnd; ++it ) {
Detail::Text usageText( it->commands(), Detail::TextAttributes()
Detail::Text usage( it->commands(), Detail::TextAttributes()
.setWidth( maxWidth+indent )
.setIndent( indent ) );
Detail::Text desc( it->description, Detail::TextAttributes()
.setWidth( width - maxWidth - 3 ) );
for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) {
std::string usageCol = i < usageText.size() ? usageText[i] : "";
for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
std::string usageCol = i < usage.size() ? usage[i] : "";
os << usageCol;
if( i < desc.size() && !desc[i].empty() )
@ -734,21 +917,21 @@ namespace Clara {
return oss.str();
}
ConfigT parse( int argc, char const * const * argv ) const {
ConfigT parse( std::vector<std::string> const& args ) const {
ConfigT config;
parseInto( argc, argv, config );
parseInto( args, config );
return config;
}
std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
std::string processName = argv[0];
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
std::string processName = args[0];
std::size_t lastSlash = processName.find_last_of( "/\\" );
if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 );
m_boundProcessName.set( config, processName );
std::vector<Parser::Token> tokens;
Parser parser;
parser.parseIntoTokens( argc, argv, tokens );
parser.parseIntoTokens( args, tokens );
return populate( tokens, config );
}
@ -779,7 +962,7 @@ namespace Clara {
arg.boundField.set( config, tokens[++i].data );
}
else {
arg.boundField.setFlag( config );
arg.boundField.set( config, "true" );
}
break;
}

View File

@ -58,6 +58,26 @@ namespace Detail {
return !operator==( rhs, lhs );
}
friend bool operator <= ( double lhs, Approx const& rhs )
{
return lhs < rhs.m_value || lhs == rhs;
}
friend bool operator <= ( Approx const& lhs, double rhs )
{
return lhs.m_value < rhs || lhs == rhs;
}
friend bool operator >= ( double lhs, Approx const& rhs )
{
return lhs > rhs.m_value || lhs == rhs;
}
friend bool operator >= ( Approx const& lhs, double rhs )
{
return lhs.m_value > rhs || lhs == rhs;
}
Approx& epsilon( double newEpsilon ) {
m_epsilon = newEpsilon;
return *this;

View File

@ -33,13 +33,14 @@
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
try { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \
} \
catch( ... ) { \
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
} \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
} while( Catch::alwaysFalse( sizeof(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
@ -129,14 +130,14 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
try { \
std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
std::string matcherAsString = (matcher).toString(); \
__catchResult \
.setLhs( Catch::toString( arg ) ) \
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
.setOp( "matches" ) \
.setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
.setResultType( (matcher).match( arg ) ); \
__catchResult.captureExpression(); \
} catch( ... ) { \
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \

View File

@ -23,6 +23,7 @@ namespace Catch {
config.abortAfter = x;
}
inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
inline void addWarning( ConfigData& config, std::string const& _warning ) {
if( _warning == "NoAssertions" )
@ -61,6 +62,21 @@ namespace Catch {
? ShowDurations::Always
: ShowDurations::Never;
}
inline void setUseColour( ConfigData& config, std::string const& value ) {
std::string mode = toLower( value );
if( mode == "yes" )
config.useColour = UseColour::Yes;
else if( mode == "no" )
config.useColour = UseColour::No;
else if( mode == "auto" )
config.useColour = UseColour::Auto;
else
throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
}
inline void forceColour( ConfigData& config ) {
config.useColour = UseColour::Yes;
}
inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
std::ifstream f( _filename.c_str() );
if( !f.is_open() )
@ -69,8 +85,11 @@ namespace Catch {
std::string line;
while( std::getline( f, line ) ) {
line = trim(line);
if( !line.empty() && !startsWith( line, "#" ) )
addTestOrTags( config, "\"" + line + "\"," );
if( !line.empty() && !startsWith( line, "#" ) ) {
if( !startsWith( line, "\"" ) )
line = "\"" + line + "\"";
addTestOrTags( config, line + "," );
}
}
}
@ -116,7 +135,7 @@ namespace Catch {
cli["-r"]["--reporter"]
// .placeholder( "name[:filename]" )
.describe( "reporter to use (defaults to console)" )
.bind( &ConfigData::reporterName, "name" );
.bind( &addReporterName, "name" );
cli["-n"]["--name"]
.describe( "suite name" )
@ -147,7 +166,7 @@ namespace Catch {
cli["-d"]["--durations"]
.describe( "show test durations" )
.bind( &setShowDurations, "yes/no" );
.bind( &setShowDurations, "yes|no" );
cli["-f"]["--input-file"]
.describe( "load test names to run from a file" )
@ -162,7 +181,7 @@ 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 );
@ -175,9 +194,13 @@ namespace Catch {
.bind( &setRngSeed, "'time'|number" );
cli["--force-colour"]
.describe( "force colourised output" )
.bind( &ConfigData::forceColour );
.describe( "force colourised output (deprecated)" )
.bind( &forceColour );
cli["--use-colour"]
.describe( "should output be colourised" )
.bind( &setUseColour, "yes|no" );
return cli;
}

View File

@ -8,9 +8,15 @@
#ifndef TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
#include "catch_compiler_capabilities.h"
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#ifdef CATCH_CONFIG_COUNTER
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
#else
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#endif
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
@ -22,14 +28,14 @@
#include "catch_compiler_capabilities.h"
namespace Catch {
struct IConfig;
struct CaseSensitive { enum Choice {
Yes,
No
}; };
class NonCopyable {
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
NonCopyable( NonCopyable const& ) = delete;
@ -110,15 +116,14 @@ namespace Catch {
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue( bool value ){ return value; }
inline bool alwaysTrue() { return true; }
inline bool alwaysFalse() { return false; }
inline bool alwaysTrue( std::size_t = 0 ) { return true; }
inline bool alwaysFalse( std::size_t = 0 ) { return false; }
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
void seedRng( IConfig const& config );
unsigned int rngSeed();
// Use this in variadic streaming macros to allow
// >> +StreamEndStop
// as well as

View File

@ -21,8 +21,11 @@ namespace Catch {
bool contains( std::string const& s, std::string const& infix ) {
return s.find( infix ) != std::string::npos;
}
char toLowerCh(char c) {
return static_cast<char>( ::tolower( c ) );
}
void toLowerInPlace( std::string& s ) {
std::transform( s.begin(), s.end(), s.begin(), ::tolower );
std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
}
std::string toLower( std::string const& s ) {
std::string lc = s;
@ -36,7 +39,7 @@ 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 );
@ -50,7 +53,7 @@ namespace Catch {
}
return replaced;
}
pluralise::pluralise( std::size_t count, std::string const& label )
: m_count( count ),
m_label( label )

View File

@ -17,11 +17,17 @@
// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// ****************
// Note to maintainers: if new toggles are added please document them
// in configuration.md, too
// ****************
// In general each macro has a _NO_<feature name> form
// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
@ -30,6 +36,18 @@
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
#ifdef __cplusplus
# if __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
# endif
# if __cplusplus >= 201402L
# define CATCH_CPP14_OR_GREATER
# endif
#endif
#ifdef __clang__
# if __has_feature(cxx_nullptr)
@ -40,6 +58,10 @@
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# endif
# if defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
# endif
#endif // __clang__
////////////////////////////////////////////////////////////////////////////////
@ -67,9 +89,16 @@
// GCC
#ifdef __GNUC__
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
#endif
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
# endif
// - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below
#endif // __GNUC__
@ -80,15 +109,19 @@
#if (_MSC_VER >= 1600)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
#endif
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
#endif
#endif // _MSC_VER
////////////////////////////////////////////////////////////////////////////////
// Use variadic macros if the compiler supports them
#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
@ -99,13 +132,20 @@
#endif
// Use __COUNTER__ if the compiler supports it
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
( defined __clang__ && __clang_major__ >= 3 )
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
// catch all support for C++11
#if (__cplusplus >= 201103L)
# define CATCH_CPP11_OR_GREATER
#if defined(CATCH_CPP11_OR_GREATER)
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
@ -135,6 +175,16 @@
# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
# endif
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
# endif
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
# endif
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
# endif
#endif // __cplusplus >= 201103L
// Now set the actual defines based on the above + anything the user has configured
@ -156,10 +206,28 @@
#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
# define CATCH_CONFIG_VARIADIC_MACROS
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG)
#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_LONG_LONG
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_OVERRIDE
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
#endif
// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
// This does not affect compilation
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
# define CATCH_CONFIG_COUNTER
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_SHUFFLE
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
#endif
// noexcept support:
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
@ -177,5 +245,19 @@
# define CATCH_NULL NULL
#endif
// override support
#ifdef CATCH_CONFIG_CPP11_OVERRIDE
# define CATCH_OVERRIDE override
#else
# define CATCH_OVERRIDE
#endif
// unique_ptr support
#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
#else
# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
#endif
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED

View File

@ -37,14 +37,14 @@ namespace Catch {
noThrow( false ),
showHelp( false ),
showInvisibles( false ),
forceColour( false ),
filenamesAsTags( false ),
abortAfter( -1 ),
rngSeed( 0 ),
verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter ),
runOrder( RunTests::InDeclarationOrder )
runOrder( RunTests::InDeclarationOrder ),
useColour( UseColour::Auto )
{}
bool listTests;
@ -57,7 +57,6 @@ namespace Catch {
bool noThrow;
bool showHelp;
bool showInvisibles;
bool forceColour;
bool filenamesAsTags;
int abortAfter;
@ -67,12 +66,13 @@ namespace Catch {
WarnAbout::What warnings;
ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder;
UseColour::YesOrNo useColour;
std::string reporterName;
std::string outputFilename;
std::string name;
std::string processName;
std::vector<std::string> reporterNames;
std::vector<std::string> testsOrTags;
};
@ -85,12 +85,11 @@ namespace Catch {
public:
Config()
: m_os( Catch::cout().rdbuf() )
{}
Config( ConfigData const& data )
: m_data( data ),
m_os( Catch::cout().rdbuf() )
m_stream( openStream() )
{
if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() );
@ -101,12 +100,6 @@ namespace Catch {
}
virtual ~Config() {
m_os.rdbuf( Catch::cout().rdbuf() );
m_stream.release();
}
void setFilename( std::string const& filename ) {
m_data.outputFilename = filename;
}
std::string const& getFilename() const {
@ -122,18 +115,7 @@ namespace Catch {
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
void setStreamBuf( std::streambuf* buf ) {
m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
}
void useStream( std::string const& streamName ) {
Stream stream = createStream( streamName );
setStreamBuf( stream.streamBuf );
m_stream.release();
m_stream = stream;
}
std::string getReporterName() const { return m_data.reporterName; }
std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
int abortAfter() const { return m_data.abortAfter; }
@ -144,24 +126,35 @@ namespace Catch {
// IConfig interface
virtual bool allowThrows() const { return !m_data.noThrow; }
virtual std::ostream& stream() const { return m_os; }
virtual std::ostream& stream() const { return m_stream->stream(); }
virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
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; }
virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
private:
IStream const* openStream() {
if( m_data.outputFilename.empty() )
return new CoutStream();
else if( m_data.outputFilename[0] == '%' ) {
if( m_data.outputFilename == "%debug" )
return new DebugOutStream();
else
throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
}
else
return new FileStream( m_data.outputFilename );
}
ConfigData m_data;
Stream m_stream;
mutable std::ostream m_os;
CATCH_AUTO_PTR( IStream const ) m_stream;
TestSpec m_testSpec;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED

View File

@ -41,15 +41,7 @@ namespace Catch {
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifdef __AFXDLL
#include <AfxWin.h>
#else
#include <windows.h>
#endif
#include "catch_windows_h_proxy.h"
namespace Catch {
namespace {
@ -95,7 +87,18 @@ namespace {
IColourImpl* platformColourInstance() {
static Win32ColourImpl s_instance;
return &s_instance;
Ptr<IConfig const> config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = !isDebuggerActive()
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes
? &s_instance
: NoColourImpl::instance();
}
} // end anon namespace
@ -120,7 +123,7 @@ namespace {
case Colour::White: return setColour( "[0m" );
case Colour::Red: return setColour( "[0;31m" );
case Colour::Green: return setColour( "[0;32m" );
case Colour::Blue: return setColour( "[0:34m" );
case Colour::Blue: return setColour( "[0;34m" );
case Colour::Cyan: return setColour( "[0;36m" );
case Colour::Yellow: return setColour( "[0;33m" );
case Colour::Grey: return setColour( "[1;30m" );
@ -146,7 +149,14 @@ namespace {
IColourImpl* platformColourInstance() {
Ptr<IConfig const> config = getCurrentContext().getConfig();
return (config && config->forceColour()) || isatty(STDOUT_FILENO)
UseColour::YesOrNo colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes
? PosixColourImpl::instance()
: NoColourImpl::instance();
}
@ -171,9 +181,7 @@ namespace Catch {
Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) {
static IColourImpl* impl = isDebuggerActive()
? NoColourImpl::instance()
: platformColourInstance();
static IColourImpl* impl = platformColourInstance();
impl->use( _colourCode );
}

View File

@ -8,10 +8,11 @@
#ifndef TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
#include "catch_runner_impl.hpp"
#include "catch_run_context.hpp"
#include "catch_context.h"
#include "catch_stream.hpp"
#include "catch_common.h"
namespace Catch {
@ -21,6 +22,11 @@ namespace Catch {
Context( Context const& );
void operator=( Context const& );
public:
virtual ~Context() {
deleteAllValues( m_generatorsByTestName );
}
public: // IContext
virtual IResultCapture* getResultCapture() {
return m_resultCapture;
@ -95,14 +101,6 @@ namespace Catch {
return getCurrentMutableContext();
}
Stream createStream( std::string const& streamName ) {
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 );
}
void cleanUpContext() {
delete currentContext;
currentContext = CATCH_NULL;

View File

@ -25,25 +25,36 @@ namespace Catch{
// http://cocoawithlove.com/2008/03/break-into-debugger.html
#ifdef DEBUG
#if defined(__ppc64__) || defined(__ppc__)
#define CATCH_BREAK_INTO_DEBUGGER() \
if( Catch::isDebuggerActive() ) { \
#define CATCH_TRAP() \
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
: : : "memory","r0","r3","r4" ); \
}
: : : "memory","r0","r3","r4" )
#else
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
#define CATCH_TRAP() _asm__("int $3\n" : : )
#endif
#endif
#elif defined(CATCH_PLATFORM_LINUX)
// If we can use inline assembler, do it because this allows us to break
// directly at the location of the failing check instead of breaking inside
// raise() called from it, i.e. one stack frame below.
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
#define CATCH_TRAP() asm volatile ("int $3")
#else // Fall back to the generic way.
#include <signal.h>
#define CATCH_TRAP() raise(SIGTRAP)
#endif
#elif defined(_MSC_VER)
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
#define CATCH_TRAP() __debugbreak()
#elif defined(__MINGW32__)
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
#define CATCH_TRAP() DebugBreak()
#endif
#ifndef CATCH_BREAK_INTO_DEBUGGER
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
#ifdef CATCH_TRAP
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
#else
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
#endif
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED

View File

@ -61,6 +61,33 @@
}
} // namespace Catch
#elif defined(CATCH_PLATFORM_LINUX)
#include <fstream>
#include <string>
namespace Catch{
// The standard POSIX way of detecting a debugger is to attempt to
// ptrace() the process, but this needs to be done from a child and not
// this process itself to still allow attaching to this process later
// if wanted, so is rather heavy. Under Linux we have the PID of the
// "debugger" (which doesn't need to be gdb, of course, it could also
// be strace, for example) in /proc/$PID/status, so just get it from
// there instead.
bool isDebuggerActive(){
std::ifstream in("/proc/self/status");
for( std::string line; std::getline(in, line); ) {
static const int PREFIX_LEN = 11;
if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
// We're traced if the PID is not 0 and no other PID starts
// with 0 digit, so it's enough to check for just a single
// character.
return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
}
}
return false;
}
} // namespace Catch
#elif defined(_MSC_VER)
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
namespace Catch {

View File

@ -11,7 +11,7 @@
#ifndef __OBJC__
// Standard C/C++ main entry point
int main (int argc, char * const argv[]) {
int main (int argc, char * argv[]) {
return Catch::Session().run( argc, argv );
}

View File

@ -52,37 +52,37 @@ namespace Internal {
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs) {
return opCast( lhs ) == opCast( rhs );
return bool( opCast( lhs ) == opCast( rhs ) );
}
};
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsNotEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) != opCast( rhs );
return bool( opCast( lhs ) != opCast( rhs ) );
}
};
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsLessThan> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) < opCast( rhs );
return bool( opCast( lhs ) < opCast( rhs ) );
}
};
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsGreaterThan> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) > opCast( rhs );
return bool( opCast( lhs ) > opCast( rhs ) );
}
};
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) >= opCast( rhs );
return bool( opCast( lhs ) >= opCast( rhs ) );
}
};
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) <= opCast( rhs );
return bool( opCast( lhs ) <= opCast( rhs ) );
}
};
@ -174,7 +174,7 @@ namespace Internal {
template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
// unsigned long long to X
template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
@ -188,7 +188,7 @@ namespace Internal {
template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
}
// pointer to long long (when comparing against NULL)
template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
@ -197,7 +197,7 @@ namespace Internal {
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
}
#endif // CATCH_CONFIG_CPP11_LONG_LONG
#ifdef CATCH_CONFIG_CPP11_NULLPTR
// pointer to nullptr_t (when comparing against nullptr)
template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {

View File

@ -32,13 +32,13 @@ namespace Catch {
#ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@try {
throw;
return tryTranslators();
}
@catch (NSException *exception) {
return Catch::toString( [exception description] );
}
#else
throw;
return tryTranslators();
#endif
}
catch( TestFailureException& ) {
@ -54,20 +54,15 @@ namespace Catch {
return msg;
}
catch(...) {
return tryTranslators( m_translators.begin() );
return "Unknown exception";
}
}
std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
if( it == m_translators.end() )
return "Unknown exception";
try {
return (*it)->translate();
}
catch(...) {
return tryTranslators( it+1 );
}
std::string tryTranslators() const {
if( m_translators.empty() )
throw;
else
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
}
private:

View File

@ -16,7 +16,7 @@
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
#include "../catch_runner.hpp"
#include "../catch_session.hpp"
#include "catch_registry_hub.hpp"
#include "catch_notimplemented_exception.hpp"
#include "catch_context_impl.hpp"
@ -35,15 +35,23 @@
#include "catch_tostring.hpp"
#include "catch_result_builder.hpp"
#include "catch_tag_alias_registry.hpp"
#include "catch_test_case_tracker.hpp"
#include "../reporters/catch_reporter_multi.hpp"
#include "../reporters/catch_reporter_xml.hpp"
#include "../reporters/catch_reporter_junit.hpp"
#include "../reporters/catch_reporter_console.hpp"
#include "../reporters/catch_reporter_compact.hpp"
namespace Catch {
// These are all here to avoid warnings about not having any out of line
// virtual methods
NonCopyable::~NonCopyable() {}
IShared::~IShared() {}
IStream::~IStream() CATCH_NOEXCEPT {}
FileStream::~FileStream() CATCH_NOEXCEPT {}
CoutStream::~CoutStream() CATCH_NOEXCEPT {}
DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
IContext::~IContext() {}
IResultCapture::~IResultCapture() {}
@ -89,6 +97,13 @@ namespace Catch {
Matchers::Impl::StdString::EndsWith::~EndsWith() {}
void Config::dummy() {}
namespace TestCaseTracking {
ITracker::~ITracker() {}
TrackerBase::~TrackerBase() {}
SectionTracker::~SectionTracker() {}
IndexTracker::~IndexTracker() {}
}
}
#ifdef __clang__

View File

@ -18,6 +18,7 @@ namespace Catch {
class AssertionResult;
struct AssertionInfo;
struct SectionInfo;
struct SectionEndInfo;
struct MessageInfo;
class ScopedMessageBuilder;
struct Counts;
@ -29,7 +30,8 @@ namespace Catch {
virtual void assertionEnded( AssertionResult const& result ) = 0;
virtual bool sectionStarted( SectionInfo const& sectionInfo,
Counts& assertions ) = 0;
virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( MessageInfo const& message ) = 0;

View File

@ -37,6 +37,11 @@ namespace Catch {
InLexicographicalOrder,
InRandomOrder
}; };
struct UseColour { enum YesOrNo {
Auto,
Yes,
No
}; };
class TestSpec;
@ -56,7 +61,7 @@ namespace Catch {
virtual TestSpec const& testSpec() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual bool forceColour() const = 0;
virtual UseColour::YesOrNo useColour() const = 0;
};
}

View File

@ -9,15 +9,20 @@
#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
#include <string>
#include <vector>
#include "catch_interfaces_registry_hub.h"
namespace Catch {
typedef std::string(*exceptionTranslateFunction)();
struct IExceptionTranslator;
typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
struct IExceptionTranslator {
virtual ~IExceptionTranslator();
virtual std::string translate() const = 0;
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
};
struct IExceptionTranslatorRegistry {
@ -35,9 +40,12 @@ namespace Catch {
: m_translateFunction( translateFunction )
{}
virtual std::string translate() const {
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
try {
throw;
if( it == itEnd )
throw;
else
return (*it)->translate( it+1, itEnd );
}
catch( T& ex ) {
return m_translateFunction( ex );
@ -58,9 +66,11 @@ namespace Catch {
}
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
static std::string translatorName( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
static std::string translatorName( signature )
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
#endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED

View File

@ -8,6 +8,8 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
#include "catch_ptr.hpp"
#include <string>
namespace Catch {
@ -29,7 +31,8 @@ namespace Catch {
struct IMutableRegistryHub {
virtual ~IMutableRegistryHub();
virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
virtual void registerTest( TestCase const& testInfo ) = 0;
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
};

View File

@ -26,18 +26,18 @@
namespace Catch
{
struct ReporterConfig {
explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
std::ostream& stream() const { return *m_stream; }
Ptr<IConfig> fullConfig() const { return m_fullConfig; }
Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
private:
std::ostream* m_stream;
Ptr<IConfig> m_fullConfig;
Ptr<IConfig const> m_fullConfig;
};
struct ReporterPreferences {
@ -219,6 +219,7 @@ namespace Catch
bool aborting;
};
class MultipleReporters;
struct IStreamingReporter : IShared {
virtual ~IStreamingReporter();
@ -240,29 +241,36 @@ namespace Catch
// 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;
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
};
struct IReporterFactory {
struct IReporterFactory : IShared {
virtual ~IReporterFactory();
virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
virtual std::string getDescription() const = 0;
};
struct IReporterRegistry {
typedef std::map<std::string, IReporterFactory*> FactoryMap;
typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
typedef std::vector<Ptr<IReporterFactory> > Listeners;
virtual ~IReporterRegistry();
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
virtual FactoryMap const& getFactories() const = 0;
virtual Listeners const& getListeners() const = 0;
};
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
}
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED

View File

@ -28,9 +28,13 @@ 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, bool negated = false ) const = 0;
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
};
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
}
#endif // TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED

View File

@ -34,8 +34,7 @@ namespace Catch {
nameAttr.setInitialIndent( 2 ).setIndent( 4 );
tagsAttr.setIndent( 6 );
std::vector<TestCase> matchedTestCases;
getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
@ -63,14 +62,16 @@ namespace Catch {
if( !config.testSpec().hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
std::size_t matchedTests = 0;
std::vector<TestCase> matchedTestCases;
getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
matchedTests++;
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Catch::cout() << testCaseInfo.name << std::endl;
if( startsWith( testCaseInfo.name, "#" ) )
Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
else
Catch::cout() << testCaseInfo.name << std::endl;
}
return matchedTests;
}
@ -104,8 +105,7 @@ namespace Catch {
std::map<std::string, TagInfo> tagCounts;
std::vector<TestCase> matchedTestCases;
getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {

View File

@ -12,6 +12,12 @@ namespace Catch {
namespace Matchers {
namespace Impl {
namespace Generic {
template<typename ExpressionT> class AllOf;
template<typename ExpressionT> class AnyOf;
template<typename ExpressionT> class Not;
}
template<typename ExpressionT>
struct Matcher : SharedImpl<IShared>
{
@ -21,6 +27,10 @@ namespace Matchers {
virtual Ptr<Matcher> clone() const = 0;
virtual bool match( ExpressionT const& expr ) const = 0;
virtual std::string toString() const = 0;
Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
Generic::Not<ExpressionT> operator ! () const;
};
template<typename DerivedT, typename ExpressionT>
@ -32,6 +42,22 @@ namespace Matchers {
};
namespace Generic {
template<typename ExpressionT>
class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
public:
explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
Not( Not const& other ) : m_matcher( other.m_matcher ) {}
virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
return !m_matcher->match( expr );
}
virtual std::string toString() const CATCH_OVERRIDE {
return "not " + m_matcher->toString();
}
private:
Ptr< Matcher<ExpressionT> > m_matcher;
};
template<typename ExpressionT>
class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
@ -63,6 +89,12 @@ namespace Matchers {
return oss.str();
}
AllOf operator && ( Matcher<ExpressionT> const& other ) const {
AllOf allOfExpr( *this );
allOfExpr.add( other );
return allOfExpr;
}
private:
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
};
@ -97,12 +129,40 @@ namespace Matchers {
return oss.str();
}
AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
AnyOf anyOfExpr( *this );
anyOfExpr.add( other );
return anyOfExpr;
}
private:
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
};
} // namespace Generic
template<typename ExpressionT>
Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
Generic::AllOf<ExpressionT> allOfExpr;
allOfExpr.add( *this );
allOfExpr.add( other );
return allOfExpr;
}
template<typename ExpressionT>
Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
Generic::AnyOf<ExpressionT> anyOfExpr;
anyOfExpr.add( *this );
anyOfExpr.add( other );
return anyOfExpr;
}
template<typename ExpressionT>
Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
return Generic::Not<ExpressionT>( *this );
}
namespace StdString {
inline std::string makeString( std::string const& str ) { return str; }
@ -118,7 +178,7 @@ namespace Matchers {
return m_caseSensitivity == CaseSensitive::No
? toLower( str )
: str;
}
std::string toStringSuffix() const
{
@ -129,7 +189,7 @@ namespace Matchers {
CaseSensitive::Choice m_caseSensitivity;
std::string m_str;
};
struct Equals : MatcherImpl<Equals, std::string> {
Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
: m_data( str, caseSensitivity )
@ -168,13 +228,13 @@ namespace Matchers {
struct StartsWith : MatcherImpl<StartsWith, std::string> {
StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
: m_data( substr, caseSensitivity ){}
StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
virtual ~StartsWith();
virtual bool match( std::string const& expr ) const {
return m_data.adjustString( expr ).find( m_data.m_str ) == 0;
return startsWith( m_data.adjustString( expr ), m_data.m_str );
}
virtual std::string toString() const {
return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
@ -191,7 +251,7 @@ namespace Matchers {
virtual ~EndsWith();
virtual bool match( std::string const& expr ) const {
return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size();
return endsWith( m_data.adjustString( expr ), m_data.m_str );
}
virtual std::string toString() const {
return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
@ -204,6 +264,11 @@ namespace Matchers {
// The following functions create the actual matcher objects.
// This allows the types to be inferred
template<typename ExpressionT>
inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
return Impl::Generic::Not<ExpressionT>( m );
}
template<typename ExpressionT>
inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
Impl::Matcher<ExpressionT> const& m2 ) {

View File

@ -10,11 +10,19 @@
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#define CATCH_PLATFORM_MAC
# define CATCH_PLATFORM_MAC
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#define CATCH_PLATFORM_IPHONE
# define CATCH_PLATFORM_IPHONE
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#define CATCH_PLATFORM_WINDOWS
# define CATCH_PLATFORM_WINDOWS
# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
# define CATCH_DEFINES_NOMINMAX
# endif
# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
# endif
#endif
#endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED

View File

@ -52,8 +52,7 @@ namespace Catch {
return *this;
}
void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
T* get() { return m_p; }
const T* get() const{ return m_p; }
T* get() const{ return m_p; }
T& operator*() const { return *m_p; }
T* operator->() const { return m_p; }
bool operator !() const { return m_p == CATCH_NULL; }

View File

@ -26,24 +26,27 @@ namespace Catch {
public: // IRegistryHub
RegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
return m_reporterRegistry;
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
return m_testCaseRegistry;
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
m_reporterRegistry.registerReporter( name, factory );
}
virtual void registerTest( TestCase const& testInfo ) {
virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
m_reporterRegistry.registerListener( factory );
}
virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
m_testCaseRegistry.registerTest( testInfo );
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}

View File

@ -36,7 +36,7 @@ namespace Catch {
template<typename T>
class ReporterRegistrar {
class ReporterFactory : public IReporterFactory {
class ReporterFactory : public SharedImpl<IReporterFactory> {
// *** Please Note ***:
// - If you end up here looking at a compiler error because it's trying to register
@ -64,11 +64,35 @@ namespace Catch {
getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
}
};
template<typename T>
class ListenerRegistrar {
class ListenerFactory : public SharedImpl<IReporterFactory> {
virtual IStreamingReporter* create( ReporterConfig const& config ) const {
return new T( config );
}
virtual std::string getDescription() const {
return "";
}
};
public:
ListenerRegistrar() {
getMutableRegistryHub().registerListener( new ListenerFactory() );
}
};
}
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED

View File

@ -18,27 +18,32 @@ namespace Catch {
public:
virtual ~ReporterRegistry() {
deleteAllValues( m_factories );
}
virtual ~ReporterRegistry() CATCH_OVERRIDE {}
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
FactoryMap::const_iterator it = m_factories.find( name );
if( it == m_factories.end() )
return CATCH_NULL;
return it->second->create( ReporterConfig( config ) );
}
void registerReporter( std::string const& name, IReporterFactory* factory ) {
void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
m_factories.insert( std::make_pair( name, factory ) );
}
void registerListener( Ptr<IReporterFactory> const& factory ) {
m_listeners.push_back( factory );
}
FactoryMap const& getFactories() const {
virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
return m_factories;
}
virtual Listeners const& getListeners() const CATCH_OVERRIDE {
return m_listeners;
}
private:
FactoryMap m_factories;
Listeners m_listeners;
};
}

View File

@ -85,7 +85,7 @@ namespace Catch {
std::string lhs, rhs, op;
} m_exprComponents;
CopyableStream m_stream;
bool m_shouldDebugBreak;
bool m_shouldThrow;
};

View File

@ -77,12 +77,12 @@ namespace Catch {
}
void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
assert( m_exprComponents.testFalse == false );
AssertionResultData data = m_data;
data.resultType = ResultWas::Ok;
data.reconstructedExpression = m_assertionInfo.capturedExpression;
std::string actualMessage = Catch::translateActiveException();
if( !matcher.match( actualMessage ) ) {
data.resultType = ResultWas::ExpressionFailed;
@ -99,7 +99,7 @@ namespace Catch {
void ResultBuilder::handleResult( AssertionResult const& result )
{
getResultCapture().assertionEnded( result );
if( !result.isOk() ) {
if( getCurrentContext().getConfig()->shouldDebugBreak() )
m_shouldDebugBreak = true;
@ -141,7 +141,7 @@ namespace Catch {
}
std::string ResultBuilder::reconstructExpression() const {
if( m_exprComponents.op == "" )
return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.lhs;
else if( m_exprComponents.op == "matches" )
return m_exprComponents.lhs + " " + m_exprComponents.rhs;
else if( m_exprComponents.op != "!" ) {

View File

@ -55,7 +55,7 @@ namespace Catch {
inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED

View File

@ -64,10 +64,7 @@ namespace Catch {
m_context( getCurrentMutableContext() ),
m_activeTestCase( CATCH_NULL ),
m_config( _config ),
m_reporter( reporter ),
m_prevRunner( m_context.getRunner() ),
m_prevResultCapture( m_context.getResultCapture() ),
m_prevConfig( m_context.getConfig() )
m_reporter( reporter )
{
m_context.setRunner( this );
m_context.setConfig( m_config );
@ -77,10 +74,6 @@ namespace Catch {
virtual ~RunContext() {
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
m_context.setRunner( m_prevRunner );
m_context.setConfig( Ptr<IConfig const>() );
m_context.setResultCapture( m_prevResultCapture );
m_context.setConfig( m_prevConfig );
}
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
@ -101,17 +94,26 @@ namespace Catch {
m_reporter->testCaseStarting( testInfo );
m_activeTestCase = &testCase;
m_testCaseTracker = TestCaseTracker( testInfo.name );
do {
m_trackerContext.startRun();
do {
m_trackerContext.startCycle();
m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name );
runCurrentTest( redirectedCout, redirectedCerr );
}
while( !m_testCaseTracker->isCompleted() && !aborting() );
while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
}
// !TBD: deprecated - this will be replaced by indexed trackers
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
Totals deltaTotals = m_totals.delta( prevTotals );
if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
deltaTotals.assertions.failed++;
deltaTotals.testCases.passed--;
deltaTotals.testCases.failed++;
}
m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( testInfo,
deltaTotals,
@ -120,7 +122,7 @@ namespace Catch {
aborting() ) );
m_activeTestCase = CATCH_NULL;
m_testCaseTracker.reset();
m_testCaseTracker = CATCH_NULL;
return deltaTotals;
}
@ -156,8 +158,10 @@ namespace Catch {
std::ostringstream oss;
oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
if( !m_testCaseTracker->enterSection( oss.str() ) )
ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
if( !sectionTracker.isOpen() )
return false;
m_activeSections.push_back( &sectionTracker );
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
@ -168,30 +172,40 @@ namespace Catch {
return true;
}
bool testForMissingAssertions( Counts& assertions ) {
if( assertions.total() != 0 ||
!m_config->warnAboutMissingAssertions() ||
m_testCaseTracker->currentSectionHasChildren() )
if( assertions.total() != 0 )
return false;
if( !m_config->warnAboutMissingAssertions() )
return false;
if( m_trackerContext.currentTracker().hasChildren() )
return false;
m_totals.assertions.failed++;
assertions.failed++;
return true;
}
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
Counts assertions = m_totals.assertions - prevAssertions;
virtual void sectionEnded( SectionEndInfo const& endInfo ) {
Counts assertions = m_totals.assertions - endInfo.prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
m_testCaseTracker->leaveSection();
if( !m_activeSections.empty() ) {
m_activeSections.back()->close();
m_activeSections.pop_back();
}
m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
m_messages.clear();
}
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
if( m_unfinishedSections.empty() )
m_activeSections.back()->fail();
else
m_activeSections.back()->close();
m_activeSections.pop_back();
m_unfinishedSections.push_back( endInfo );
}
virtual void pushScopedMessage( MessageInfo const& message ) {
m_messages.push_back( message );
}
@ -257,10 +271,9 @@ namespace Catch {
double duration = 0;
try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
TestCaseTracker::Guard guard( *m_testCaseTracker );
seedRng( *m_config );
Timer timer;
timer.start();
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
@ -279,6 +292,7 @@ namespace Catch {
catch(...) {
makeUnexpectedResultBuilder().useActiveException();
}
m_testCaseTracker->close();
handleUnfinishedSections();
m_messages.clear();
@ -313,39 +327,29 @@ namespace Catch {
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(),
for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
itEnd = m_unfinishedSections.rend();
it != itEnd;
++it )
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
sectionEnded( *it );
m_unfinishedSections.clear();
}
struct UnfinishedSections {
UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
: info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
{}
SectionInfo info;
Counts prevAssertions;
double durationInSeconds;
};
TestRunInfo m_runInfo;
IMutableContext& m_context;
TestCase const* m_activeTestCase;
Option<TestCaseTracker> m_testCaseTracker;
ITracker* m_testCaseTracker;
ITracker* m_currentSectionTracker;
AssertionResult m_lastResult;
Ptr<IConfig const> m_config;
Totals m_totals;
Ptr<IStreamingReporter> m_reporter;
std::vector<MessageInfo> m_messages;
IRunner* m_prevRunner;
IResultCapture* m_prevResultCapture;
Ptr<IConfig const> m_prevConfig;
AssertionInfo m_lastAssertionInfo;
std::vector<UnfinishedSections> m_unfinishedSections;
std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections;
TrackerContext m_trackerContext;
};
IResultCapture& getResultCapture() {

View File

@ -32,8 +32,13 @@ namespace Catch {
}
Section::~Section() {
if( m_sectionIncluded )
getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
if( m_sectionIncluded ) {
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
if( std::uncaught_exception() )
getResultCapture().sectionEndedEarly( endInfo );
else
getResultCapture().sectionEnded( endInfo );
}
}
// This indicates whether the section should be executed or not

View File

@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
#include "catch_common.h"
#include "catch_totals.hpp"
namespace Catch {
@ -23,6 +24,16 @@ namespace Catch {
SourceLineInfo lineInfo;
};
struct SectionEndInfo {
SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
: sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
{}
SectionInfo sectionInfo;
Counts prevAssertions;
double durationInSeconds;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED

View File

@ -9,28 +9,56 @@
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#include <streambuf>
#include "catch_compiler_capabilities.h"
#include "catch_streambuf.h"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wpadded"
#endif
#include <streambuf>
#include <ostream>
#include <fstream>
#include <memory>
namespace Catch {
class Stream {
public:
Stream();
Stream( std::streambuf* _streamBuf, bool _isOwned );
void release();
std::streambuf* streamBuf;
private:
bool isOwned;
};
std::ostream& cout();
std::ostream& cerr();
struct IStream {
virtual ~IStream() CATCH_NOEXCEPT;
virtual std::ostream& stream() const = 0;
};
class FileStream : public IStream {
mutable std::ofstream m_ofs;
public:
FileStream( std::string const& filename );
virtual ~FileStream() CATCH_NOEXCEPT;
public: // IStream
virtual std::ostream& stream() const CATCH_OVERRIDE;
};
class CoutStream : public IStream {
mutable std::ostream m_os;
public:
CoutStream();
virtual ~CoutStream() CATCH_NOEXCEPT;
public: // IStream
virtual std::ostream& stream() const CATCH_OVERRIDE;
};
class DebugOutStream : public IStream {
CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
mutable std::ostream m_os;
public:
DebugOutStream();
virtual ~DebugOutStream() CATCH_NOEXCEPT;
public: // IStream
virtual std::ostream& stream() const CATCH_OVERRIDE;
};
}
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED

View File

@ -10,7 +10,6 @@
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
#include "catch_stream.h"
#include "catch_streambuf.h"
#include "catch_debugger.h"
#include <stdexcept>
@ -57,6 +56,20 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////
FileStream::FileStream( std::string const& filename ) {
m_ofs.open( filename.c_str() );
if( m_ofs.fail() ) {
std::ostringstream oss;
oss << "Unable to open file: '" << filename << "'";
throw std::domain_error( oss.str() );
}
}
std::ostream& FileStream::stream() const {
return m_ofs;
}
struct OutputDebugWriter {
void operator()( std::string const&str ) {
@ -64,23 +77,26 @@ namespace Catch {
}
};
Stream::Stream()
: streamBuf( CATCH_NULL ), isOwned( false )
DebugOutStream::DebugOutStream()
: m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
m_os( m_streamBuf.get() )
{}
Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
: streamBuf( _streamBuf ), isOwned( _isOwned )
{}
void Stream::release() {
if( isOwned ) {
delete streamBuf;
streamBuf = CATCH_NULL;
isOwned = false;
}
std::ostream& DebugOutStream::stream() const {
return m_os;
}
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
// Store the streambuf from cout up-front because
// cout may get redirected when running tests
CoutStream::CoutStream()
: m_os( Catch::cout().rdbuf() )
{}
std::ostream& CoutStream::stream() const {
return m_os;
}
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
std::ostream& cout() {
return std::cout;
}

View File

@ -5,9 +5,6 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
#ifdef __clang__
# ifdef __ICC // icpc defines the __clang__ macro
# pragma warning(push)
@ -22,6 +19,7 @@
# pragma clang diagnostic ignored "-Wc++98-compat"
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
# pragma clang diagnostic ignored "-Wswitch-enum"
# pragma clang diagnostic ignored "-Wcovered-switch-default"
# endif
#elif defined __GNUC__
# pragma GCC diagnostic ignored "-Wvariadic-macros"
@ -29,5 +27,3 @@
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpadded"
#endif
#endif // TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED

View File

@ -31,7 +31,7 @@ namespace Catch {
MayFail = 1 << 3,
Throws = 1 << 4
};
TestCaseInfo( std::string const& _name,
std::string const& _className,
std::string const& _description,
@ -41,7 +41,7 @@ namespace Catch {
TestCaseInfo( TestCaseInfo const& other );
friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
bool isHidden() const;
bool throws() const;
bool okToFail() const;

View File

@ -88,7 +88,7 @@ namespace Catch {
tags.insert( "hide" );
tags.insert( "." );
}
TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
return TestCase( _testCase, info );
}
@ -97,7 +97,7 @@ namespace Catch {
{
testCaseInfo.tags = tags;
testCaseInfo.lcaseTags.clear();
std::ostringstream oss;
for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
oss << "[" << *it << "]";
@ -107,7 +107,7 @@ namespace Catch {
}
testCaseInfo.tagsAsString = oss.str();
}
TestCaseInfo::TestCaseInfo( std::string const& _name,
std::string const& _className,
std::string const& _description,

View File

@ -19,18 +19,93 @@
#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; }
};
struct RandomNumberGenerator {
typedef std::ptrdiff_t result_type;
result_type operator()( result_type n ) const { return std::rand() % n; }
#ifdef CATCH_CONFIG_CPP11_SHUFFLE
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return 1000000; }
result_type operator()() const { return std::rand() % max(); }
#endif
template<typename V>
static void shuffle( V& vector ) {
RandomNumberGenerator rng;
#ifdef CATCH_CONFIG_CPP11_SHUFFLE
std::shuffle( vector.begin(), vector.end(), rng );
#else
std::random_shuffle( vector.begin(), vector.end(), rng );
#endif
}
};
inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
std::vector<TestCase> sorted = unsortedTestCases;
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( sorted.begin(), sorted.end() );
break;
case RunTests::InRandomOrder:
{
seedRng( config );
RandomNumberGenerator::shuffle( sorted );
}
break;
case RunTests::InDeclarationOrder:
// already in declaration order
break;
}
return sorted;
}
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
}
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
std::set<TestCase> seenFunctions;
for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
it != itEnd;
++it ) {
std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
if( !prev.second ) {
std::ostringstream ss;
ss << Colour( Colour::Red )
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
throw std::runtime_error(ss.str());
}
}
}
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
std::vector<TestCase> filtered;
filtered.reserve( testCases.size() );
for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
it != itEnd;
++it )
if( matchTest( *it, testSpec, config ) )
filtered.push_back( *it );
return filtered;
}
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
}
class TestRegistry : public ITestCaseRegistry {
public:
TestRegistry() : m_unnamedCount( 0 ) {}
TestRegistry()
: m_currentSortOrder( RunTests::InDeclarationOrder ),
m_unnamedCount( 0 )
{}
virtual ~TestRegistry();
virtual void registerTest( TestCase const& testCase ) {
@ -40,70 +115,27 @@ namespace Catch {
oss << "Anonymous test case " << ++m_unnamedCount;
return registerTest( testCase.withName( oss.str() ) );
}
if( m_functions.find( testCase ) == m_functions.end() ) {
m_functions.insert( testCase );
m_functionsInOrder.push_back( testCase );
if( !testCase.isHidden() )
m_nonHiddenFunctions.push_back( testCase );
}
else {
TestCase const& prev = *m_functions.find( testCase );
{
Colour colourGuard( Colour::Red );
Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
<< "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
<< "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
}
exit(1);
}
m_functions.push_back( testCase );
}
virtual std::vector<TestCase> const& getAllTests() const {
return m_functionsInOrder;
return m_functions;
}
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
if( m_sortedFunctions.empty() )
enforceNoDuplicateTestCases( m_functions );
virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
return m_nonHiddenFunctions;
}
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 ) {
bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
if( includeTest != negated )
matchingTestCases.push_back( *it );
if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
m_sortedFunctions = sortTests( config, m_functions );
m_currentSortOrder = config.runOrder();
}
sortTests( config, matchingTestCases );
return m_sortedFunctions;
}
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:
{
seedRng( config );
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;
std::vector<TestCase> m_functions;
mutable RunTests::InWhatOrder m_currentSortOrder;
mutable std::vector<TestCase> m_sortedFunctions;
size_t m_unnamedCount;
std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
};
@ -138,29 +170,38 @@ namespace Catch {
return className;
}
///////////////////////////////////////////////////////////////////////////
void registerTestCase
( ITestCase* testCase,
char const* classOrQualifiedMethodName,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
AutoReg::AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
getMutableRegistryHub().registerTest
( makeTestCase
( testCase,
extractClassName( classOrQualifiedMethodName ),
nameAndDesc.name,
nameAndDesc.description,
lineInfo ) );
}
void registerTestCaseFunction
( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
}
AutoReg::~AutoReg() {}
///////////////////////////////////////////////////////////////////////////
void AutoReg::registerTestCase( ITestCase* testCase,
char const* classOrQualifiedMethodName,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
getMutableRegistryHub().registerTest
( makeTestCase( testCase,
extractClassName( classOrQualifiedMethodName ),
nameAndDesc.name,
nameAndDesc.description,
lineInfo ) );
AutoReg::AutoReg
( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
registerTestCaseFunction( function, lineInfo, nameAndDesc );
}
AutoReg::~AutoReg() {}
} // end namespace Catch

View File

@ -9,141 +9,321 @@
#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
#include "catch_compiler_capabilities.h"
#include "catch_ptr.hpp"
#include <map>
#include <string>
#include <assert.h>
#include <vector>
namespace Catch {
namespace SectionTracking {
namespace TestCaseTracking {
class TrackedSection {
struct ITracker : SharedImpl<> {
virtual ~ITracker();
// static queries
virtual std::string name() const = 0;
// dynamic queries
virtual bool isComplete() const = 0; // Successfully completed or failed
virtual bool isSuccessfullyCompleted() const = 0;
virtual bool isOpen() const = 0; // Started but not complete
virtual bool hasChildren() const = 0;
virtual ITracker& parent() = 0;
// actions
virtual void close() = 0; // Successfully complete
virtual void fail() = 0;
virtual void markAsNeedingAnotherRun() = 0;
virtual void addChild( Ptr<ITracker> const& child ) = 0;
virtual ITracker* findChild( std::string const& name ) = 0;
virtual void openChild() = 0;
typedef std::map<std::string, TrackedSection> TrackedSections;
public:
// Debug/ checking
virtual bool isSectionTracker() const = 0;
virtual bool isIndexTracker() const = 0;
};
class TrackerContext {
enum RunState {
NotStarted,
Executing,
ExecutingChildren,
Completed
CompletedCycle
};
TrackedSection( std::string const& name, TrackedSection* parent )
: m_name( name ), m_runState( NotStarted ), m_parent( parent )
Ptr<ITracker> m_rootTracker;
ITracker* m_currentTracker;
RunState m_runState;
public:
static TrackerContext& instance() {
static TrackerContext s_instance;
return s_instance;
}
TrackerContext()
: m_currentTracker( CATCH_NULL ),
m_runState( NotStarted )
{}
RunState runState() const { return m_runState; }
TrackedSection* findChild( std::string const& childName );
TrackedSection* acquireChild( std::string const& childName );
void enter() {
if( m_runState == NotStarted )
m_runState = Executing;
}
void leave();
TrackedSection* getParent() {
return m_parent;
ITracker& startRun();
void endRun() {
m_rootTracker.reset();
m_currentTracker = CATCH_NULL;
m_runState = NotStarted;
}
bool hasChildren() const {
void startCycle() {
m_currentTracker = m_rootTracker.get();
m_runState = Executing;
}
void completeCycle() {
m_runState = CompletedCycle;
}
bool completedCycle() const {
return m_runState == CompletedCycle;
}
ITracker& currentTracker() {
return *m_currentTracker;
}
void setCurrentTracker( ITracker* tracker ) {
m_currentTracker = tracker;
}
};
class TrackerBase : public ITracker {
protected:
enum CycleState {
NotStarted,
Executing,
ExecutingChildren,
NeedsAnotherRun,
CompletedSuccessfully,
Failed
};
class TrackerHasName {
std::string m_name;
public:
TrackerHasName( std::string const& name ) : m_name( name ) {}
bool operator ()( Ptr<ITracker> const& tracker ) {
return tracker->name() == m_name;
}
};
typedef std::vector<Ptr<ITracker> > Children;
std::string m_name;
TrackerContext& m_ctx;
ITracker* m_parent;
Children m_children;
CycleState m_runState;
public:
TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent )
: m_name( name ),
m_ctx( ctx ),
m_parent( parent ),
m_runState( NotStarted )
{}
virtual ~TrackerBase();
virtual std::string name() const CATCH_OVERRIDE {
return m_name;
}
virtual bool isComplete() const CATCH_OVERRIDE {
return m_runState == CompletedSuccessfully || m_runState == Failed;
}
virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
return m_runState == CompletedSuccessfully;
}
virtual bool isOpen() const CATCH_OVERRIDE {
return m_runState != NotStarted && !isComplete();
}
virtual bool hasChildren() const CATCH_OVERRIDE {
return !m_children.empty();
}
private:
std::string m_name;
RunState m_runState;
TrackedSections m_children;
TrackedSection* m_parent;
};
inline TrackedSection* TrackedSection::findChild( std::string const& childName ) {
TrackedSections::iterator it = m_children.find( childName );
return it != m_children.end()
? &it->second
: CATCH_NULL;
}
inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) {
if( TrackedSection* child = findChild( childName ) )
return child;
m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
return findChild( childName );
}
inline void TrackedSection::leave() {
for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
it != itEnd;
++it )
if( it->second.runState() != Completed ) {
virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
m_children.push_back( child );
}
virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE {
Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
return( it != m_children.end() )
? it->get()
: CATCH_NULL;
}
virtual ITracker& parent() CATCH_OVERRIDE {
assert( m_parent ); // Should always be non-null except for root
return *m_parent;
}
virtual void openChild() CATCH_OVERRIDE {
if( m_runState != ExecutingChildren ) {
m_runState = ExecutingChildren;
return;
if( m_parent )
m_parent->openChild();
}
m_runState = Completed;
}
class TestCaseTracker {
public:
TestCaseTracker( std::string const& testCaseName )
: m_testCase( testCaseName, CATCH_NULL ),
m_currentSection( &m_testCase ),
m_completedASectionThisRun( false )
{}
bool enterSection( std::string const& name ) {
TrackedSection* child = m_currentSection->acquireChild( name );
if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
return false;
m_currentSection = child;
m_currentSection->enter();
return true;
}
void leaveSection() {
m_currentSection->leave();
m_currentSection = m_currentSection->getParent();
assert( m_currentSection != CATCH_NULL );
m_completedASectionThisRun = true;
}
bool currentSectionHasChildren() const {
return m_currentSection->hasChildren();
}
bool isCompleted() const {
return m_testCase.runState() == TrackedSection::Completed;
virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
void open() {
m_runState = Executing;
moveToThis();
if( m_parent )
m_parent->openChild();
}
class Guard {
public:
Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
m_tracker.enterTestCase();
virtual void close() CATCH_OVERRIDE {
// Close any still open children (e.g. generators)
while( &m_ctx.currentTracker() != this )
m_ctx.currentTracker().close();
switch( m_runState ) {
case NotStarted:
case CompletedSuccessfully:
case Failed:
throw std::logic_error( "Illogical state" );
case NeedsAnotherRun:
break;;
case Executing:
m_runState = CompletedSuccessfully;
break;
case ExecutingChildren:
if( m_children.empty() || m_children.back()->isComplete() )
m_runState = CompletedSuccessfully;
break;
default:
throw std::logic_error( "Unexpected state" );
}
~Guard() {
m_tracker.leaveTestCase();
}
private:
Guard( Guard const& );
void operator = ( Guard const& );
TestCaseTracker& m_tracker;
};
moveToParent();
m_ctx.completeCycle();
}
virtual void fail() CATCH_OVERRIDE {
m_runState = Failed;
if( m_parent )
m_parent->markAsNeedingAnotherRun();
moveToParent();
m_ctx.completeCycle();
}
virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
m_runState = NeedsAnotherRun;
}
private:
void enterTestCase() {
m_currentSection = &m_testCase;
m_completedASectionThisRun = false;
m_testCase.enter();
void moveToParent() {
assert( m_parent );
m_ctx.setCurrentTracker( m_parent );
}
void leaveTestCase() {
m_testCase.leave();
void moveToThis() {
m_ctx.setCurrentTracker( this );
}
TrackedSection m_testCase;
TrackedSection* m_currentSection;
bool m_completedASectionThisRun;
};
} // namespace SectionTracking
class SectionTracker : public TrackerBase {
public:
SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent )
: TrackerBase( name, ctx, parent )
{}
virtual ~SectionTracker();
using SectionTracking::TestCaseTracker;
virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
SectionTracker* section = CATCH_NULL;
ITracker& currentTracker = ctx.currentTracker();
if( ITracker* childTracker = currentTracker.findChild( name ) ) {
assert( childTracker );
assert( childTracker->isSectionTracker() );
section = static_cast<SectionTracker*>( childTracker );
}
else {
section = new SectionTracker( name, ctx, &currentTracker );
currentTracker.addChild( section );
}
if( !ctx.completedCycle() && !section->isComplete() ) {
section->open();
}
return *section;
}
};
class IndexTracker : public TrackerBase {
int m_size;
int m_index;
public:
IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size )
: TrackerBase( name, ctx, parent ),
m_size( size ),
m_index( -1 )
{}
virtual ~IndexTracker();
virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
IndexTracker* tracker = CATCH_NULL;
ITracker& currentTracker = ctx.currentTracker();
if( ITracker* childTracker = currentTracker.findChild( name ) ) {
assert( childTracker );
assert( childTracker->isIndexTracker() );
tracker = static_cast<IndexTracker*>( childTracker );
}
else {
tracker = new IndexTracker( name, ctx, &currentTracker, size );
currentTracker.addChild( tracker );
}
if( !ctx.completedCycle() && !tracker->isComplete() ) {
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
tracker->moveNext();
tracker->open();
}
return *tracker;
}
int index() const { return m_index; }
void moveNext() {
m_index++;
m_children.clear();
}
virtual void close() CATCH_OVERRIDE {
TrackerBase::close();
if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
m_runState = Executing;
}
};
inline ITracker& TrackerContext::startRun() {
m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL );
m_currentTracker = CATCH_NULL;
m_runState = Executing;
return *m_rootTracker;
}
} // namespace TestCaseTracking
using TestCaseTracking::ITracker;
using TestCaseTracking::TrackerContext;
using TestCaseTracking::SectionTracker;
using TestCaseTracking::IndexTracker;
} // namespace Catch

View File

@ -42,27 +42,32 @@ struct NameAndDesc {
const char* description;
};
void registerTestCase
( ITestCase* testCase,
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo );
struct AutoReg {
AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc );
AutoReg
( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc );
template<typename C>
AutoReg( void (C::*method)(),
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
registerTestCase( new MethodTestCase<C>( method ),
className,
nameAndDesc,
lineInfo );
}
AutoReg
( void (C::*method)(),
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
void registerTestCase( ITestCase* testCase,
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo );
registerTestCase
( new MethodTestCase<C>( method ),
className,
nameAndDesc,
lineInfo );
}
~AutoReg();
@ -71,50 +76,70 @@ private:
void operator= ( AutoReg const& );
};
void registerTestCaseFunction
( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc );
} // end namespace Catch
#ifdef CATCH_CONFIG_VARIADIC_MACROS
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void TestName()
#define INTERNAL_CATCH_TESTCASE( ... ) \
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
namespace{ \
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
struct TestName : ClassName{ \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
} \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
void TestName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
#else
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
static void TestName(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void TestName()
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
namespace{ \
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
struct TestCaseName : ClassName{ \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
} \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
void TestCaseName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
#endif
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED

View File

@ -20,7 +20,7 @@
#include <vector>
namespace Catch {
class TestSpec {
struct Pattern : SharedImpl<> {
virtual ~Pattern();
@ -38,7 +38,7 @@ namespace Catch {
private:
WildcardPattern m_wildcardPattern;
};
class TagPattern : public Pattern {
public:
TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
@ -49,7 +49,7 @@ namespace Catch {
private:
std::string m_tag;
};
class ExcludedPattern : public Pattern {
public:
ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
@ -64,10 +64,11 @@ namespace Catch {
bool matches( TestCaseInfo const& testCase ) const {
// All patterns in a filter must match for the filter to be a match
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
if( !(*it)->matches( testCase ) )
return false;
return true;
}
return true;
}
};

View File

@ -19,11 +19,12 @@
namespace Catch {
class TestSpecParser {
enum Mode{ None, Name, QuotedName, Tag };
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Mode m_mode;
bool m_exclusion;
std::size_t m_start, m_pos;
std::string m_arg;
std::vector<std::size_t> m_escapeChars;
TestSpec::Filter m_currentFilter;
TestSpec m_testSpec;
ITagAliasRegistry const* m_tagAliases;
@ -36,6 +37,7 @@ namespace Catch {
m_exclusion = false;
m_start = std::string::npos;
m_arg = m_tagAliases->expandAliases( arg );
m_escapeChars.clear();
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
visitChar( m_arg[m_pos] );
if( m_mode == Name )
@ -54,6 +56,7 @@ namespace Catch {
case '~': m_exclusion = true; return;
case '[': return startNewMode( Tag, ++m_pos );
case '"': return startNewMode( QuotedName, ++m_pos );
case '\\': return escape();
default: startNewMode( Name, m_pos ); break;
}
}
@ -69,7 +72,11 @@ namespace Catch {
addPattern<TestSpec::NamePattern>();
startNewMode( Tag, ++m_pos );
}
else if( c == '\\' )
escape();
}
else if( m_mode == EscapedName )
m_mode = Name;
else if( m_mode == QuotedName && c == '"' )
addPattern<TestSpec::NamePattern>();
else if( m_mode == Tag && c == ']' )
@ -79,10 +86,17 @@ namespace Catch {
m_mode = mode;
m_start = start;
}
void escape() {
m_mode = EscapedName;
m_escapeChars.push_back( m_pos );
}
std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
template<typename T>
void addPattern() {
std::string token = subString();
for( size_t i = 0; i < m_escapeChars.size(); ++i )
token = token.substr( 0, m_escapeChars[i] ) + token.substr( m_escapeChars[i]+1 );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
token = token.substr( 8 );

View File

@ -15,7 +15,7 @@
#endif
#ifdef CATCH_PLATFORM_WINDOWS
#include <windows.h>
#include "catch_windows_h_proxy.h"
#else
#include <sys/time.h>
#endif

View File

@ -67,7 +67,7 @@ std::string toString( std::nullptr_t );
std::string toString( NSObject* const& nsObject );
#endif
namespace Detail {
extern const std::string unprintableString;
@ -78,7 +78,7 @@ namespace Detail {
struct TrueType { char sizer[1]; };
struct FalseType { char sizer[2]; };
TrueType& testStreamable( std::ostream& );
FalseType testStreamable( FalseType );

View File

@ -16,7 +16,7 @@ namespace Catch {
namespace Detail {
const std::string unprintableString = "{?}";
namespace {
const int hexThreshold = 255;
@ -175,7 +175,7 @@ std::string toString( unsigned long long value ) {
return oss.str();
}
#endif
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std::string toString( std::nullptr_t ) {
return "nullptr";

View File

@ -27,7 +27,7 @@ namespace Catch {
unsigned int const buildNumber;
friend std::ostream& operator << ( std::ostream& os, Version const& version );
private:
void operator=( Version const& );
};

View File

@ -37,7 +37,7 @@ namespace Catch {
return os;
}
Version libraryVersion( 1, 2, 1, "develop", 9 );
Version libraryVersion( 1, 6, 1, "", 0 );
}

View File

@ -19,9 +19,9 @@ namespace Catch
WildcardAtEnd = 2,
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
};
public:
WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
: m_caseSensitivity( caseSensitivity ),
m_wildcard( NoWildcard ),
@ -48,7 +48,7 @@ namespace Catch
case WildcardAtBothEnds:
return contains( adjustCase( str ), m_pattern );
}
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"

View File

@ -0,0 +1,32 @@
/*
* Created by Martin on 16/01/2017.
*
* 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_WINDOWS_H_PROXY_H_INCLUDED
#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
#ifdef CATCH_DEFINES_NOMINMAX
# define NOMINMAX
#endif
#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#ifdef __AFXDLL
#include <AfxWin.h>
#else
#include <windows.h>
#endif
#ifdef CATCH_DEFINES_NOMINMAX
# undef NOMINMAX
#endif
#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
# undef WIN32_LEAN_AND_MEAN
#endif
#endif // TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED

View File

@ -22,23 +22,23 @@ namespace Catch {
class XmlEncode {
public:
enum ForWhat { ForTextNodes, ForAttributes };
XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
: m_str( str ),
m_forWhat( forWhat )
{}
void encodeTo( std::ostream& os ) const {
// Apostrophe escaping not necessary if we always use " to write attributes
// (see: http://www.w3.org/TR/xml/#syntax)
for( std::size_t i = 0; i < m_str.size(); ++ i ) {
char c = m_str[i];
switch( c ) {
case '<': os << "&lt;"; break;
case '&': os << "&amp;"; break;
case '>':
// See: http://www.w3.org/TR/xml/#syntax
if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
@ -46,18 +46,19 @@ namespace Catch {
else
os << c;
break;
case '\"':
if( m_forWhat == ForAttributes )
os << "&quot;";
else
os << c;
break;
default:
// Escape control chars - based on contribution by @espenalb in PR #465
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
// Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
else
os << c;
}
@ -68,12 +69,12 @@ namespace Catch {
xmlEncode.encodeTo( os );
return os;
}
private:
std::string m_str;
ForWhat m_forWhat;
};
class XmlWriter {
public:
@ -112,13 +113,20 @@ namespace Catch {
: m_tagIsOpen( false ),
m_needsNewline( false ),
m_os( &Catch::cout() )
{}
{
// We encode control characters, which requires
// XML 1.1
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
}
XmlWriter( std::ostream& os )
: m_tagIsOpen( false ),
m_needsNewline( false ),
m_os( &os )
{}
{
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
}
~XmlWriter() {
while( !m_tags.empty() )

View File

@ -19,47 +19,53 @@ namespace Catch {
StreamingReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
{}
{
m_reporterPrefs.shouldRedirectStdOut = false;
}
virtual ~StreamingReporterBase();
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
return m_reporterPrefs;
}
virtual void noMatchingTestCases( std::string const& ) {}
virtual ~StreamingReporterBase() CATCH_OVERRIDE;
virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
currentTestRunInfo = _testRunInfo;
}
virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
currentGroupInfo = _groupInfo;
}
virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
currentTestCaseInfo = _testInfo;
}
virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
m_sectionStack.push_back( _sectionInfo );
}
virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
m_sectionStack.pop_back();
}
virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
currentTestCaseInfo.reset();
}
virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
currentGroupInfo.reset();
}
virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
currentTestCaseInfo.reset();
currentGroupInfo.reset();
currentTestRunInfo.reset();
}
virtual void skipTest( TestCaseInfo const& ) {
virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
// Don't do anything with this by default.
// It can optionally be overridden in the derived class.
}
Ptr<IConfig> m_config;
Ptr<IConfig const> m_config;
std::ostream& stream;
LazyStat<TestRunInfo> currentTestRunInfo;
@ -67,6 +73,7 @@ namespace Catch {
LazyStat<TestCaseInfo> currentTestCaseInfo;
std::vector<SectionInfo> m_sectionStack;
ReporterPreferences m_reporterPrefs;
};
struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
@ -118,15 +125,21 @@ namespace Catch {
CumulativeReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
{}
{
m_reporterPrefs.shouldRedirectStdOut = false;
}
~CumulativeReporterBase();
virtual void testRunStarting( TestRunInfo const& ) {}
virtual void testGroupStarting( GroupInfo const& ) {}
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
return m_reporterPrefs;
}
virtual void testCaseStarting( TestCaseInfo const& ) {}
virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
virtual void sectionStarting( SectionInfo const& sectionInfo ) {
virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
Ptr<SectionNode> node;
if( m_sectionStack.empty() ) {
@ -151,21 +164,21 @@ namespace Catch {
m_deepestSection = node;
}
virtual void assertionStarting( AssertionInfo const& ) {}
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
assert( !m_sectionStack.empty() );
SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back( assertionStats );
return true;
}
virtual void sectionEnded( SectionStats const& sectionStats ) {
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
assert( !m_sectionStack.empty() );
SectionNode& node = *m_sectionStack.back();
node.stats = sectionStats;
m_sectionStack.pop_back();
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
assert( m_sectionStack.size() == 0 );
node->children.push_back( m_rootSection );
@ -176,12 +189,12 @@ namespace Catch {
m_deepestSection->stdOut = testCaseStats.stdOut;
m_deepestSection->stdErr = testCaseStats.stdErr;
}
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
node->children.swap( m_testCases );
m_testGroups.push_back( node );
}
virtual void testRunEnded( TestRunStats const& testRunStats ) {
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Ptr<TestRunNode> node = new TestRunNode( testRunStats );
node->children.swap( m_testGroups );
m_testRuns.push_back( node );
@ -189,9 +202,9 @@ namespace Catch {
}
virtual void testRunEndedCumulative() = 0;
virtual void skipTest( TestCaseInfo const& ) {}
virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
Ptr<IConfig> m_config;
Ptr<IConfig const> m_config;
std::ostream& stream;
std::vector<AssertionStats> m_assertions;
std::vector<std::vector<Ptr<SectionNode> > > m_sections;
@ -203,6 +216,7 @@ namespace Catch {
Ptr<SectionNode> m_rootSection;
Ptr<SectionNode> m_deepestSection;
std::vector<Ptr<SectionNode> > m_sectionStack;
ReporterPreferences m_reporterPrefs;
};
@ -216,6 +230,18 @@ namespace Catch {
return line;
}
struct TestEventListenerBase : StreamingReporterBase {
TestEventListenerBase( ReporterConfig const& _config )
: StreamingReporterBase( _config )
{}
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
return false;
}
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED

View File

@ -21,24 +21,19 @@ namespace Catch {
m_headerPrinted( false )
{}
virtual ~ConsoleReporter();
virtual ~ConsoleReporter() CATCH_OVERRIDE;
static std::string getDescription() {
return "Reports test results as plain lines of text";
}
virtual ReporterPreferences getPreferences() const {
ReporterPreferences prefs;
prefs.shouldRedirectStdOut = false;
return prefs;
}
virtual void noMatchingTestCases( std::string const& spec ) {
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
stream << "No test cases matched '" << spec << "'" << std::endl;
}
virtual void assertionStarting( AssertionInfo const& ) {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = _assertionStats.assertionResult;
bool printInfoMessages = true;
@ -58,11 +53,11 @@ namespace Catch {
return true;
}
virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
m_headerPrinted = false;
StreamingReporterBase::sectionStarting( _sectionInfo );
}
virtual void sectionEnded( SectionStats const& _sectionStats ) {
virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
if( _sectionStats.missingAssertions ) {
lazyPrint();
Colour colour( Colour::ResultError );
@ -84,11 +79,11 @@ namespace Catch {
StreamingReporterBase::sectionEnded( _sectionStats );
}
virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseEnded( _testCaseStats );
m_headerPrinted = false;
}
virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
if( currentGroupInfo.used ) {
printSummaryDivider();
stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
@ -97,7 +92,7 @@ namespace Catch {
}
StreamingReporterBase::testGroupEnded( _testGroupStats );
}
virtual void testRunEnded( TestRunStats const& _testRunStats ) {
virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
printTotalsDivider( _testRunStats.totals );
printTotals( _testRunStats.totals );
stream << std::endl;
@ -354,7 +349,7 @@ namespace Catch {
if( totals.testCases.total() == 0 ) {
stream << Colour( Colour::Warning ) << "No tests ran\n";
}
else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
stream << Colour( Colour::ResultSuccess ) << "All tests passed";
stream << " ("
<< pluralise( totals.assertions.passed, "assertion" ) << " in "

View File

@ -18,33 +18,58 @@
namespace Catch {
namespace {
std::string getCurrentTimestamp() {
// Beware, this is not reentrant because of backward compatibility issues
// Also, UTC only, again because of backward compatibility (%z is C++11)
time_t rawtime;
std::time(&rawtime);
const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
#ifdef CATCH_PLATFORM_WINDOWS
std::tm timeInfo = {};
gmtime_s(&timeInfo, &rawtime);
#else
std::tm* timeInfo;
timeInfo = std::gmtime(&rawtime);
#endif
char timeStamp[timeStampSize];
const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
#ifdef CATCH_PLATFORM_WINDOWS
std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
#else
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
#endif
return std::string(timeStamp);
}
}
class JunitReporter : public CumulativeReporterBase {
public:
JunitReporter( ReporterConfig const& _config )
: CumulativeReporterBase( _config ),
xml( _config.stream() )
{}
{
m_reporterPrefs.shouldRedirectStdOut = true;
}
~JunitReporter();
virtual ~JunitReporter() CATCH_OVERRIDE;
static std::string getDescription() {
return "Reports test results in an XML format that looks like Ant's junitreport target";
}
virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
virtual ReporterPreferences getPreferences() const {
ReporterPreferences prefs;
prefs.shouldRedirectStdOut = true;
return prefs;
}
virtual void testRunStarting( TestRunInfo const& runInfo ) {
virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
CumulativeReporterBase::testRunStarting( runInfo );
xml.startElement( "testsuites" );
}
virtual void testGroupStarting( GroupInfo const& groupInfo ) {
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
suiteTimer.start();
stdOutForSuite.str("");
stdErrForSuite.str("");
@ -52,25 +77,25 @@ namespace Catch {
CumulativeReporterBase::testGroupStarting( groupInfo );
}
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
unexpectedExceptions++;
return CumulativeReporterBase::assertionEnded( assertionStats );
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
stdOutForSuite << testCaseStats.stdOut;
stdErrForSuite << testCaseStats.stdErr;
CumulativeReporterBase::testCaseEnded( testCaseStats );
}
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
double suiteTime = suiteTimer.getElapsedSeconds();
CumulativeReporterBase::testGroupEnded( testGroupStats );
writeGroup( *m_testGroups.back(), suiteTime );
}
virtual void testRunEndedCumulative() {
virtual void testRunEndedCumulative() CATCH_OVERRIDE {
xml.endElement();
}
@ -86,7 +111,7 @@ namespace Catch {
xml.writeAttribute( "time", "" );
else
xml.writeAttribute( "time", suiteTime );
xml.writeAttribute( "timestamp", "tbd" ); // !TBD
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
// Write test cases
for( TestGroupNode::ChildNodes::const_iterator
@ -108,7 +133,7 @@ namespace Catch {
SectionNode const& rootSection = *testCaseNode.children.front();
std::string className = stats.testInfo.className;
if( className.empty() ) {
if( rootSection.childSections.empty() )
className = "global";
@ -122,7 +147,7 @@ namespace Catch {
std::string name = trim( sectionNode.stats.sectionInfo.name );
if( !rootName.empty() )
name = rootName + "/" + name;
if( !sectionNode.assertions.empty() ||
!sectionNode.stdOut.empty() ||
!sectionNode.stdErr.empty() ) {
@ -191,7 +216,7 @@ namespace Catch {
elementName = "internalError";
break;
}
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
xml.writeAttribute( "message", result.getExpandedExpression() );
@ -220,7 +245,7 @@ namespace Catch {
unsigned int unexpectedExceptions;
};
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
} // end namespace Catch

View File

@ -0,0 +1,152 @@
/*
* Created by Phil on 5/08/2015.
* Copyright 2015 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_MULTI_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
#include "../internal/catch_interfaces_reporter.h"
namespace Catch {
class MultipleReporters : public SharedImpl<IStreamingReporter> {
typedef std::vector<Ptr<IStreamingReporter> > Reporters;
Reporters m_reporters;
public:
void add( Ptr<IStreamingReporter> const& reporter ) {
m_reporters.push_back( reporter );
}
public: // IStreamingReporter
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
return m_reporters[0]->getPreferences();
}
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->noMatchingTestCases( spec );
}
virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->testRunStarting( testRunInfo );
}
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->testGroupStarting( groupInfo );
}
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->testCaseStarting( testInfo );
}
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->sectionStarting( sectionInfo );
}
virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->assertionStarting( assertionInfo );
}
// The return value indicates if the messages buffer should be cleared:
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
bool clearBuffer = false;
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
clearBuffer |= (*it)->assertionEnded( assertionStats );
return clearBuffer;
}
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->sectionEnded( sectionStats );
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->testCaseEnded( testCaseStats );
}
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->testGroupEnded( testGroupStats );
}
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->testRunEnded( testRunStats );
}
virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
it != itEnd;
++it )
(*it)->skipTest( testInfo );
}
virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
return this;
}
};
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
Ptr<IStreamingReporter> resultingReporter;
if( existingReporter ) {
MultipleReporters* multi = existingReporter->tryAsMulti();
if( !multi ) {
multi = new MultipleReporters;
resultingReporter = Ptr<IStreamingReporter>( multi );
if( existingReporter )
multi->add( existingReporter );
}
else
resultingReporter = existingReporter;
multi->add( additionalReporter );
}
else
resultingReporter = additionalReporter;
return resultingReporter;
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED

View File

@ -17,18 +17,22 @@
#include <cstring>
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
# 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
namespace Catch {
struct TeamCityReporter : StreamingReporterBase {
TeamCityReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
m_headerPrintedForThisSection( false )
{}
{
m_reporterPrefs.shouldRedirectStdOut = true;
}
static std::string escape( std::string const& str ) {
std::string escaped = str;
replaceInPlace( escaped, "|", "||" );
@ -39,18 +43,13 @@ namespace Catch {
replaceInPlace( escaped, "]", "|]" );
return escaped;
}
virtual ~TeamCityReporter();
virtual ~TeamCityReporter() CATCH_OVERRIDE;
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 ) {
virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
stream << "##teamcity[testIgnored name='"
<< escape( testInfo.name ) << "'";
if( testInfo.isHidden() )
@ -59,35 +58,35 @@ namespace Catch {
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 ) {
virtual void noMatchingTestCases( std::string const& /* spec */ ) CATCH_OVERRIDE {}
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testGroupStarting( groupInfo );
stream << "##teamcity[testSuiteStarted name='"
<< escape( groupInfo.name ) << "']\n";
}
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
StreamingReporterBase::testGroupEnded( testGroupStats );
stream << "##teamcity[testSuiteFinished name='"
<< escape( testGroupStats.groupInfo.name ) << "']\n";
}
virtual void assertionStarting( AssertionInfo const& ) {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
}
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
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";
@ -126,15 +125,15 @@ namespace Catch {
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() ) << "'"
@ -142,19 +141,19 @@ namespace Catch {
}
return true;
}
virtual void sectionStarting( SectionInfo const& sectionInfo ) {
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
m_headerPrintedForThisSection = false;
StreamingReporterBase::sectionStarting( sectionInfo );
}
virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseStarting( testInfo );
stream << "##teamcity[testStarted name='"
<< escape( testInfo.name ) << "']\n";
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseEnded( testCaseStats );
if( !testCaseStats.stdOut.empty() )
stream << "##teamcity[testStdOut name='"
@ -182,9 +181,9 @@ namespace Catch {
printHeaderString( os, it->name );
os << getLineOfChars<'-'>() << "\n";
}
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
if( !lineInfo.empty() )
os << lineInfo << "\n";
os << getLineOfChars<'.'>() << "\n\n";
@ -204,19 +203,19 @@ namespace Catch {
}
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
# pragma clang diagnostic pop
#endif
#endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED

View File

@ -20,49 +20,46 @@ namespace Catch {
public:
XmlReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
m_xml(_config.stream()),
m_sectionDepth( 0 )
{}
{
m_reporterPrefs.shouldRedirectStdOut = true;
}
virtual ~XmlReporter() CATCH_OVERRIDE;
virtual ~XmlReporter();
static std::string getDescription() {
return "Reports test results as an XML document";
}
public: // StreamingReporterBase
virtual ReporterPreferences getPreferences() const {
ReporterPreferences prefs;
prefs.shouldRedirectStdOut = true;
return prefs;
}
virtual void noMatchingTestCases( std::string const& s ) {
virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
StreamingReporterBase::noMatchingTestCases( s );
}
virtual void testRunStarting( TestRunInfo const& testInfo ) {
virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testRunStarting( testInfo );
m_xml.setStream( stream );
m_xml.startElement( "Catch" );
if( !m_config->name().empty() )
m_xml.writeAttribute( "name", m_config->name() );
}
virtual void testGroupStarting( GroupInfo const& groupInfo ) {
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testGroupStarting( groupInfo );
m_xml.startElement( "Group" )
.writeAttribute( "name", groupInfo.name );
}
virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseStarting(testInfo);
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
if ( m_config->showDurations() == ShowDurations::Always )
m_testCaseTimer.start();
}
virtual void sectionStarting( SectionInfo const& sectionInfo ) {
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
StreamingReporterBase::sectionStarting( sectionInfo );
if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" )
@ -71,11 +68,11 @@ namespace Catch {
}
}
virtual void assertionStarting( AssertionInfo const& ) { }
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
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();
@ -118,7 +115,7 @@ namespace Catch {
.writeText( assertionResult.getMessage() );
break;
case ResultWas::FatalErrorCondition:
m_xml.scopedElement( "Fatal Error Condition" )
m_xml.scopedElement( "FatalErrorCondition" )
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
.writeAttribute( "line", assertionResult.getSourceInfo().line )
.writeText( assertionResult.getMessage() );
@ -137,14 +134,14 @@ namespace Catch {
default:
break;
}
if( assertionResult.hasExpression() )
m_xml.endElement();
return true;
}
virtual void sectionEnded( SectionStats const& sectionStats ) {
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
StreamingReporterBase::sectionEnded( sectionStats );
if( --m_sectionDepth > 0 ) {
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
@ -159,7 +156,7 @@ namespace Catch {
}
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseEnded( testCaseStats );
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
@ -170,7 +167,7 @@ namespace Catch {
m_xml.endElement();
}
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
StreamingReporterBase::testGroupEnded( testGroupStats );
// TODO: Check testGroupStats.aborting and act accordingly.
m_xml.scopedElement( "OverallResults" )
@ -179,8 +176,8 @@ namespace Catch {
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
m_xml.endElement();
}
virtual void testRunEnded( TestRunStats const& testRunStats ) {
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
StreamingReporterBase::testRunEnded( testRunStats );
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", testRunStats.totals.assertions.passed )

View File

@ -1,48 +0,0 @@
cmake_minimum_required(VERSION 2.8)
project(Catch)
# define some folders
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
${SELF_TEST_DIR}/ApproxTests.cpp
${SELF_TEST_DIR}/BDDTests.cpp
${SELF_TEST_DIR}/ClassTests.cpp
${SELF_TEST_DIR}/ConditionTests.cpp
${SELF_TEST_DIR}/ExceptionTests.cpp
${SELF_TEST_DIR}/GeneratorTests.cpp
${SELF_TEST_DIR}/MessageTests.cpp
${SELF_TEST_DIR}/MiscTests.cpp
${SELF_TEST_DIR}/SectionTrackerTests.cpp
${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
include_directories(${CATCH_DIR}/include)
add_executable(SelfTest ${SOURCES})
# configure unit tests via CTest
enable_testing()
add_test(NAME RunTests COMMAND SelfTest)
add_test(NAME ListTests COMMAND SelfTest --list-tests)
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
add_test(NAME ListTags COMMAND SelfTest --list-tags)
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")

View File

@ -16,7 +16,7 @@ TEST_CASE
)
{
double d = 1.23;
REQUIRE( d == Approx( 1.23 ) );
REQUIRE( d != Approx( 1.22 ) );
REQUIRE( d != Approx( 1.24 ) );
@ -34,11 +34,41 @@ TEST_CASE
)
{
double d = 1.23;
REQUIRE( d != Approx( 1.231 ) );
REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) );
}
///////////////////////////////////////////////////////////////////////////////
TEST_CASE
(
"Less-than inequalities with different epsilons",
"[Approx]"
)
{
double d = 1.23;
REQUIRE( d <= Approx( 1.24 ) );
REQUIRE( d <= Approx( 1.23 ) );
REQUIRE_FALSE( d <= Approx( 1.22 ) );
REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) );
}
///////////////////////////////////////////////////////////////////////////////
TEST_CASE
(
"Greater-than inequalities with different epsilons",
"[Approx]"
)
{
double d = 1.23;
REQUIRE( d >= Approx( 1.22 ) );
REQUIRE( d >= Approx( 1.23 ) );
REQUIRE_FALSE( d >= Approx( 1.24 ) );
REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) );
}
///////////////////////////////////////////////////////////////////////////////
TEST_CASE
(
@ -71,7 +101,7 @@ TEST_CASE
const double dZero = 0;
const double dSmall = 0.00001;
const double dMedium = 1.234;
REQUIRE( 1.0f == Approx( 1 ) );
REQUIRE( 0 == Approx( dZero) );
REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) );
@ -87,14 +117,14 @@ TEST_CASE
)
{
double d = 1.23;
Approx approx = Approx::custom().epsilon( 0.005 );
REQUIRE( d == approx( 1.23 ) );
REQUIRE( d == approx( 1.22 ) );
REQUIRE( d == approx( 1.24 ) );
REQUIRE( d != approx( 1.25 ) );
REQUIRE( approx( d ) == 1.23 );
REQUIRE( approx( d ) == 1.22 );
REQUIRE( approx( d ) == 1.24 );

View File

@ -30,13 +30,13 @@ SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capa
GIVEN( "an empty vector" ) {
std::vector<int> v;
REQUIRE( v.size() == 0 );
WHEN( "it is made larger" ) {
v.resize( 10 );
THEN( "the size and capacity go up" ) {
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
AND_WHEN( "it is made smaller again" ) {
v.resize( 5 );
THEN( "the size goes down but the capacity stays the same" ) {
@ -46,7 +46,7 @@ SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capa
}
}
}
WHEN( "we reserve more space" ) {
v.reserve( 10 );
THEN( "The capacity is increased but the size remains the same" ) {
@ -76,19 +76,19 @@ struct Fixture
: d_counter(0)
{
}
int counter()
{
return d_counter++;
}
int d_counter;
};
}
SCENARIO_METHOD(Fixture,
"BDD tests requiring Fixtures to provide commonly-accessed data or methods",
"BDD tests requiring Fixtures to provide commonly-accessed data or methods",
"[bdd][fixtures]") {
const int before(counter());
GIVEN("No operations precede me") {

View File

@ -1,8 +1,48 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CatchSelfTest is a <version> host application.
<exe-name> is a <version> host application.
Run with -? for options
-------------------------------------------------------------------------------
'Not' checks that should fail
-------------------------------------------------------------------------------
ConditionTests.cpp:<line number>
...............................................................................
ConditionTests.cpp:<line number>: FAILED:
CHECK( false != false )
ConditionTests.cpp:<line number>: FAILED:
CHECK( true != true )
ConditionTests.cpp:<line number>: FAILED:
CHECK( !true )
with expansion:
false
ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( true )
ConditionTests.cpp:<line number>: FAILED:
CHECK( !trueValue )
with expansion:
false
ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( trueValue )
with expansion:
!true
ConditionTests.cpp:<line number>: FAILED:
CHECK( !(1 == 1) )
with expansion:
false
ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( 1 == 1 )
with expansion:
!(1 == 1)
-------------------------------------------------------------------------------
A METHOD_AS_TEST_CASE based test run that fails
-------------------------------------------------------------------------------
@ -25,6 +65,97 @@ ClassTests.cpp:<line number>: FAILED:
with expansion:
1 == 2
-------------------------------------------------------------------------------
A couple of nested sections followed by a failure
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
explicitly with message:
to infinity and beyond
-------------------------------------------------------------------------------
A failing expression with a non streamable type is still captured
-------------------------------------------------------------------------------
TrickyTests.cpp:<line number>
...............................................................................
TrickyTests.cpp:<line number>: FAILED:
CHECK( &o1 == &o2 )
with expansion:
0x<hex digits> == 0x<hex digits>
TrickyTests.cpp:<line number>: FAILED:
CHECK( o1 == o2 )
with expansion:
{?} == {?}
-------------------------------------------------------------------------------
An unchecked exception reports the line of the last assertion
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
{Unknown expression after the reported line}
due to unexpected exception with message:
unexpected exception
-------------------------------------------------------------------------------
Contains string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching(), Contains( "not there" ) )
with expansion:
"this string contains 'abc' as a substring" contains: "not there"
-------------------------------------------------------------------------------
Custom exceptions can be translated when testing for nothrow
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_NOTHROW( throwCustom() )
due to unexpected exception with message:
custom exception - not std
-------------------------------------------------------------------------------
Custom exceptions can be translated when testing for throwing as something else
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_THROWS_AS( throwCustom() )
due to unexpected exception with message:
custom exception - not std
-------------------------------------------------------------------------------
Custom std-exceptions can be custom translated
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
due to unexpected exception with message:
custom std exception
-------------------------------------------------------------------------------
EndsWith string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching(), EndsWith( "this" ) )
with expansion:
"this string contains 'abc' as a substring" ends with: "this"
-------------------------------------------------------------------------------
Equality checks that should fail
-------------------------------------------------------------------------------
@ -96,6 +227,100 @@ ConditionTests.cpp:<line number>: FAILED:
with expansion:
1.3 == Approx( 1.301 )
-------------------------------------------------------------------------------
Equals string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching(), Equals( "something else" ) )
with expansion:
"this string contains 'abc' as a substring" equals: "something else"
-------------------------------------------------------------------------------
Expected exceptions that don't throw or unexpected exceptions fail the test
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
CHECK_THROWS_AS( thisThrows() )
due to unexpected exception with message:
expected exception
ExceptionTests.cpp:<line number>: FAILED:
CHECK_THROWS_AS( thisDoesntThrow() )
because no exception was thrown where one was expected:
ExceptionTests.cpp:<line number>: FAILED:
CHECK_NOTHROW( thisThrows() )
due to unexpected exception with message:
expected exception
-------------------------------------------------------------------------------
FAIL aborts the test
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
This is a failure
-------------------------------------------------------------------------------
FAIL does not require an argument
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
INFO and WARN do not abort tests
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>:
warning:
this is a warning
-------------------------------------------------------------------------------
INFO gets logged on failure
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
REQUIRE( a == 1 )
with expansion:
2 == 1
with messages:
this message should be logged
so should this
-------------------------------------------------------------------------------
INFO gets logged on failure, even if captured before successful assertions
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
CHECK( a == 1 )
with expansion:
2 == 1
with messages:
this message may be logged later
this message should be logged
MessageTests.cpp:<line number>: FAILED:
CHECK( a == 0 )
with expansion:
2 == 0
with message:
and this, but later
-------------------------------------------------------------------------------
Inequality checks that should fail
-------------------------------------------------------------------------------
@ -127,6 +352,60 @@ ConditionTests.cpp:<line number>: FAILED:
with expansion:
5 != 5
-------------------------------------------------------------------------------
Matchers can be composed with both && and || - failing
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) )
with expansion:
"this string contains 'abc' as a substring" ( ( contains: "string" or
contains: "different" ) and contains: "random" )
-------------------------------------------------------------------------------
Matchers can be negated (Not) with the ! operator - failing
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching(), !Contains( "substring" ) )
with expansion:
"this string contains 'abc' as a substring" not contains: "substring"
-------------------------------------------------------------------------------
Mismatching exception messages failing the test
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
with expansion:
expected exception
-------------------------------------------------------------------------------
Nice descriptive name
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>:
warning:
This one ran
-------------------------------------------------------------------------------
Non-std exceptions can be translated
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
due to unexpected exception with message:
custom exception
-------------------------------------------------------------------------------
Ordering comparison checks that should fail
-------------------------------------------------------------------------------
@ -229,64 +508,99 @@ with expansion:
"hello" <= "a"
-------------------------------------------------------------------------------
'Not' checks that should fail
Output from all sections is reported
one
-------------------------------------------------------------------------------
ConditionTests.cpp:<line number>
MessageTests.cpp:<line number>
...............................................................................
ConditionTests.cpp:<line number>: FAILED:
CHECK( false != false )
ConditionTests.cpp:<line number>: FAILED:
CHECK( true != true )
ConditionTests.cpp:<line number>: FAILED:
CHECK( !true )
with expansion:
false
ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( true )
ConditionTests.cpp:<line number>: FAILED:
CHECK( !trueValue )
with expansion:
false
ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( trueValue )
with expansion:
!true
ConditionTests.cpp:<line number>: FAILED:
CHECK( !(1 == 1) )
with expansion:
false
ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( 1 == 1 )
with expansion:
!(1 == 1)
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
Message from section one
-------------------------------------------------------------------------------
Expected exceptions that don't throw or unexpected exceptions fail the test
Output from all sections is reported
two
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
Message from section two
-------------------------------------------------------------------------------
Pointers can be converted to strings
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>:
warning:
actual address of p: 0x<hex digits>
MessageTests.cpp:<line number>:
warning:
toString(p): 0x<hex digits>
-------------------------------------------------------------------------------
SCOPED_INFO is reset for each loop
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
REQUIRE( i < 10 )
with expansion:
10 < 10
with messages:
current counter 10
i := 10
A string sent directly to stdout
A string sent directly to stderr
Message from section one
Message from section two
-------------------------------------------------------------------------------
StartsWith string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching(), StartsWith( "string" ) )
with expansion:
"this string contains 'abc' as a substring" starts with: "string"
hello
hello
-------------------------------------------------------------------------------
Tabs and newlines show in output
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK( s1 == s2 )
with expansion:
"if ($b == 10) {
$a= 20;
}"
==
"if ($b == 10) {
$a = 20;
}
"
-------------------------------------------------------------------------------
Unexpected exceptions can be translated
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
CHECK_THROWS_AS( thisThrows() )
due to unexpected exception with message:
expected exception
ExceptionTests.cpp:<line number>: FAILED:
CHECK_THROWS_AS( thisDoesntThrow() )
because no exception was thrown where one was expected:
ExceptionTests.cpp:<line number>: FAILED:
CHECK_NOTHROW( thisThrows() )
due to unexpected exception with message:
expected exception
3.14
-------------------------------------------------------------------------------
When unchecked exceptions are thrown directly they are always failures
@ -299,29 +613,8 @@ due to unexpected exception with message:
unexpected exception
-------------------------------------------------------------------------------
An unchecked exception reports the line of the last assertion
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
{Unknown expression after the reported line}
due to unexpected exception with message:
unexpected exception
-------------------------------------------------------------------------------
When unchecked exceptions are thrown from sections they are always failures
section name
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
due to unexpected exception with message:
unexpected exception
-------------------------------------------------------------------------------
When unchecked exceptions are thrown from functions they are always failures
When unchecked exceptions are thrown during a CHECK the test should abort and
fail
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
@ -344,8 +637,7 @@ due to unexpected exception with message:
expected exception
-------------------------------------------------------------------------------
When unchecked exceptions are thrown during a CHECK the test should abort and
fail
When unchecked exceptions are thrown from functions they are always failures
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
@ -356,158 +648,69 @@ due to unexpected exception with message:
expected exception
-------------------------------------------------------------------------------
Unexpected custom exceptions can be translated
When unchecked exceptions are thrown from sections they are always failures
section name
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
due to unexpected exception with message:
custom exception
unexpected exception
-------------------------------------------------------------------------------
Custom exceptions can be translated when testing for nothrow
Where the LHS is not a simple value
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
TrickyTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_NOTHROW( throwCustom() )
due to unexpected exception with message:
custom exception - not std
-------------------------------------------------------------------------------
Custom exceptions can be translated when testing for throwing as something else
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_THROWS_AS( throwCustom() )
due to unexpected exception with message:
custom exception - not std
-------------------------------------------------------------------------------
Unexpected exceptions can be translated
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
due to unexpected exception with message:
3.14
-------------------------------------------------------------------------------
Mismatching exception messages failing the test
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
with expansion:
expected exception
-------------------------------------------------------------------------------
INFO and WARN do not abort tests
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>:
TrickyTests.cpp:<line number>:
warning:
this is a warning
Uncomment the code in this test to check that it gives a sensible compiler
error
-------------------------------------------------------------------------------
INFO gets logged on failure
Where there is more to the expression after the RHS
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
TrickyTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
REQUIRE( a == 1 )
TrickyTests.cpp:<line number>:
warning:
Uncomment the code in this test to check that it gives a sensible compiler
error
-------------------------------------------------------------------------------
checkedElse, failing
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECKED_ELSE( flag )
with expansion:
2 == 1
with messages:
this message should be logged
so should this
false
-------------------------------------------------------------------------------
INFO gets logged on failure, even if captured before successful assertions
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
CHECK( a == 1 )
MiscTests.cpp:<line number>: FAILED:
REQUIRE( testCheckedElse( false ) )
with expansion:
2 == 1
with messages:
this message may be logged later
this message should be logged
false
MessageTests.cpp:<line number>: FAILED:
CHECK( a == 0 )
-------------------------------------------------------------------------------
checkedIf, failing
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECKED_IF( flag )
with expansion:
2 == 0
with message:
and this, but later
false
-------------------------------------------------------------------------------
FAIL aborts the test
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
This is a failure
-------------------------------------------------------------------------------
FAIL does not require an argument
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Output from all sections is reported
one
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
Message from section one
-------------------------------------------------------------------------------
Output from all sections is reported
two
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
Message from section two
Message from section one
Message from section two
-------------------------------------------------------------------------------
SCOPED_INFO is reset for each loop
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
REQUIRE( i < 10 )
MiscTests.cpp:<line number>: FAILED:
REQUIRE( testCheckedIf( false ) )
with expansion:
10 < 10
with messages:
current counter 10
i := 10
false
-------------------------------------------------------------------------------
just failure
@ -519,45 +722,6 @@ MessageTests.cpp:<line number>: FAILED:
explicitly with message:
Previous info should not be seen
-------------------------------------------------------------------------------
sends information to INFO
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
REQUIRE( false )
with messages:
hi
i := 7
-------------------------------------------------------------------------------
Pointers can be converted to strings
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>:
warning:
actual address of p: 0x<hex digits>
MessageTests.cpp:<line number>:
warning:
toString(p): 0x<hex digits>
-------------------------------------------------------------------------------
more nested SECTION tests
s1
s2
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
REQUIRE( a == b )
with expansion:
1 == 2
-------------------------------------------------------------------------------
looped SECTION tests
s1
@ -618,39 +782,18 @@ with expansion:
with message:
Testing if fib[7] (21) is even
A string sent directly to stdout
A string sent directly to stderr
-------------------------------------------------------------------------------
checkedIf, failing
more nested SECTION tests
s1
s2
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECKED_IF( flag )
REQUIRE( a == b )
with expansion:
false
MiscTests.cpp:<line number>: FAILED:
REQUIRE( testCheckedIf( false ) )
with expansion:
false
-------------------------------------------------------------------------------
checkedElse, failing
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECKED_ELSE( flag )
with expansion:
false
MiscTests.cpp:<line number>: FAILED:
REQUIRE( testCheckedElse( false ) )
with expansion:
false
1 == 2
-------------------------------------------------------------------------------
send a single char to INFO
@ -664,126 +807,16 @@ with message:
3
-------------------------------------------------------------------------------
Contains string matcher
sends information to INFO
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
MessageTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching() Contains( "not there" ) )
with expansion:
"this string contains 'abc' as a substring" contains: "not there"
-------------------------------------------------------------------------------
StartsWith string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching() StartsWith( "string" ) )
with expansion:
"this string contains 'abc' as a substring" starts with: "string"
-------------------------------------------------------------------------------
EndsWith string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching() EndsWith( "this" ) )
with expansion:
"this string contains 'abc' as a substring" ends with: "this"
-------------------------------------------------------------------------------
Equals string matcher
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK_THAT( testStringForMatching() Equals( "something else" ) )
with expansion:
"this string contains 'abc' as a substring" equals: "something else"
-------------------------------------------------------------------------------
Nice descriptive name
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>:
warning:
This one ran
-------------------------------------------------------------------------------
A couple of nested sections followed by a failure
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
explicitly with message:
to infinity and beyond
-------------------------------------------------------------------------------
Tabs and newlines show in output
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK( s1 == s2 )
with expansion:
"if ($b == 10) {
$a= 20;
}"
==
"if ($b == 10) {
$a = 20;
}
"
hello
hello
-------------------------------------------------------------------------------
Where there is more to the expression after the RHS
-------------------------------------------------------------------------------
TrickyTests.cpp:<line number>
...............................................................................
TrickyTests.cpp:<line number>:
warning:
Uncomment the code in this test to check that it gives a sensible compiler
error
-------------------------------------------------------------------------------
Where the LHS is not a simple value
-------------------------------------------------------------------------------
TrickyTests.cpp:<line number>
...............................................................................
TrickyTests.cpp:<line number>:
warning:
Uncomment the code in this test to check that it gives a sensible compiler
error
-------------------------------------------------------------------------------
A failing expression with a non streamable type is still captured
-------------------------------------------------------------------------------
TrickyTests.cpp:<line number>
...............................................................................
TrickyTests.cpp:<line number>: FAILED:
CHECK( &o1 == &o2 )
with expansion:
0x<hex digits> == 0x<hex digits>
TrickyTests.cpp:<line number>: FAILED:
CHECK( o1 == o2 )
with expansion:
{?} == {?}
MessageTests.cpp:<line number>: FAILED:
REQUIRE( false )
with messages:
hi
i := 7
-------------------------------------------------------------------------------
string literals of different sizes can be compared
@ -797,6 +830,6 @@ with expansion:
"first" == "second"
===============================================================================
test cases: 159 | 119 passed | 39 failed | 1 failed as expected
assertions: 784 | 691 passed | 80 failed | 13 failed as expected
test cases: 159 | 115 passed | 42 failed | 2 failed as expected
assertions: 909 | 813 passed | 78 failed | 18 failed as expected

File diff suppressed because it is too large Load Diff

View File

@ -1,491 +1,40 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CatchSelfTest is a <version> host application.
<exe-name> is a <version> host application.
Run with -? for options
-------------------------------------------------------------------------------
toString(enum)
# A test name that starts with a #
-------------------------------------------------------------------------------
EnumToString.cpp:<line number>
MiscTests.cpp:<line number>
...............................................................................
EnumToString.cpp:<line number>:
MiscTests.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"
with message:
yay
-------------------------------------------------------------------------------
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
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d == Approx( 1.23 ) )
with expansion:
1.23 == Approx( 1.23 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d != Approx( 1.22 ) )
with expansion:
1.23 != Approx( 1.22 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d != Approx( 1.24 ) )
with expansion:
1.23 != Approx( 1.24 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( Approx( d ) == 1.23 )
with expansion:
Approx( 1.23 ) == 1.23
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( Approx( d ) != 1.22 )
with expansion:
Approx( 1.23 ) != 1.22
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( Approx( d ) != 1.24 )
with expansion:
Approx( 1.23 ) != 1.24
-------------------------------------------------------------------------------
Approximate comparisons with different epsilons
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d != Approx( 1.231 ) )
with expansion:
1.23 != Approx( 1.231 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) )
with expansion:
1.23 == Approx( 1.231 )
-------------------------------------------------------------------------------
Approximate comparisons with floats
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 1.23f == Approx( 1.23f ) )
with expansion:
1.23f == Approx( 1.2300000191 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 0.0f == Approx( 0.0f ) )
with expansion:
0.0f == Approx( 0.0 )
-------------------------------------------------------------------------------
Approximate comparisons with ints
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 1 == Approx( 1 ) )
with expansion:
1 == Approx( 1.0 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 0 == Approx( 0 ) )
with expansion:
0 == Approx( 0.0 )
-------------------------------------------------------------------------------
Approximate comparisons with mixed numeric types
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 1.0f == Approx( 1 ) )
with expansion:
1.0f == Approx( 1.0 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 0 == Approx( dZero) )
with expansion:
0 == Approx( 0.0 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) )
with expansion:
0 == Approx( 0.00001 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( 1.234f == Approx( dMedium ) )
with expansion:
1.234f == Approx( 1.234 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( dMedium == Approx( 1.234f ) )
with expansion:
1.234 == Approx( 1.2339999676 )
-------------------------------------------------------------------------------
Use a custom approx
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d == approx( 1.23 ) )
with expansion:
1.23 == Approx( 1.23 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d == approx( 1.22 ) )
with expansion:
1.23 == Approx( 1.22 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d == approx( 1.24 ) )
with expansion:
1.23 == Approx( 1.24 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( d != approx( 1.25 ) )
with expansion:
1.23 != Approx( 1.25 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( approx( d ) == 1.23 )
with expansion:
Approx( 1.23 ) == 1.23
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( approx( d ) == 1.22 )
with expansion:
Approx( 1.23 ) == 1.22
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( approx( d ) == 1.24 )
with expansion:
Approx( 1.23 ) == 1.24
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( approx( d ) != 1.25 )
with expansion:
Approx( 1.23 ) != 1.25
-------------------------------------------------------------------------------
Approximate PI
-------------------------------------------------------------------------------
ApproxTests.cpp:<line number>
...............................................................................
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) )
with expansion:
3.1428571429 == Approx( 3.141 )
ApproxTests.cpp:<line number>:
PASSED:
REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) )
with expansion:
3.1428571429 != Approx( 3.141 )
-------------------------------------------------------------------------------
A METHOD_AS_TEST_CASE based test run that succeeds
-------------------------------------------------------------------------------
ClassTests.cpp:<line number>
...............................................................................
ClassTests.cpp:<line number>:
PASSED:
REQUIRE( s == "hello" )
with expansion:
"hello" == "hello"
-------------------------------------------------------------------------------
A METHOD_AS_TEST_CASE based test run that fails
-------------------------------------------------------------------------------
ClassTests.cpp:<line number>
...............................................................................
ClassTests.cpp:<line number>: FAILED:
REQUIRE( s == "world" )
with expansion:
"hello" == "world"
-------------------------------------------------------------------------------
A TEST_CASE_METHOD based test run that succeeds
-------------------------------------------------------------------------------
ClassTests.cpp:<line number>
...............................................................................
ClassTests.cpp:<line number>:
PASSED:
REQUIRE( m_a == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
A TEST_CASE_METHOD based test run that fails
-------------------------------------------------------------------------------
ClassTests.cpp:<line number>
...............................................................................
ClassTests.cpp:<line number>: FAILED:
REQUIRE( m_a == 2 )
with expansion:
1 == 2
-------------------------------------------------------------------------------
Equality checks that should succeed
-------------------------------------------------------------------------------
ConditionTests.cpp:<line number>
...............................................................................
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.int_seven == 7 )
with expansion:
7 == 7
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.float_nine_point_one == Approx( 9.1f ) )
with expansion:
9.1f == Approx( 9.1000003815 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.double_pi == Approx( 3.1415926535 ) )
with expansion:
3.1415926535 == Approx( 3.1415926535 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.str_hello == "hello" )
with expansion:
"hello" == "hello"
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( "hello" == data.str_hello )
with expansion:
"hello" == "hello"
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.str_hello.size() == 5 )
with expansion:
5 == 5
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( x == Approx( 1.3 ) )
with expansion:
1.3 == Approx( 1.3 )
-------------------------------------------------------------------------------
Equality checks that should fail
'Not' checks that should fail
-------------------------------------------------------------------------------
ConditionTests.cpp:<line number>
...............................................................................
ConditionTests.cpp:<line number>: FAILED:
CHECK( data.int_seven == 6 )
with expansion:
7 == 6
CHECK( false != false )
ConditionTests.cpp:<line number>: FAILED:
CHECK( data.int_seven == 8 )
with expansion:
7 == 8
-------------------------------------------------------------------------------
Inequality checks that should succeed
-------------------------------------------------------------------------------
ConditionTests.cpp:<line number>
...............................................................................
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.int_seven != 6 )
with expansion:
7 != 6
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.int_seven != 8 )
with expansion:
7 != 8
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.float_nine_point_one != Approx( 9.11f ) )
with expansion:
9.1f != Approx( 9.1099996567 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.float_nine_point_one != Approx( 9.0f ) )
with expansion:
9.1f != Approx( 9.0 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.float_nine_point_one != Approx( 1 ) )
with expansion:
9.1f != Approx( 1.0 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.float_nine_point_one != Approx( 0 ) )
with expansion:
9.1f != Approx( 0.0 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.double_pi != Approx( 3.1415 ) )
with expansion:
3.1415926535 != Approx( 3.1415 )
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.str_hello != "goodbye" )
with expansion:
"hello" != "goodbye"
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.str_hello != "hell" )
with expansion:
"hello" != "hell"
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.str_hello != "hello1" )
with expansion:
"hello" != "hello1"
ConditionTests.cpp:<line number>:
PASSED:
REQUIRE( data.str_hello.size() != 6 )
with expansion:
5 != 6
-------------------------------------------------------------------------------
Inequality checks that should fail
-------------------------------------------------------------------------------
ConditionTests.cpp:<line number>
...............................................................................
CHECK( true != true )
ConditionTests.cpp:<line number>: FAILED:
CHECK( data.int_seven != 7 )
CHECK( !true )
with expansion:
7 != 7
false
ConditionTests.cpp:<line number>: FAILED:
CHECK( data.float_nine_point_one != Approx( 9.1f ) )
with expansion:
9.1f != Approx( 9.1000003815 )
CHECK_FALSE( true )
===============================================================================
test cases: 19 | 15 passed | 3 failed | 1 failed as expected
assertions: 62 | 56 passed | 4 failed | 2 failed as expected
test cases: 2 | 1 passed | 1 failed
assertions: 5 | 1 passed | 4 failed

View File

@ -1,29 +1,119 @@
<?xml version="1.1" encoding="UTF-8"?>
<testsuites>
<testsuite name="all tests" errors="12" failures="88" tests="804" hostname="tbd" time="{duration}" timestamp="tbd">
<testcase classname="global" name="toString(enum)" time="{duration}"/>
<testcase classname="global" name="toString(enum w/operator&lt;&lt;)" time="{duration}"/>
<testcase classname="global" name="toString(enum class)" time="{duration}"/>
<testcase classname="global" name="toString(enum class w/operator&lt;&lt;)" 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}"/>
<testcase classname="global" name="Approximate comparisons with ints" time="{duration}"/>
<testcase classname="global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
<testcase classname="global" name="Use a custom approx" time="{duration}"/>
<testcase classname="global" name="Approximate PI" time="{duration}"/>
<testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
<testsuite name="<exe-name>" errors="13" failures="68" tests="912" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="global" name="'Not' checks that should fail" time="{duration}">
<failure message="false != false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="true != true" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="!true" type="CHECK_FALSE">
ConditionTests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="!true" type="CHECK_FALSE">
ConditionTests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="!(1 == 1)" type="CHECK_FALSE">
ConditionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="'Not' checks that should succeed" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to true" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to false" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="negation" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="double negation" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="direct" time="{duration}"/>
<testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
<failure message="&quot;hello&quot; == &quot;world&quot;" type="REQUIRE">
ClassTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
<testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
<testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that fails" time="{duration}">
<failure message="1 == 2" type="REQUIRE">
ClassTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Equality checks that should succeed" time="{duration}"/>
<testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
<testcase classname="A couple of nested sections followed by a failure" name="root" time="{duration}">
<failure type="FAIL">
to infinity and beyond
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="A couple of nested sections followed by a failure" name="Outer/Inner" 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>
<failure message="{?} == {?}" type="CHECK">
TrickyTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="AllOf matcher" time="{duration}"/>
<testcase classname="global" name="An expression with side-effects should only be evaluated once" time="{duration}"/>
<testcase classname="global" name="An unchecked exception reports the line of the last assertion" time="{duration}">
<error message="{Unknown expression after the reported line}">
unexpected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Anonymous test case 1" time="{duration}"/>
<testcase classname="global" name="AnyOf matcher" time="{duration}"/>
<testcase classname="global" name="Approximate PI" time="{duration}"/>
<testcase classname="global" name="Approximate comparisons with different epsilons" time="{duration}"/>
<testcase classname="global" name="Approximate comparisons with floats" time="{duration}"/>
<testcase classname="global" name="Approximate comparisons with ints" time="{duration}"/>
<testcase classname="global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
<testcase classname="Assertions then sections" name="root" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/>
<testcase classname="global" name="Comparing function pointers" time="{duration}"/>
<testcase classname="global" name="Comparing member function pointers" time="{duration}"/>
<testcase classname="global" name="Comparisons between ints where one side is computed" time="{duration}"/>
<testcase classname="global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/>
<testcase classname="global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/>
<testcase classname="global" name="Contains string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; contains: &quot;not there&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
<error message="throwCustom()" type="REQUIRE_NOTHROW">
custom exception - not std
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Custom exceptions can be translated when testing for throwing as something else" time="{duration}">
<error message="throwCustom()" type="REQUIRE_THROWS_AS">
custom exception - not std
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Custom std-exceptions can be custom translated" time="{duration}">
<error type="TEST_CASE">
custom std exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Demonstrate that a non-const == is not used" time="{duration}"/>
<testcase classname="global" name="EndsWith string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; ends with: &quot;this&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Equality checks that should fail" time="{duration}">
<failure message="7 == 6" type="CHECK">
ConditionTests.cpp:<line number>
@ -65,7 +155,63 @@ ConditionTests.cpp:<line number>
ConditionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Inequality checks that should succeed" time="{duration}"/>
<testcase classname="global" name="Equality checks that should succeed" time="{duration}"/>
<testcase classname="global" name="Equals" time="{duration}"/>
<testcase classname="global" name="Equals string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; equals: &quot;something else&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Equals string matcher, with NULL" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="exact match" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="different case" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="wildcarded" time="{duration}"/>
<testcase classname="global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}">
<error message="thisThrows()" type="CHECK_THROWS_AS">
expected exception
ExceptionTests.cpp:<line number>
</error>
<failure message="thisDoesntThrow()" type="CHECK_THROWS_AS">
ExceptionTests.cpp:<line number>
</failure>
<error message="thisThrows()" type="CHECK_NOTHROW">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="FAIL aborts the test" time="{duration}">
<failure type="FAIL">
This is a failure
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="FAIL does not require an argument" time="{duration}">
<failure type="FAIL">
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Factorials are computed" time="{duration}"/>
<testcase classname="global" name="Generator over a range of pairs" time="{duration}"/>
<testcase classname="global" name="Generators over two ranges" time="{duration}"/>
<testcase classname="global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
<testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/>
<testcase classname="global" name="INFO gets logged on failure" time="{duration}">
<failure message="2 == 1" type="REQUIRE">
this message should be logged
so should this
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="INFO gets logged on failure, even if captured before successful assertions" time="{duration}">
<failure message="2 == 1" type="CHECK">
this message should be logged
MessageTests.cpp:<line number>
</failure>
<failure message="2 == 0" type="CHECK">
and this, but later
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Inequality checks that should fail" time="{duration}">
<failure message="7 != 7" type="CHECK">
ConditionTests.cpp:<line number>
@ -83,7 +229,51 @@ ConditionTests.cpp:<line number>
ConditionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Ordering comparison checks that should succeed" time="{duration}"/>
<testcase classname="global" name="Inequality checks that should succeed" time="{duration}"/>
<testcase classname="global" name="Less-than inequalities with different epsilons" 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}"/>
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped three times" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="plain string/Short wrap" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="plain string/As container" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="plain string/Indent first line differently" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="With newlines/No wrapping" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="With newlines/Trailing newline" time="{duration}"/>
<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="global" name="Long text is truncted" time="{duration}"/>
<testcase classname="global" name="ManuallyRegistered" time="{duration}"/>
<testcase classname="global" name="Matchers can be (AllOf) composed with the &amp;&amp; operator" time="{duration}"/>
<testcase classname="global" name="Matchers can be (AnyOf) composed with the || operator" time="{duration}"/>
<testcase classname="global" name="Matchers can be composed with both &amp;&amp; and ||" time="{duration}"/>
<testcase classname="global" name="Matchers can be composed with both &amp;&amp; and || - failing" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; ( ( contains: &quot;string&quot; or contains: &quot;different&quot; ) and contains: &quot;random&quot; )" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Matchers can be negated (Not) with the ! operator" time="{duration}"/>
<testcase classname="global" name="Matchers can be negated (Not) with the ! operator - failing" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; not contains: &quot;substring&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Mismatching exception messages failing the test" time="{duration}">
<failure message="expected exception" type="REQUIRE_THROWS_WITH">
ExceptionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Nice descriptive name" time="{duration}"/>
<testcase classname="global" name="Non-std exceptions can be translated" time="{duration}">
<error type="TEST_CASE">
custom exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="NotImplemented exception" time="{duration}"/>
<testcase classname="global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/>
<testcase classname="global" name="Operators at different namespace levels not hijacked by Koenig lookup" time="{duration}"/>
<testcase classname="global" name="Ordering comparison checks that should fail" time="{duration}">
<failure message="7 > 7" type="CHECK">
ConditionTests.cpp:<line number>
@ -143,155 +333,7 @@ ConditionTests.cpp:<line number>
ConditionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/>
<testcase classname="global" name="comparisons between int variables" time="{duration}"/>
<testcase classname="global" name="comparisons between const int variables" time="{duration}"/>
<testcase classname="global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/>
<testcase classname="global" name="Comparisons between ints where one side is computed" time="{duration}"/>
<testcase classname="global" name="Pointers can be compared to null" time="{duration}"/>
<testcase classname="global" name="'Not' checks that should succeed" time="{duration}"/>
<testcase classname="global" name="'Not' checks that should fail" time="{duration}">
<failure message="false != false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="true != true" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="!true" type="CHECK_FALSE">
ConditionTests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="!true" type="CHECK_FALSE">
ConditionTests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
ConditionTests.cpp:<line number>
</failure>
<failure message="!(1 == 1)" type="CHECK_FALSE">
ConditionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="When checked exceptions are thrown they can be expected or unexpected" time="{duration}"/>
<testcase classname="global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}">
<error message="thisThrows()" type="CHECK_THROWS_AS">
expected exception
ExceptionTests.cpp:<line number>
</error>
<failure message="thisDoesntThrow()" type="CHECK_THROWS_AS">
ExceptionTests.cpp:<line number>
</failure>
<error message="thisThrows()" type="CHECK_NOTHROW">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown directly they are always failures" time="{duration}">
<error type="TEST_CASE">
unexpected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="An unchecked exception reports the line of the last assertion" time="{duration}">
<error message="{Unknown expression after the reported line}">
unexpected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="When unchecked exceptions are thrown from sections they are always failures" name="section name" time="{duration}">
<error type="TEST_CASE">
unexpected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown from functions they are always failures" time="{duration}">
<error message="thisThrows() == 0" type="CHECK">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown during a REQUIRE the test should abort fail" time="{duration}">
<error message="thisThrows() == 0" type="REQUIRE">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown during a CHECK the test should abort and fail" time="{duration}">
<error message="thisThrows() == 0" type="CHECK">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Unexpected custom exceptions can be translated" time="{duration}">
<error type="TEST_CASE">
custom exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
<error message="throwCustom()" type="REQUIRE_NOTHROW">
custom exception - not std
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Custom exceptions can be translated when testing for throwing as something else" time="{duration}">
<error message="throwCustom()" type="REQUIRE_THROWS_AS">
custom exception - not std
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Unexpected exceptions can be translated" time="{duration}">
<error type="TEST_CASE">
3.14
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="NotImplemented exception" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="exact match" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="different case" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="wildcarded" time="{duration}"/>
<testcase classname="global" name="Mismatching exception messages failing the test" time="{duration}">
<failure message="expected exception" type="REQUIRE_THROWS_WITH">
ExceptionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Generators over two ranges" time="{duration}"/>
<testcase classname="global" name="Generator over a range of pairs" time="{duration}"/>
<testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/>
<testcase classname="global" name="SUCCEED counts as a test pass" time="{duration}"/>
<testcase classname="global" name="INFO gets logged on failure" time="{duration}">
<failure message="2 == 1" type="REQUIRE">
this message should be logged
so should this
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="INFO gets logged on failure, even if captured before successful assertions" time="{duration}">
<failure message="2 == 1" type="CHECK">
this message should be logged
MessageTests.cpp:<line number>
</failure>
<failure message="2 == 0" type="CHECK">
and this, but later
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="FAIL aborts the test" time="{duration}">
<failure type="FAIL">
This is a failure
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="FAIL does not require an argument" time="{duration}">
<failure type="FAIL">
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="SUCCESS does not require an argument" time="{duration}"/>
<testcase classname="global" name="Ordering comparison checks that should succeed" time="{duration}"/>
<testcase classname="Output from all sections is reported" name="one" time="{duration}">
<failure type="FAIL">
Message from section one
@ -304,12 +346,64 @@ Message from section two
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
<system-out>
Message from section one
Message from section two
</system-out>
</testcase>
<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}"/>
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Test spec from quoted name should have one filter" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at the start" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at the end" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at both ends" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Redundant wildcard at the start" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Redundant wildcard at the end" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Redundant wildcard at both ends" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at both ends, redundant at start" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Just wildcard" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Single tag" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Single tag, two matches" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Two tags" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Two tags, spare separated" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcarded name and tag" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Single tag exclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="One tag exclusion and one tag inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="One tag exclusion and one wldcarded name inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="One tag exclusion, using exclude:, and one wldcarded name inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="name exclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="wildcarded name exclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="wildcarded name exclusion with tag inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="wildcarded name exclusion, using exclude:, with tag inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="two wildcarded names" time="{duration}"/>
<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="Parsing a std::pair" time="{duration}"/>
<testcase classname="global" name="Pointers can be compared to null" time="{duration}"/>
<testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using ~" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/-r/console" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/-r/xml" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/-r xml and junit" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/--reporter/junit" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="debugger/-b" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="debugger/--break" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-a aborts after first failure" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-x 2 aborts after two failures" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-x must be greater than zero" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-x must be numeric" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="nothrow/-e" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="nothrow/--nothrow" time="{duration}"/>
<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="use-colour/without option" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="use-colour/auto" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="use-colour/yes" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="use-colour/no" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="use-colour/error" time="{duration}"/>
<testcase classname="global" name="SCOPED_INFO is reset for each loop" time="{duration}">
<failure message="10 &lt; 10" type="REQUIRE">
current counter 10
@ -317,30 +411,164 @@ i := 10
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="SUCCEED counts as a test pass" time="{duration}"/>
<testcase classname="global" name="SUCCESS does not require an argument" time="{duration}"/>
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/>
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
<testcase classname="Scenario: This is a really long scenario name to see how the list command deals with wrapping" name="Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up/And when: it is made smaller again/Then: the size goes down but the capacity stays the same" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: we reserve more space/Then: The capacity is increased but the size remains the same" time="{duration}"/>
<testcase classname="global" name="Sends stuff to stdout and stderr" time="{duration}">
<system-out>
A string sent directly to stdout
</system-out>
<system-err>
A string sent directly to stderr
</system-err>
</testcase>
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
<system-out>
Message from section one
Message from section two
</system-out>
</testcase>
<testcase classname="global" name="StartsWith string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; starts with: &quot;string&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="String matchers" time="{duration}"/>
<testcase classname="global" name="Strings can be rendered with colour" time="{duration}">
<system-out>
hello
hello
</system-out>
</testcase>
<testcase classname="global" name="Tabs and newlines show in output" time="{duration}">
<failure message="&quot;if ($b == 10) {
$a = 20;
}&quot;
==
&quot;if ($b == 10) {
$a = 20;
}
&quot;" type="CHECK">
MiscTests.cpp:<line number>
</failure>
</testcase>
<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="Test case with one argument" time="{duration}"/>
<testcase classname="global" name="Test enum bit values" time="{duration}"/>
<testcase classname="global" name="Text can be formatted using the Text class" time="{duration}"/>
<testcase classname="global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/>
<testcase classname="global" name="This test 'should' fail but doesn't" time="{duration}"/>
<testcase classname="Tracker" name="root" time="{duration}"/>
<testcase classname="Tracker" name="successfully close one section" time="{duration}"/>
<testcase classname="Tracker" name="fail one section" time="{duration}"/>
<testcase classname="Tracker" name="fail one section/re-enter after failed section" time="{duration}"/>
<testcase classname="Tracker" name="fail one section/re-enter after failed section and find next section" time="{duration}"/>
<testcase classname="Tracker" name="successfully close one section, then find another" time="{duration}"/>
<testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2" time="{duration}"/>
<testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
<testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
<testcase classname="Tracker" name="open a nested section" time="{duration}"/>
<testcase classname="Tracker" name="start a generator" time="{duration}"/>
<testcase classname="Tracker" name="start a generator/close outer section" time="{duration}"/>
<testcase classname="Tracker" name="start a generator/close outer section/Re-enter for second generation" time="{duration}"/>
<testcase classname="Tracker" name="start a generator/Start a new inner section" time="{duration}"/>
<testcase classname="Tracker" name="start a generator/Start a new inner section/Re-enter for second generation" time="{duration}"/>
<testcase classname="Tracker" name="start a generator/Fail an inner section" time="{duration}"/>
<testcase classname="Tracker" name="start a generator/Fail an inner section/Re-enter for second generation" time="{duration}"/>
<testcase classname="global" name="Unexpected exceptions can be translated" time="{duration}">
<error type="TEST_CASE">
3.14
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Use a custom approx" time="{duration}"/>
<testcase classname="Variadic macros" name="Section with one argument" time="{duration}"/>
<testcase classname="global" name="When checked exceptions are thrown they can be expected or unexpected" time="{duration}"/>
<testcase classname="global" name="When unchecked exceptions are thrown directly they are always failures" time="{duration}">
<error type="TEST_CASE">
unexpected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown during a CHECK the test should abort and fail" time="{duration}">
<error message="thisThrows() == 0" type="CHECK">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown during a REQUIRE the test should abort fail" time="{duration}">
<error message="thisThrows() == 0" type="REQUIRE">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="When unchecked exceptions are thrown from functions they are always failures" time="{duration}">
<error message="thisThrows() == 0" type="CHECK">
expected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="When unchecked exceptions are thrown from sections they are always failures" name="section name" time="{duration}">
<error type="TEST_CASE">
unexpected exception
ExceptionTests.cpp:<line number>
</error>
</testcase>
<testcase classname="global" name="Where the LHS is not a simple value" time="{duration}"/>
<testcase classname="global" name="Where there is more to the expression after the RHS" time="{duration}"/>
<testcase classname="global" name="X/level/0/a" time="{duration}"/>
<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="XmlEncode" name="normal string" time="{duration}"/>
<testcase classname="XmlEncode" name="empty string" time="{duration}"/>
<testcase classname="XmlEncode" name="string with ampersand" time="{duration}"/>
<testcase classname="XmlEncode" name="string with less-than" time="{duration}"/>
<testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/>
<testcase classname="XmlEncode" name="string with quotes" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/>
<testcase classname="global" name="atomic if" time="{duration}"/>
<testcase classname="global" name="boolean member" time="{duration}"/>
<testcase classname="global" name="checkedElse" time="{duration}"/>
<testcase classname="global" name="checkedElse, failing" time="{duration}">
<failure message="false" type="CHECKED_ELSE">
MiscTests.cpp:<line number>
</failure>
<failure message="false" type="REQUIRE">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="checkedIf" time="{duration}"/>
<testcase classname="global" name="checkedIf, failing" time="{duration}">
<failure message="false" type="CHECKED_IF">
MiscTests.cpp:<line number>
</failure>
<failure message="false" type="REQUIRE">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="comparisons between const int variables" time="{duration}"/>
<testcase classname="global" name="comparisons between int variables" time="{duration}"/>
<testcase classname="even more nested SECTION tests" name="c/d (leaf)" time="{duration}"/>
<testcase classname="even more nested SECTION tests" name="c/e (leaf)" time="{duration}"/>
<testcase classname="even more nested SECTION tests" name="f (leaf)" time="{duration}"/>
<testcase classname="global" name="just failure" time="{duration}">
<failure type="FAIL">
Previous info should not be seen
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="sends information to INFO" time="{duration}">
<failure message="false" type="REQUIRE">
hi
i := 7
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/>
<testcase classname="random SECTION tests" name="s1" time="{duration}"/>
<testcase classname="random SECTION tests" name="s2" time="{duration}"/>
<testcase classname="nested SECTION tests" name="s1" time="{duration}"/>
<testcase classname="nested SECTION tests" name="s1/s2" time="{duration}"/>
<testcase classname="more nested SECTION tests" name="s2/s1" time="{duration}">
<failure message="1 == 2" type="REQUIRE">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="looped SECTION tests" name="s1" time="{duration}">
<failure message="0 > 1" type="CHECK">
MiscTests.cpp:<line number>
@ -372,138 +600,22 @@ Testing if fib[7] (21) is even
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Sends stuff to stdout and stderr" time="{duration}">
<system-out>
A string sent directly to stdout
</system-out>
<system-err>
A string sent directly to stderr
</system-err>
</testcase>
<testcase classname="global" name="null strings" time="{duration}"/>
<testcase classname="global" name="checkedIf" time="{duration}"/>
<testcase classname="global" name="checkedIf, failing" time="{duration}">
<failure message="false" type="CHECKED_IF">
MiscTests.cpp:<line number>
</failure>
<failure message="false" type="REQUIRE">
<testcase classname="more nested SECTION tests" name="s2/s1" time="{duration}">
<failure message="1 == 2" type="REQUIRE">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="checkedElse" time="{duration}"/>
<testcase classname="global" name="checkedElse, failing" time="{duration}">
<failure message="false" type="CHECKED_ELSE">
MiscTests.cpp:<line number>
</failure>
<failure message="false" type="REQUIRE">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="send a single char to INFO" time="{duration}">
<failure message="false" type="REQUIRE">
3
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="atomic if" time="{duration}"/>
<testcase classname="global" name="String matchers" time="{duration}"/>
<testcase classname="global" name="Contains string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; contains: &quot;not there&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="StartsWith string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; starts with: &quot;string&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="EndsWith string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; ends with: &quot;this&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Equals string matcher" time="{duration}">
<failure message="&quot;this string contains 'abc' as a substring&quot; equals: &quot;something else&quot;" type="CHECK_THAT">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Equals string matcher, with NULL" time="{duration}"/>
<testcase classname="global" name="AllOf matcher" time="{duration}"/>
<testcase classname="global" name="AnyOf matcher" time="{duration}"/>
<testcase classname="global" name="Equals" time="{duration}"/>
<testcase classname="global" name="Factorials are computed" time="{duration}"/>
<testcase classname="global" name="Nice descriptive name" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="root" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="resizing bigger changes size and capacity" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="reserving bigger changes capacity but not size" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="reserving smaller does not change size or capacity" time="{duration}"/>
<testcase classname="A couple of nested sections followed by a failure" name="root" time="{duration}">
<failure type="FAIL">
to infinity and beyond
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="A couple of nested sections followed by a failure" name="Outer/Inner" time="{duration}"/>
<testcase classname="more nested SECTION tests" name="s1/s3" time="{duration}"/>
<testcase classname="more nested SECTION tests" name="s1/s4" time="{duration}"/>
<testcase classname="nested SECTION tests" name="s1" time="{duration}"/>
<testcase classname="nested SECTION tests" name="s1/s2" time="{duration}"/>
<testcase classname="global" name="non streamable - with conv. op" time="{duration}"/>
<testcase classname="global" name="not allowed" time="{duration}"/>
<testcase classname="global" name="Tabs and newlines show in output" time="{duration}">
<failure message="&quot;if ($b == 10) {
$a = 20;
}&quot;
==
&quot;if ($b == 10) {
$a = 20;
}
&quot;" type="CHECK">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/>
<testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
<testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
<testcase classname="global" name="toString on wchar_t returns the string contents" time="{duration}"/>
<testcase classname="XmlEncode" name="normal string" time="{duration}"/>
<testcase classname="XmlEncode" name="empty string" time="{duration}"/>
<testcase classname="XmlEncode" name="string with ampersand" time="{duration}"/>
<testcase classname="XmlEncode" name="string with less-than" time="{duration}"/>
<testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/>
<testcase classname="XmlEncode" name="string with quotes" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/>
<testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/>
<testcase classname="global" name="long long" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using ~" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/-r/console" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/-r/xml" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="reporter/--reporter/junit" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="debugger/-b" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="debugger/--break" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-a aborts after first failure" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-x 2 aborts after two failures" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-x must be greater than zero" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="abort/-x must be numeric" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="nothrow/-e" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="nothrow/--nothrow" time="{duration}"/>
<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}"/>
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped three times" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="plain string/Short wrap" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="plain string/As container" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="plain string/Indent first line differently" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="With newlines/No wrapping" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="With newlines/Trailing newline" time="{duration}"/>
<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="global" name="null strings" time="{duration}"/>
<testcase classname="global" name="pair&lt;pair&lt;int,const char *,pair&lt;std::string,int> > -> toString" time="{duration}"/>
<testcase classname="global" name="pointer to class" time="{duration}"/>
<testcase classname="random SECTION tests" name="s1" time="{duration}"/>
<testcase classname="random SECTION tests" name="s2" 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}"/>
@ -511,128 +623,53 @@ MiscTests.cpp:<line number>
<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
hello
</system-out>
</testcase>
<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 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>
<failure message="{?} == {?}" type="CHECK">
TrickyTests.cpp:<line number>
<testcase classname="global" name="send a single char to INFO" time="{duration}">
<failure message="false" type="REQUIRE">
3
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="sends information to INFO" time="{duration}">
<failure message="false" type="REQUIRE">
hi
i := 7
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="std::pair&lt;int,const std::string> -> toString" time="{duration}"/>
<testcase classname="global" name="std::pair&lt;int,std::string> -> toString" time="{duration}"/>
<testcase classname="global" name="std::vector&lt;std::pair&lt;std::string,int> > -> toString" time="{duration}"/>
<testcase classname="global" name="string literals of different sizes can be compared" time="{duration}">
<failure message="&quot;first&quot; == &quot;second&quot;" type="REQUIRE">
TrickyTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="An expression with side-effects should only be evaluated once" time="{duration}"/>
<testcase classname="global" name="Operators at different namespace levels not hijacked by Koenig lookup" time="{duration}"/>
<testcase classname="global" name="Demonstrate that a non-const == is not used" time="{duration}"/>
<testcase classname="global" name="Test enum bit values" time="{duration}"/>
<testcase classname="global" name="boolean member" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to true" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to false" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="negation" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="double negation" time="{duration}"/>
<testcase classname="(unimplemented) static bools can be evaluated" name="direct" time="{duration}"/>
<testcase classname="global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/>
<testcase classname="Assertions then sections" name="root" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/>
<testcase classname="global" name="non streamable - with conv. op" time="{duration}"/>
<testcase classname="global" name="Comparing function pointers" time="{duration}"/>
<testcase classname="global" name="Comparing member function pointers" time="{duration}"/>
<testcase classname="global" name="pointer to class" time="{duration}"/>
<testcase classname="global" name="null_ptr" time="{duration}"/>
<testcase classname="global" name="X/level/0/a" time="{duration}"/>
<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 on const wchar_t const pointer returns the string contents" time="{duration}"/>
<testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
<testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
<testcase classname="global" name="toString on wchar_t returns the string contents" 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&lt;has_toString )" time="{duration}"/>
<testcase classname="global" name="toString( has_toString )" time="{duration}"/>
<testcase classname="global" name="toString( vectors&lt;has_maker )" time="{duration}"/>
<testcase classname="global" name="toString( vectors&lt;has_maker_and_toString )" time="{duration}"/>
<testcase classname="global" name="std::pair&lt;int,std::string> -> toString" time="{duration}"/>
<testcase classname="global" name="std::pair&lt;int,const std::string> -> toString" time="{duration}"/>
<testcase classname="global" name="std::vector&lt;std::pair&lt;std::string,int> > -> toString" time="{duration}"/>
<testcase classname="global" name="pair&lt;pair&lt;int,const char *,pair&lt;std::string,int> > -> toString" time="{duration}"/>
<testcase classname="global" name="toString( vectors&lt;has_toString )" time="{duration}"/>
<testcase classname="global" name="toString(enum w/operator&lt;&lt;)" time="{duration}"/>
<testcase classname="global" name="toString(enum)" time="{duration}"/>
<testcase classname="global" name="vector&lt;int> -> toString" time="{duration}"/>
<testcase classname="global" name="vector&lt;string> -> toString" time="{duration}"/>
<testcase classname="global" name="vector&lt;int,allocator> -> toString" time="{duration}"/>
<testcase classname="global" name="vec&lt;vec&lt;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}"/>
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Test spec from quoted name should have one filter" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at the start" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at the end" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at both ends" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Redundant wildcard at the start" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Redundant wildcard at the end" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Redundant wildcard at both ends" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcard at both ends, redundant at start" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Just wildcard" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Single tag" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Single tag, two matches" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Two tags" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Two tags, spare separated" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Wildcarded name and tag" time="{duration}"/>
<testcase classname="Parse test names and tags" name="Single tag exclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="One tag exclusion and one tag inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="One tag exclusion and one wldcarded name inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="One tag exclusion, using exclude:, and one wldcarded name inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="name exclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="wildcarded name exclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="wildcarded name exclusion with tag inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="wildcarded name exclusion, using exclude:, with tag inclusion" time="{duration}"/>
<testcase classname="Parse test names and tags" name="two wildcarded names" time="{duration}"/>
<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&lt;>" time="{duration}"/>
<testcase classname="global" name="tuple&lt;int>" time="{duration}"/>
<testcase classname="global" name="tuple&lt;float,int>" time="{duration}"/>
<testcase classname="global" name="tuple&lt;string,string>" time="{duration}"/>
<testcase classname="global" name="tuple&lt;tuple&lt;int>,tuple&lt;>,float>" time="{duration}"/>
<testcase classname="global" name="tuple&lt;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}"/>
<testcase classname="global" name="Test case with one argument" time="{duration}"/>
<testcase classname="Variadic macros" name="Section with one argument" time="{duration}"/>
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/>
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up/And when: it is made smaller again/Then: the size goes down but the capacity stays the same" time="{duration}"/>
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: we reserve more space/Then: The capacity is increased but the size remains the same" time="{duration}"/>
<testcase classname="Scenario: This is a really long scenario name to see how the list command deals with wrapping" name="Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
<testcase classname="section tracking" name="root" time="{duration}"/>
<testcase classname="section tracking" name="test case with no sections" time="{duration}"/>
<testcase classname="section tracking" name="test case with one section" time="{duration}"/>
<testcase classname="section tracking" name="test case with two consecutive sections" time="{duration}"/>
<testcase classname="section tracking" name="test case with one section within another" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="root" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="resizing bigger changes size and capacity" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="reserving bigger changes capacity but not size" time="{duration}"/>
<testcase classname="vectors can be sized and resized" name="reserving smaller does not change size or capacity" time="{duration}"/>
<testcase classname="xmlentitycheck" name="embedded xml" time="{duration}"/>
<testcase classname="xmlentitycheck" name="encoded chars" time="{duration}"/>
<system-out>
A string sent directly to stdout
Message from section one
Message from section two
A string sent directly to stdout
hello
hello
</system-out>

File diff suppressed because it is too large Load Diff

View File

@ -13,18 +13,18 @@ namespace
class TestClass
{
std::string s;
public:
TestClass()
: s( "hello" )
{}
void succeedingCase()
{
{
REQUIRE( s == "hello" );
}
void failingCase()
{
{
REQUIRE( s == "world" );
}
};
@ -38,20 +38,20 @@ METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test r
struct Fixture
{
Fixture() : m_a( 1 ) {}
int m_a;
};
TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[class]" )
{
REQUIRE( m_a == 1 );
{
REQUIRE( m_a == 1 );
}
// We should be able to write our tests within a different namespace
namespace Inner
{
TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that fails", "[.][class][failing]" )
{
REQUIRE( m_a == 2 );
{
REQUIRE( m_a == 2 );
}
}

View File

@ -7,7 +7,7 @@
*/
#include "catch.hpp"
#include "catch_test_spec_parser.hpp"
#include "internal/catch_test_spec_parser.hpp"
#ifdef __clang__
# pragma clang diagnostic ignored "-Wc++98-compat"

View File

@ -22,7 +22,7 @@ struct TestData {
float_nine_point_one( 9.1f ),
double_pi( 3.1415926535 )
{}
int int_seven;
std::string str_hello;
float float_nine_point_one;
@ -37,7 +37,7 @@ struct TestDef {
TestDef& operator[]( const std::string& ) {
return *this;
}
};
// The "failing" tests all use the CHECK macro, which continues if the specific test fails.
@ -49,14 +49,14 @@ TEST_CASE( "Equality checks that should succeed", "" )
TestDef td;
td + "hello" + "hello";
TestData data;
REQUIRE( data.int_seven == 7 );
REQUIRE( data.float_nine_point_one == Approx( 9.1f ) );
REQUIRE( data.double_pi == Approx( 3.1415926535 ) );
REQUIRE( data.str_hello == "hello" );
REQUIRE( "hello" == data.str_hello );
REQUIRE( "hello" == data.str_hello );
REQUIRE( data.str_hello.size() == 5 );
double x = 1.1 + 0.1 + 0.1;
@ -66,7 +66,7 @@ TEST_CASE( "Equality checks that should succeed", "" )
TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" )
{
TestData data;
CHECK( data.int_seven == 6 );
CHECK( data.int_seven == 8 );
CHECK( data.int_seven == 0 );
@ -87,7 +87,7 @@ TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" )
TEST_CASE( "Inequality checks that should succeed", "" )
{
TestData data;
REQUIRE( data.int_seven != 6 );
REQUIRE( data.int_seven != 8 );
REQUIRE( data.float_nine_point_one != Approx( 9.11f ) );
@ -101,10 +101,10 @@ TEST_CASE( "Inequality checks that should succeed", "" )
REQUIRE( data.str_hello.size() != 6 );
}
TEST_CASE( "Inequality checks that should fail", "[.][failing]" )
TEST_CASE( "Inequality checks that should fail", "[.][failing][!shouldfail]" )
{
TestData data;
CHECK( data.int_seven != 7 );
CHECK( data.float_nine_point_one != Approx( 9.1f ) );
CHECK( data.double_pi != Approx( 3.1415926535 ) );
@ -116,7 +116,7 @@ TEST_CASE( "Inequality checks that should fail", "[.][failing]" )
TEST_CASE( "Ordering comparison checks that should succeed", "" )
{
TestData data;
REQUIRE( data.int_seven < 8 );
REQUIRE( data.int_seven > 6 );
REQUIRE( data.int_seven > 0 );
@ -126,14 +126,14 @@ TEST_CASE( "Ordering comparison checks that should succeed", "" )
REQUIRE( data.int_seven >= 6 );
REQUIRE( data.int_seven <= 7 );
REQUIRE( data.int_seven <= 8 );
REQUIRE( data.float_nine_point_one > 9 );
REQUIRE( data.float_nine_point_one < 10 );
REQUIRE( data.float_nine_point_one < 9.2 );
REQUIRE( data.str_hello <= "hello" );
REQUIRE( data.str_hello >= "hello" );
REQUIRE( data.str_hello < "hellp" );
REQUIRE( data.str_hello < "zebra" );
REQUIRE( data.str_hello > "hellm" );
@ -143,7 +143,7 @@ TEST_CASE( "Ordering comparison checks that should succeed", "" )
TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" )
{
TestData data;
CHECK( data.int_seven > 7 );
CHECK( data.int_seven < 7 );
CHECK( data.int_seven > 8 );
@ -153,11 +153,11 @@ TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" )
CHECK( data.int_seven >= 8 );
CHECK( data.int_seven <= 6 );
CHECK( data.float_nine_point_one < 9 );
CHECK( data.float_nine_point_one > 10 );
CHECK( data.float_nine_point_one > 9.2 );
CHECK( data.str_hello > "hello" );
CHECK( data.str_hello < "hello" );
CHECK( data.str_hello > "hellp" );
@ -178,7 +178,7 @@ TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigne
unsigned long ul = 4;
char c = 5;
unsigned char uc = 6;
REQUIRE( i == 1 );
REQUIRE( ui == 2 );
REQUIRE( l == 3 );
@ -215,7 +215,7 @@ TEST_CASE( "comparisons between int variables", "" )
unsigned short unsigned_short_var = 1;
unsigned int unsigned_int_var = 1;
unsigned long unsigned_long_var = 1L;
REQUIRE( long_var == unsigned_char_var );
REQUIRE( long_var == unsigned_short_var );
REQUIRE( long_var == unsigned_int_var );
@ -252,7 +252,7 @@ template<typename T>
struct Ex
{
Ex( T ){}
bool operator == ( const T& ) const { return true; }
T operator * ( const T& ) const { return T(); }
};
@ -273,13 +273,13 @@ TEST_CASE( "Pointers can be compared to null", "" )
{
TestData* p = CATCH_NULL;
TestData* pNULL = CATCH_NULL;
REQUIRE( p == CATCH_NULL );
REQUIRE( p == pNULL );
TestData data;
p = &data;
REQUIRE( p != CATCH_NULL );
const TestData* cp = p;
@ -290,7 +290,7 @@ TEST_CASE( "Pointers can be compared to null", "" )
REQUIRE( returnsNull() == CATCH_NULL );
REQUIRE( returnsConstNull() == CATCH_NULL );
REQUIRE( CATCH_NULL != p );
}
@ -304,7 +304,7 @@ TEST_CASE( "Pointers can be compared to null", "" )
TEST_CASE( "'Not' checks that should succeed", "" )
{
bool falseValue = false;
REQUIRE( false == false );
REQUIRE( true == true );
REQUIRE( !false );
@ -320,15 +320,15 @@ TEST_CASE( "'Not' checks that should succeed", "" )
TEST_CASE( "'Not' checks that should fail", "[.][failing]" )
{
bool trueValue = true;
CHECK( false != false );
CHECK( true != true );
CHECK( !true );
CHECK_FALSE( true );
CHECK( !trueValue );
CHECK_FALSE( trueValue );
CHECK( !(1 == 1) );
CHECK_FALSE( 1 == 1 );
}

View File

@ -38,7 +38,7 @@ TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) {
// Enum class without user-provided stream operator
enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 };
TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) {
TEST_CASE( "toString(enum class)", "[toString][enum][enumClass][c++11][.]" ) {
EnumClass1 e0 = EnumClass1::EnumClass1Value0;
CHECK( Catch::toString(e0) == "0" );
EnumClass1 e1 = EnumClass1::EnumClass1Value1;
@ -59,7 +59,7 @@ inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
}
}
TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) {
TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass][c++11][.]" ) {
EnumClass2 e0 = EnumClass2::EnumClass2Value0;
CHECK( Catch::toString(e0) == "E2/V0" );
EnumClass2 e1 = EnumClass2::EnumClass2Value1;

View File

@ -96,32 +96,61 @@ public:
CustomException( const std::string& msg )
: m_msg( msg )
{}
std::string getMessage() const
{
return m_msg;
}
private:
std::string m_msg;
};
class CustomStdException : public std::exception
{
public:
CustomStdException( const std::string& msg )
: m_msg( msg )
{}
~CustomStdException() CATCH_NOEXCEPT {}
std::string getMessage() const
{
return m_msg;
}
private:
std::string m_msg;
};
CATCH_TRANSLATE_EXCEPTION( CustomException& ex )
{
return ex.getMessage();
}
CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex )
{
return ex.getMessage();
}
CATCH_TRANSLATE_EXCEPTION( double& ex )
{
return Catch::toString( ex );
}
TEST_CASE("Unexpected custom exceptions can be translated", "[.][failing]" )
TEST_CASE("Non-std exceptions can be translated", "[.][failing]" )
{
if( Catch::alwaysTrue() )
throw CustomException( "custom exception" );
}
TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing]" )
{
if( Catch::alwaysTrue() )
throw CustomException( "custom std exception" );
}
inline void throwCustom() {
if( Catch::alwaysTrue() )
throw CustomException( "custom exception - not std" );

View File

@ -19,10 +19,10 @@ inline int multiply( int a, int b )
CATCH_TEST_CASE( "Generators over two ranges", "[generators]" )
{
using namespace Catch::Generators;
int i = CATCH_GENERATE( between( 1, 5 ).then( values( 15, 20, 21 ).then( 36 ) ) );
int j = CATCH_GENERATE( between( 100, 107 ) );
CATCH_REQUIRE( multiply( i, 2 ) == i*2 );
CATCH_REQUIRE( multiply( j, 2 ) == j*2 );
}
@ -32,11 +32,11 @@ struct IntPair { int first, second; };
CATCH_TEST_CASE( "Generator over a range of pairs", "[generators]" )
{
using namespace Catch::Generators;
IntPair p[] = { { 0, 1 }, { 2, 3 } };
IntPair* i = CATCH_GENERATE( between( p, &p[1] ) );
CATCH_REQUIRE( i->first == i->second-1 );
}

View File

@ -38,7 +38,7 @@ TEST_CASE( "INFO gets logged on failure, even if captured before successful asse
CHECK( a == 2 );
INFO( "this message should be logged" );
CHECK( a == 1 );
INFO( "and this, but later" );
@ -85,7 +85,7 @@ TEST_CASE( "Standard output from all sections is reported", "[messages][.]" )
{
std::cout << "Message from section one" << std::endl;
}
SECTION( "two", "" )
{
std::cout << "Message from section two" << std::endl;

View File

@ -7,19 +7,21 @@
*/
#include "catch.hpp"
#include "catch_xmlwriter.hpp"
#include <iostream>
#ifdef __clang__
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
# pragma clang diagnostic ignored "-Wc++98-compat"
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#endif
#include "../include/internal/catch_xmlwriter.hpp"
#include <iostream>
TEST_CASE( "random SECTION tests", "[.][sections][failing]" )
{
int a = 1;
int b = 2;
SECTION( "s1", "doesn't equal" )
{
REQUIRE( a != b );
@ -36,7 +38,7 @@ TEST_CASE( "nested SECTION tests", "[.][sections][failing]" )
{
int a = 1;
int b = 2;
SECTION( "s1", "doesn't equal" )
{
REQUIRE( a != b );
@ -53,7 +55,7 @@ TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" )
{
int a = 1;
int b = 2;
SECTION( "s1", "doesn't equal" )
{
SECTION( "s2", "equal" )
@ -78,29 +80,32 @@ TEST_CASE( "even more nested SECTION tests", "[sections]" )
{
SECTION( "d (leaf)", "" )
{
SUCCEED(""); // avoid failing due to no tests
}
SECTION( "e (leaf)", "" )
{
SUCCEED(""); // avoid failing due to no tests
}
}
SECTION( "f (leaf)", "" )
{
SUCCEED(""); // avoid failing due to no tests
}
}
TEST_CASE( "looped SECTION tests", "[.][failing][sections]" )
{
int a = 1;
for( int b = 0; b < 10; ++b )
{
std::ostringstream oss;
oss << "b is currently: " << b;
SECTION( "s1", oss.str() )
{
CHECK( b > a );
CHECK( b > a );
}
}
}
@ -108,18 +113,18 @@ TEST_CASE( "looped SECTION tests", "[.][failing][sections]" )
TEST_CASE( "looped tests", "[.][failing]" )
{
static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 };
for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i )
{
INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" );
CHECK( ( fib[i] % 2 ) == 0 );
CHECK( ( fib[i] % 2 ) == 0 );
}
}
TEST_CASE( "Sends stuff to stdout and stderr", "[.]" )
{
std::cout << "A string sent directly to stdout" << std::endl;
std::cerr << "A string sent directly to stderr" << std::endl;
}
@ -157,7 +162,7 @@ inline bool testCheckedElse( bool flag )
{
CHECKED_ELSE( flag )
return false;
return true;
}
@ -175,24 +180,24 @@ TEST_CASE( "xmlentitycheck", "" )
{
SECTION( "embedded xml", "<test>it should be possible to embed xml characters, such as <, \" or &, or even whole <xml>documents</xml> within an attribute</test>" )
{
// No test
SUCCEED(""); // We need this here to stop it failing due to no tests
}
SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" )
{
// No test
SUCCEED(""); // We need this here to stop it failing due to no tests
}
}
TEST_CASE( "send a single char to INFO", "[failing][.]" )
{
INFO(3);
REQUIRE(false);
REQUIRE(false);
}
TEST_CASE( "atomic if", "[failing][0]")
{
size_t x = 0;
if( x )
REQUIRE(x > 0);
else
@ -203,10 +208,16 @@ inline const char* testStringForMatching()
{
return "this string contains 'abc' as a substring";
}
inline const char* testStringForMatching2()
{
return "some completely different text that contains one common word";
}
using namespace Catch::Matchers;
TEST_CASE("String matchers", "[matchers]" )
{
REQUIRE_THAT( testStringForMatching(), Contains( "string" ) );
REQUIRE_THAT( testStringForMatching(), Contains( "string" ) );
CHECK_THAT( testStringForMatching(), Contains( "abc" ) );
CHECK_THAT( testStringForMatching(), StartsWith( "this" ) );
@ -251,6 +262,42 @@ TEST_CASE("Equals", "[matchers]")
CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) );
}
TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]")
{
CHECK_THAT( testStringForMatching(),
Contains( "string" ) &&
Contains( "abc" ) &&
Contains( "substring" ) &&
Contains( "contains" ) );
}
TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]")
{
CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) );
CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) );
}
TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]")
{
CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) );
}
TEST_CASE("Matchers can be composed with both && and || - failing", "[matchers][operators][operator||][operator&&][.failing]")
{
CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) );
}
TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]")
{
CHECK_THAT( testStringForMatching(), !Contains( "different" ) );
}
TEST_CASE("Matchers can be negated (Not) with the ! operator - failing", "[matchers][operators][not][.failing]")
{
CHECK_THAT( testStringForMatching(), !Contains( "substring" ) );
}
inline unsigned int Factorial( unsigned int number )
{
// return number <= 1 ? number : Factorial(number-1)*number;
@ -292,38 +339,38 @@ TEST_CASE( "second tag", "[tag2]" )
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
SECTION( "resizing bigger changes size and capacity", "" ) {
v.resize( 10 );
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "resizing smaller changes size but not capacity", "" ) {
v.resize( 0 );
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
SECTION( "We can use the 'swap trick' to reset the capacity", "" ) {
std::vector<int> empty;
empty.swap( v );
REQUIRE( v.capacity() == 0 );
}
}
SECTION( "reserving bigger changes capacity but not size", "" ) {
v.reserve( 10 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "reserving smaller does not change size or capacity", "" ) {
v.reserve( 0 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
}
@ -359,27 +406,27 @@ TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) {
TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) {
const wchar_t * const s = L"wide load";
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
const wchar_t * const s = L"wide load";
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
}
TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) {
const wchar_t * s = L"wide load";
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
const wchar_t * s = L"wide load";
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
}
TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
wchar_t * const s = const_cast<wchar_t* const>( L"wide load" );
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
wchar_t * const s = const_cast<wchar_t* const>( L"wide load" );
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
}
TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
wchar_t * s = const_cast<wchar_t*>( L"wide load" );
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
wchar_t * s = const_cast<wchar_t*>( L"wide load" );
std::string result = Catch::toString( s );
CHECK( result == "\"wide load\"" );
}
inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) {
@ -411,17 +458,17 @@ TEST_CASE( "XmlEncode" ) {
REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" );
}
SECTION( "string with control char (1)" ) {
REQUIRE( encode( "[\x01]" ) == "[&#x1]" );
REQUIRE( encode( "[\x01]" ) == "[&#x01;]" );
}
SECTION( "string with control char (x7F)" ) {
REQUIRE( encode( "[\x7F]" ) == "[&#x7F]" );
REQUIRE( encode( "[\x7F]" ) == "[&#x7F;]" );
}
}
#ifdef CATCH_CONFIG_CPP11_LONG_LONG
TEST_CASE( "long long" ) {
TEST_CASE( "long long", "[c++11][.]" ) {
long long l = std::numeric_limits<long long>::max();
REQUIRE( l == std::numeric_limits<long long>::max() );
}
#endif
@ -431,3 +478,12 @@ TEST_CASE( "long long" ) {
// int x = 10/i; // This should cause the signal to fire
// CHECK( x == 0 );
//}
TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" )
{
SUCCEED( "oops!" );
}
TEST_CASE( "# A test name that starts with a #" ) {
SUCCEED( "yay" );
}

View File

@ -0,0 +1,328 @@
/*
* Created by Phil on 1/10/2015.
* Copyright 2015 Two Blue Cubes Ltd
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "internal/catch_suppress_warnings.h"
#include "internal/catch_test_case_tracker.hpp"
namespace Catch
{
class LocalContext {
public:
TrackerContext& operator()() const {
return TrackerContext::instance();
}
};
} // namespace Catch
inline Catch::TrackerContext& C_A_T_C_H_Context() {
return Catch::TrackerContext::instance();
}
// -------------------
#include "catch.hpp"
using namespace Catch;
//inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) {
//
// REQUIRE( C_A_T_C_H_Context().i() == 42 );
//}
TEST_CASE( "Tracker", "" ) {
TrackerContext ctx;
ctx.startRun();
ctx.startCycle();
ITracker& testCase = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase.isOpen() );
ITracker& s1 = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1.isOpen() );
SECTION( "successfully close one section", "" ) {
s1.close();
REQUIRE( s1.isSuccessfullyCompleted() );
REQUIRE( testCase.isComplete() == false );
testCase.close();
REQUIRE( ctx.completedCycle() );
REQUIRE( testCase.isSuccessfullyCompleted() );
}
SECTION( "fail one section", "" ) {
s1.fail();
REQUIRE( s1.isComplete() );
REQUIRE( s1.isSuccessfullyCompleted() == false );
REQUIRE( testCase.isComplete() == false );
testCase.close();
REQUIRE( ctx.completedCycle() );
REQUIRE( testCase.isSuccessfullyCompleted() == false );
SECTION( "re-enter after failed section", "" ) {
ctx.startCycle();
ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase2.isOpen() );
ITracker& s1b = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1b.isOpen() == false );
testCase2.close();
REQUIRE( ctx.completedCycle() );
REQUIRE( testCase.isComplete() );
REQUIRE( testCase.isSuccessfullyCompleted() );
}
SECTION( "re-enter after failed section and find next section", "" ) {
ctx.startCycle();
ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase2.isOpen() );
ITracker& s1b = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1b.isOpen() == false );
ITracker& s2 = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2.isOpen() );
s2.close();
REQUIRE( ctx.completedCycle() );
testCase2.close();
REQUIRE( testCase.isComplete() );
REQUIRE( testCase.isSuccessfullyCompleted() );
}
}
SECTION( "successfully close one section, then find another", "" ) {
s1.close();
ITracker& s2 = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2.isOpen() == false );
testCase.close();
REQUIRE( testCase.isComplete() == false );
SECTION( "Re-enter - skips S1 and enters S2", "" ) {
ctx.startCycle();
ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase2.isOpen() );
ITracker& s1b = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1b.isOpen() == false );
ITracker& s2b = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2b.isOpen() );
REQUIRE( ctx.completedCycle() == false );
SECTION ("Successfully close S2") {
s2b.close();
REQUIRE( ctx.completedCycle() );
REQUIRE( s2b.isSuccessfullyCompleted() );
REQUIRE( testCase2.isComplete() == false );
testCase2.close();
REQUIRE( testCase2.isSuccessfullyCompleted() );
}
SECTION ("fail S2") {
s2b.fail();
REQUIRE( ctx.completedCycle() );
REQUIRE( s2b.isComplete() );
REQUIRE( s2b.isSuccessfullyCompleted() == false );
testCase2.close();
REQUIRE( testCase2.isSuccessfullyCompleted() == false );
// Need a final cycle
ctx.startCycle();
ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase3.isOpen() );
ITracker& s1c = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1c.isOpen() == false );
ITracker& s2c = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2c.isOpen() == false );
testCase3.close();
REQUIRE( testCase3.isSuccessfullyCompleted() );
}
}
}
SECTION( "open a nested section", "" ) {
ITracker& s2 = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2.isOpen() );
s2.close();
REQUIRE( s2.isComplete() );
REQUIRE( s1.isComplete() == false );
s1.close();
REQUIRE( s1.isComplete() );
REQUIRE( testCase.isComplete() == false );
testCase.close();
REQUIRE( testCase.isComplete() );
}
SECTION( "start a generator", "" ) {
IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 );
REQUIRE( g1.isOpen() );
REQUIRE( g1.index() == 0 );
REQUIRE( g1.isComplete() == false );
REQUIRE( s1.isComplete() == false );
SECTION( "close outer section" )
{
s1.close();
REQUIRE( s1.isComplete() == false );
testCase.close();
REQUIRE( testCase.isSuccessfullyCompleted() == false );
SECTION( "Re-enter for second generation", "" ) {
ctx.startCycle();
ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase2.isOpen() );
ITracker& s1b = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1b.isOpen() );
IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 );
REQUIRE( g1b.isOpen() );
REQUIRE( g1b.index() == 1 );
REQUIRE( s1.isComplete() == false );
s1b.close();
REQUIRE( s1b.isComplete() );
REQUIRE( g1b.isComplete() );
testCase2.close();
REQUIRE( testCase2.isComplete() );
}
}
SECTION( "Start a new inner section", "" ) {
ITracker& s2 = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2.isOpen() );
s2.close();
REQUIRE( s2.isComplete() );
s1.close();
REQUIRE( s1.isComplete() == false );
testCase.close();
REQUIRE( testCase.isComplete() == false );
SECTION( "Re-enter for second generation", "" ) {
ctx.startCycle();
ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase2.isOpen() );
ITracker& s1b = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1b.isOpen() );
// generator - next value
IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 );
REQUIRE( g1b.isOpen() );
REQUIRE( g1b.index() == 1 );
// inner section again
ITracker& s2b = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2b.isOpen() );
s2b.close();
REQUIRE( s2b.isComplete() );
s1b.close();
REQUIRE( g1b.isComplete() );
REQUIRE( s1b.isComplete() );
testCase2.close();
REQUIRE( testCase2.isComplete() );
}
}
SECTION( "Fail an inner section", "" ) {
ITracker& s2 = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2.isOpen() );
s2.fail();
REQUIRE( s2.isComplete() );
REQUIRE( s2.isSuccessfullyCompleted() == false );
s1.close();
REQUIRE( s1.isComplete() == false );
testCase.close();
REQUIRE( testCase.isComplete() == false );
SECTION( "Re-enter for second generation", "" ) {
ctx.startCycle();
ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase2.isOpen() );
ITracker& s1b = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1b.isOpen() );
// generator - still same value
IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 );
REQUIRE( g1b.isOpen() );
REQUIRE( g1b.index() == 0 );
// inner section again - this time won't open
ITracker& s2b = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2b.isOpen() == false );
s1b.close();
REQUIRE( g1b.isComplete() == false );
REQUIRE( s1b.isComplete() == false );
testCase2.close();
REQUIRE( testCase2.isComplete() == false );
// Another cycle - now should complete
ctx.startCycle();
ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" );
REQUIRE( testCase3.isOpen() );
ITracker& s1c = SectionTracker::acquire( ctx, "S1" );
REQUIRE( s1c.isOpen() );
// generator - now next value
IndexTracker& g1c = IndexTracker::acquire( ctx, "G1", 2 );
REQUIRE( g1c.isOpen() );
REQUIRE( g1c.index() == 1 );
// inner section - now should open again
ITracker& s2c = SectionTracker::acquire( ctx, "S2" );
REQUIRE( s2c.isOpen() );
s2c.close();
REQUIRE( s2c.isComplete() );
s1c.close();
REQUIRE( g1c.isComplete() );
REQUIRE( s1c.isComplete() );
testCase3.close();
REQUIRE( testCase3.isComplete() );
}
}
// !TBD"
// nested generator
// two sections within a generator
}
}

View File

@ -1,118 +0,0 @@
/*
* Created by Phil on 20/07/2013.
* Copyright 2013 Two Blue Cubes Ltd
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifdef __clang__
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wc++98-compat"
#endif
#include "internal/catch_test_case_tracker.hpp"
#include "catch.hpp"
TEST_CASE( "section tracking", "" ) {
using namespace Catch;
TestCaseTracker testCaseTracker( "test case" );
const std::string section1Name = "section 1";
const std::string section2Name = "section 2";
CHECK_FALSE( testCaseTracker.isCompleted() );
SECTION( "test case with no sections", "" ) {
{
TestCaseTracker::Guard guard( testCaseTracker );
CHECK_FALSE( testCaseTracker.isCompleted() );
}
CHECK( testCaseTracker.isCompleted() );
}
SECTION( "test case with one section", "" ) {
{
TestCaseTracker::Guard guard( testCaseTracker );
// Enter section? - yes
CHECK( testCaseTracker.enterSection( section1Name ) );
CHECK_FALSE( testCaseTracker.isCompleted() );
testCaseTracker.leaveSection();
// Leave test case - now complete
}
CHECK( testCaseTracker.isCompleted() );
// ...
// Enter test case again
{
TestCaseTracker::Guard guard( testCaseTracker );
// Enter section? - no - now complete
CHECK_FALSE( testCaseTracker.enterSection( section1Name ) );
}
}
SECTION( "test case with two consecutive sections", "" ) {
// Enter test case
{
TestCaseTracker::Guard guard( testCaseTracker );
// Enter section 1? - yes
CHECK( testCaseTracker.enterSection( section1Name ) );
testCaseTracker.leaveSection();
// Enter section 2? - no - we just exected section 1
CHECK_FALSE( testCaseTracker.enterSection( section2Name ) );
// Leave test case - incomplete (still need to visit section 2)
}
CHECK_FALSE( testCaseTracker.isCompleted() );
// ...
// Enter test case again
{
TestCaseTracker::Guard guard( testCaseTracker );
// Enter section 1? - no, already done now
CHECK_FALSE( testCaseTracker.enterSection( section1Name ) );
// Enter section 2? - yes
CHECK( testCaseTracker.enterSection( section2Name ) );
testCaseTracker.leaveSection();
// Leave test case - now complete
}
CHECK( testCaseTracker.isCompleted() );
}
SECTION( "test case with one section within another", "" ) {
// Enter test case again
{
TestCaseTracker::Guard guard( testCaseTracker );
// Enter section 1? - yes
CHECK( testCaseTracker.enterSection( section1Name ) );
// Enter section 2? - yes
CHECK( testCaseTracker.enterSection( section2Name ) );
CHECK_FALSE( testCaseTracker.isCompleted() );
testCaseTracker.leaveSection(); // section 2
testCaseTracker.leaveSection(); // section 1
// Leave test case - now complete
}
CHECK( testCaseTracker.isCompleted() );
}
}

View File

@ -1,3 +1,3 @@
// This file is only here to verify (to the extent possible) the self sufficiency of the header
#include "catch_suppress_warnings.h"
#include "catch_common.h"
#include "internal/catch_suppress_warnings.h"
#include "internal/catch_common.h"

View File

@ -1,3 +1,3 @@
// This file is only here to verify (to the extent possible) the self sufficiency of the header
#include "catch_suppress_warnings.h"
#include "catch_console_colour.hpp"
#include "internal/catch_suppress_warnings.h"
#include "internal/catch_console_colour.hpp"

View File

@ -1,2 +1,2 @@
// This file is only here to verify (to the extent possible) the self sufficiency of the header
#include "catch_debugger.h"
#include "internal/catch_debugger.h"

View File

@ -1,3 +1,3 @@
// This file is only here to verify (to the extent possible) the self sufficiency of the header
#include "catch_suppress_warnings.h"
#include "catch_interfaces_capture.h"
#include "internal/catch_suppress_warnings.h"
#include "internal/catch_interfaces_capture.h"

Some files were not shown because too many files have changed in this diff Show More