Compare commits

..

279 Commits

Author SHA1 Message Date
Phil Nash
5d6c1f4dd0 Dev build 2 2017-08-18 15:58:00 +01:00
Phil Nash
3bc03cd617 Went back to Catch 1.x behaviour for -d
-d takes "yes" or "no", rather than being a standalone flag option. The default is "defaultForReporter" so the previous change actually dropped some control.
2017-08-18 15:53:10 +01:00
Phil Nash
28f11a7149 Added dummy listener registration 2017-08-17 19:40:48 +01:00
Martin Hořeňovský
24af32f378 Add define that pulls in reporter and listeners interfaces
This allows users to define reporters and listeners in files different
from the main file.

Related to #991, #986
2017-08-17 20:23:30 +02:00
Phil Nash
0545de0a31 Hold translated exception in local string while matching 2017-08-17 19:21:00 +01:00
Phil Nash
ee75b324e7 Rebased with missing [failing] tag 2017-08-17 19:21:00 +01:00
Martin Hořeňovský
597fca3c89 Remove <algorithm> header from the common path
It was only used for std::max<double> within Approx, so we now have
::Catch::Detail::max(double, double) that is used instead.
2017-08-17 20:04:53 +02:00
Martin Hořeňovský
f99f511155 Removed *_REGISTER_REPORTER from main path
Also simplified them to single macro: CATCH_REGISTER_REPORTER
2017-08-17 20:03:16 +02:00
Martin Hořeňovský
9a18ba042f Remove deprecated listener registration macro 2017-08-17 20:03:16 +02:00
Martin Hořeňovský
8e6641c19b Replace stdint.h include with cstdint include
Just small unification of includes
2017-08-17 20:03:16 +02:00
Martin Hořeňovský
185573e701 Do not include c++ stitch marking in final single header 2017-08-17 20:03:15 +02:00
Phil Nash
632e023ff4 Added non-copyable test to [failing] set 2017-08-17 16:55:35 +01:00
Phil Nash
b8f482b9aa Added test comparing non-copyable values 2017-08-17 16:48:46 +01:00
Phil Nash
aaedae60b4 Fixed issue with comparing non-copyable values 2017-08-17 16:46:05 +01:00
Phil Nash
ff9aaf3afe Added Clara and TextFlowCpp to open source users 2017-08-17 10:48:53 +01:00
Phil Nash
e6ffbb732a Updated conan files to use version number 2017-08-17 08:40:58 +01:00
Phil Nash
581aaae57e Generated single include for develop build 2017-08-17 08:29:57 +01:00
Phil Nash
0b52dbe8bb Small doc updates 2017-08-17 08:28:45 +01:00
Phil Nash
8c0a6a4358 Create CODE_OF_CONDUCT.md 2017-08-17 07:45:50 +01:00
Phil Nash
8582780f11 Don't include string/ vector matchers if CATCH_CONFIG_MATCHERS defined 2017-08-16 14:38:04 +01:00
Phil Nash
a36395e2ff Changed use of strncpy to memcpy 2017-08-15 23:47:52 +01:00
Phil Nash
699e571400 Documented benchmark-resolution-multiple command line option
- and increased default to 100
2017-08-15 19:51:22 +01:00
Phil Nash
07ded81541 Added --libidentify and --wait-for-keypress to docs 2017-08-15 19:43:30 +01:00
Phil Nash
a988af219c No longer show full usage in event of error
(it obscures the error message)
- instead just suggests running with -? to see usage
2017-08-15 17:08:32 +01:00
Monocasual
74dfd0b1e0 Add open-source user 2017-08-15 13:48:43 +01:00
Phil Nash
917a51da6b Added libidentify support, including option for waiting for keypress on exit (and/ or start) 2017-08-15 13:48:14 +01:00
Martin Hořeňovský
f06ed856d8 Cherry picked 4f21bb72ff (Add tests for #961) from master
- had to redo the baselines
2017-08-15 12:43:27 +01:00
Martin Hořeňovský
0aec06f4c3 Update documentation with changes from 7e4038d 2017-08-14 12:20:27 +01:00
Phil Nash
7be258536e Suppress strncpy copy warnings on MSVC 2017-08-14 12:12:28 +01:00
Phil Nash
94d347b059 Removed StringData 2017-08-14 09:14:49 +01:00
Phil Nash
3772f69f0f Removed String and StringBuilder 2017-08-14 09:04:14 +01:00
Phil Nash
ece64c3b3a Removed redundant .c_str()s from StringRef usages 2017-08-14 08:54:57 +01:00
Phil Nash
fa3535e95e Added << ostream overload to StringRef 2017-08-14 08:50:44 +01:00
Phil Nash
bb8c1fb17f Rebased with string conversion tests 2017-08-14 08:43:33 +01:00
Phil Nash
c659e0fd3d StringRef conversions to/ from std::string 2017-08-14 08:39:14 +01:00
Phil Nash
1aab791d67 reformatted benchmark output a bit 2017-08-11 22:24:52 +01:00
Phil Nash
eed4ae86ad Added config to control multiple of clock resolution to run benchmark iterations for 2017-08-11 22:24:52 +01:00
Phil Nash
df5c31bb19 Cleaned up the output a bit
- removed [!shouldfail] test from "green" path
- changed "spanner" to more descriptive text
2017-08-11 10:38:29 +01:00
Phil Nash
684cbb2631 Fixes issue with fatal errors and non-failing assertions
Fixes #990
2017-08-10 17:10:13 +01:00
Phil Nash
6282999291 Rebased approvals with info loop change 2017-08-10 17:00:22 +01:00
Phil Nash
97c06ca6fb Merge branch 'reevaluate' into dev-modernize 2017-08-10 16:18:05 +01:00
Martin Hořeňovský
3382312bd8 Remove obsoleted SCOPED_MSG and SCOPED_CAPTURE
Standard `MSG` and `CAPTURE` behave the same way these used to,
and are recommended instead.
2017-08-10 17:06:32 +02:00
Martin Hořeňovský
5da76bb7be Allow specifying default reporter at compile time 2017-08-10 16:24:31 +02:00
Martin Hořeňovský
11295a2663 Make catch_stream.hpp a standard .cpp file 2017-08-10 11:45:05 +02:00
Martin Hořeňovský
aa42dd92d1 Merge branch 'master' into dev-modernize 2017-08-10 11:34:26 +02:00
Phil Nash
ee9b19efd3 Moved matcher-based capture macros into their own file
- this file excluded from the CATCH_CONFIG_DISABLE_MATCHERS path.
- matchers are always compiled in to the impl file
- _THROWS_WITH macros are still available with matchers disabled - but only the ones that take a string
- tests that use matchers have #ifdefs, so the whole SelfTest project can compile with matchers disable.
2017-08-09 12:10:14 +01:00
Phil Nash
b59e0ed48a Collapsed alternate capture macros now originals are redundant 2017-08-09 11:36:33 +01:00
Phil Nash
8d21b4a916 Removed some unnecessary #includes
- and don't #include "catch_debugger.h" in the header path when CATCH_CONFIG_FAST_COMPILE is defined
2017-08-09 10:51:50 +01:00
Phil Nash
4b5ac4d3d9 Actually do what the previous commit claimed to do!
:-s
2017-08-09 10:29:05 +01:00
Phil Nash
8382d99081 Workaround for GCC 4.8 "deleted ctor in aggregate" bug 2017-08-09 10:18:31 +01:00
Phil Nash
dc1df297e3 Suppressed some warnings
- signed/ unsigned mismatches
- virtual destructor on ITransientExpression (even though not needed)
2017-08-09 09:29:44 +01:00
Phil Nash
8c95a81448 Removed all (well, most) of the redundant, ResultBuilder-based, code 2017-08-09 09:08:33 +01:00
Phil Nash
7df290dfc1 Integrated new AssertionHandler into unexpected exception handling in RunContext 2017-08-09 08:49:59 +01:00
Phil Nash
201028d6ec Integrated INTERNAL_CATCH_THROWS with new AssertionHandler 2017-08-09 00:52:20 +01:00
Phil Nash
27fd8f80bd Integrated INTERNAL_CATCH_THROWS_STR_MATCHES with new AssertionHandler 2017-08-09 00:44:30 +01:00
Phil Nash
ef4fa56b71 integrated INTERNAL_CATCH_THROWS_MATCHES with new AssertionHandler 2017-08-08 23:41:55 +01:00
Phil Nash
9668410b8e integrated INTERNAL_CHECK_THAT with new AssertionHandler 2017-08-08 23:31:43 +01:00
Phil Nash
2832e23aa9 Restored exceptionGuard functionality under CATCH_CONFIG_FAST_COMPILE 2017-08-08 21:07:30 +01:00
Phil Nash
5f91724368 integrated AssertionHandler into INTERNAL_CATCH_MSG 2017-08-08 20:17:09 +01:00
Phil Nash
8a97beece2 integrated AssertionHandler into INTERNAL_CATCH_THROWS_AS 2017-08-08 19:43:07 +01:00
Phil Nash
f033f4f184 integrated AssertionHandler into INTERNAL_CATCH_NO_THROW 2017-08-08 19:36:18 +01:00
Phil Nash
f247ce5bff First cut of new AssertionHandler/ Decomposer
- integrated into INTERNAL_CATCH_TEST. Needs more work to fully replace existing stuff
2017-08-08 17:53:01 +01:00
Phil Nash
f8148ebae1 Made macroName and capturedExpression StringRefs 2017-08-08 01:22:21 +01:00
Phil Nash
59f9bcf1ed Reduced AssertionInfo to a pure record type 2017-08-08 01:08:07 +01:00
Phil Nash
5e60050299 Removed default ctors for AssertionInfo, AssertionResult and SourceLineInfo 2017-08-08 01:02:24 +01:00
Phil Nash
e658bacb04 Refactored how FAST_COMPILE affects internal test macros (less duplication) 2017-08-07 00:09:54 +01:00
Phil Nash
3a409e9fd4 Suppress more signed/ unsigned mismatches during Evaluator calls on MSVC 2017-08-06 00:38:03 +01:00
Phil Nash
63392e095e Refactored Evaluator templates to only be specialised on Op, with Lhs/Rhs types templated on method instead 2017-08-06 00:29:37 +01:00
Phil Nash
0a2ce87d32 Removed compare layer from expression evaluation 2017-08-06 00:13:00 +01:00
Phil Nash
b3b29f4b4c Use size_t for String size types 2017-08-05 22:53:21 +01:00
Phil Nash
cff3818e68 Correctly handle special tags that also imply being hidden (!benchmark) 2017-08-05 22:24:17 +01:00
Phil Nash
519db85758 Report benchmark durations in natural units
(and extended StringRef to be able to report utf8 char lengths
2017-08-05 21:41:56 +01:00
Phil Nash
4421672fb8 Removed benchmark tests from approval tests (for now) 2017-08-05 11:26:20 +01:00
Phil Nash
f45d35c980 Added benchmark tests 2017-08-05 11:12:29 +01:00
Phil Nash
22e9ebef0d Factored table writing code out into a TablePrinter class (removes a lot of magic numbers and ad-hoc formatting) 2017-08-04 23:54:51 +01:00
Phil Nash
97d6b08087 Changed clock resolution estimator to return uint64_t 2017-08-04 21:31:28 +01:00
Phil Nash
a9b6813ad9 First draft of (experimental) benchmarking support 2017-08-04 19:23:30 +01:00
Phil Nash
a1e3f0b624 Moved Timer impl back to cpp
(I thought it wasn't included on the non-main path, but it is)
2017-08-04 13:53:47 +01:00
Phil Nash
39d37d9f34 Timer resolution is now nanoseconds 2017-08-04 12:22:16 +01:00
Phil Nash
c7028f7bc7 Made most of Timer class inline - and export getCurrentMicrosecondsSinceEpoch() 2017-08-04 12:16:05 +01:00
Phil Nash
5450de2acd Added some missing overrides and removed some virtuals from overrides 2017-08-04 12:13:58 +01:00
Martin Hořeňovský
3882ac1a19 Include proper exception header in enforce.h 2017-08-02 00:26:52 +02:00
Martin Hořeňovský
e8b785b177 Fixup bad merge in 2212cdfe 2017-08-02 00:04:26 +02:00
Danila Sukharev
887fe1d5d2 Adding more flexibility into the cmake catch parsing script (#971)
* Adding more flexibility into the cmake catch parsing script
2017-08-01 22:50:21 +02:00
Anton Vorobyev
eab56d6656 Initial support for native IBM i ILE C++ (#976)
* - Initial support for native IBM i ILE C++

Signed-off-by: zeromem <zeromem2@gmail.com>
2017-08-01 22:49:27 +02:00
Neal Coombes
2212cdfe26 Eliminate some work when results won't be reported. 2017-08-01 22:49:27 +02:00
Markus Werle
28741467d5 Update tutorial.md 2017-08-01 22:29:13 +02:00
Ivan Kush
7a76ff161b added 'args' argument parser library 2017-08-01 22:27:51 +02:00
Fran García Salomón
4f72202c04 Fix for JUnit reporter when using dynamically generated sections (#963)
* BySectionInfo should also take into account the section name in addition to the source code line
2017-08-01 22:25:16 +02:00
Martin Hořeňovský
cde987a92e Note start of .cpp files in single header 2017-08-01 22:20:14 +02:00
Martin Hořeňovský
249bf116e8 Route all T* comparisons through const void* comparisons
This should stop the evaluate machinery from instantiating all the
templates for every ptr type that is compared, instead generating it
for single one.
2017-08-01 22:09:32 +02:00
Martin Hořeňovský
6d4673505d Add missing <algorithm> include in catch_approx.hpp 2017-08-01 22:02:00 +02:00
Martin Hořeňovský
85e14c5fb5 Move some compile-time dispatch to runtime
The runtime performance is likely to be negligible,
but compile times need every improvement they can get.
2017-08-01 21:58:09 +02:00
Martin Hořeňovský
feca97dfde Split out internal error macros from the common path 2017-08-01 18:46:33 +02:00
Martin Hořeňovský
c815ad1d53 Fix fwd declaration of IConfig in catch_test_case_registry_impl.hpp 2017-08-01 17:52:02 +02:00
Martin Hořeňovský
d4e796c138 Move Section(End)Info bodies to proper .cpp file 2017-08-01 17:51:32 +02:00
Martin Hořeňovský
0a3f899d6a Move windows.h reduction logic into windows.h proxy header
Fixes #965 (at least the primary problem, the separate warnings can
be taken care of later)
2017-07-31 08:36:39 +02:00
Martin Hořeňovský
d118ce191d Disable build broken by travis changes
It should be reenabled at some point, but I don't have the time ATM
2017-07-29 08:44:40 +02:00
Martin Hořeňovský
d08e31d89e Fix inverted CATCH_CONFIG_DISABLE_MATCHERS toggle 2017-07-29 08:43:32 +02:00
Martin Hořeňovský
0ca4cfb743 Introduce compile time toggle to remove Matchers from TU
The toggle is `CATCH_CONFIG_DISABLE_MATCHERS` and the only use is
to speed up compilation of small TUs. For large ones it is likely
insignificant, because the speed up is constant relative to
number of tests/assertions in TU.
2017-07-28 21:34:34 +02:00
Martin Hořeňovský
35c1301bd5 Fix missing CATCH_ prefixed macros 2017-07-28 21:04:18 +02:00
Martin Hořeňovský
d01fe03ba6 Removed <algorithm> include from the main path 2017-07-28 15:11:05 +02:00
Martin Hořeňovský
287cc92b2c Remove <set> include from the common test path 2017-07-27 22:31:27 +02:00
Martin Hořeňovský
446bad752f Move std::exception_ptr out of interfaces 2017-07-27 12:24:52 +02:00
Martin Hořeňovský
307eeefa8f Change typedefs to using 2017-07-27 12:24:21 +02:00
Martin Hořeňovský
33fd54a673 Split Option<T> and TagAlias definitions away from the main include path 2017-07-27 11:55:30 +02:00
Martin Hořeňovský
918eca5ee9 Improve single header generator 2017-07-27 11:32:05 +02:00
Martin Hořeňovský
5ebbec7dab Move all stringref function bodies out of line 2017-07-27 11:32:04 +02:00
Martin Hořeňovský
a40add3153 Clean up Approx to take arguments by const& 2017-07-27 11:32:04 +02:00
Martin Hořeňovský
ab0f1dcde9 Remove superfluous include 2017-07-27 11:32:03 +02:00
Martin Hořeňovský
a75eaa3c5a Split out more headers into separate .cpp files 2017-07-27 11:32:02 +02:00
Martin Hořeňovský
9de729b515 General cleanup 2017-07-27 11:32:01 +02:00
Martin Hořeňovský
1a96175bb2 Split out helper functions on std::string from catch_common.h 2017-07-25 21:57:35 +02:00
Martin Hořeňovský
1e59ccee41 Addressed Resharper-C++ warnings
See #958
2017-07-25 17:16:28 +02:00
Martin Hořeňovský
b6f62af7d1 Address more of PVS studio warnings 2017-07-25 15:45:50 +02:00
Phil Nash
46bf7605f4 Hold exception translators by unique_ptr
- and removed range deleters
2017-07-20 23:50:07 +01:00
Phil Nash
cb6963216f Removed catch_section_info.cpp (not used) 2017-07-20 23:49:03 +01:00
Phil Nash
b35225ff3a Removed tbc_text_format from CMakeLists.txt 2017-07-20 23:37:25 +01:00
Phil Nash
c91639e1d7 Use Columns to format reporter list 2017-07-20 23:32:35 +01:00
Phil Nash
3a37f45a97 Removed tbc_text_format (superceded by TextFlow) 2017-07-20 23:20:42 +01:00
Phil Nash
6ec7709e07 removed final use of tbc_text_format (console reporter) 2017-07-20 23:13:08 +01:00
Phil Nash
58d8bc6985 Removed Text tests (TextFlow has it's own test suite) 2017-07-20 23:09:50 +01:00
Phil Nash
93556a1fb3 Removed "unapproved" baselines that got checked in at some point 2017-07-20 23:06:21 +01:00
Phil Nash
d3c7d424fe Removed "long text" test (not a limitation of TextFlow) 2017-07-20 23:04:34 +01:00
Phil Nash
224250e2d4 listTests now only uses TextFlow (not tbd_text_format) again 2017-07-20 20:10:13 +01:00
Phil Nash
5c3355ad1b Embed Clara with TextFlow fix for whitespace after newline 2017-07-20 20:07:28 +01:00
Phil Nash
b2a4dfcda4 Embedded version of Clara with TextFlow fix for embedded newlines 2017-07-20 19:42:06 +01:00
Phil Nash
f0890dcdf8 removed redundant virtuals on override functions (and added a couple of overrides) 2017-07-20 16:23:52 +01:00
Martin Hořeňovský
74ab1cd94b Update Baselines 2017-07-20 00:29:19 +02:00
Martin Hořeňovský
87a66b8479 Address results of PVS-Studio static analysis
Couple are left un-addressed, see #958 for details.
2017-07-20 00:27:28 +02:00
Martin Hořeňovský
2a586437e8 Fix merge mishap (duplicated catch_reporter_multi header) 2017-07-19 23:20:30 +02:00
Martin Hořeňovský
cf2678dce6 Merge branch 'dev-better-verbosity' of https://github.com/BMBurstein/Catch 2017-07-19 23:17:19 +02:00
Martin Hořeňovský
d7f754dc49 Fix SelfTest compilation after _THROWS_ assertion change
That is, changes made in efd79aa0bd
2017-07-19 22:21:47 +02:00
Martin Hořeňovský
a14bd08b27 Update documentation to reflect the last change 2017-07-19 21:34:06 +02:00
Martin Hořeňovský
efd79aa0bd Extend exception type in _THROWS_ with const& unconditionally
Potentially breaking change, but most people apparently were using it
wrong and thus it won't be breaking for them.

Closes #955
2017-07-19 21:30:00 +02:00
Martin Hořeňovský
4a1e898eae More method bodies moved out of line 2017-07-19 15:32:58 +02:00
Martin Hořeňovský
d7ff62430a Removed superfluous inline specifications 2017-07-19 13:40:00 +02:00
Martin Hořeňovský
edbe122761 Split out non-templated Approx methods into cpp file 2017-07-19 13:40:00 +02:00
Phil Nash
0a614ee5ba re/moved some headers in catch_tostring 2017-07-19 08:31:10 +01:00
Phil Nash
4833932ab2 Removed redundant member 2017-07-19 08:17:41 +01:00
Phil Nash
cd6f6c021a Minor clean-ups in string conversion code 2017-07-19 08:16:55 +01:00
Phil Nash
b0e3f45a22 Replaced some uses of tbc_text_format with TextFlow (from Clara) 2017-07-18 20:27:42 +01:00
Phil Nash
d43024ff6b Removed intermediate IConfig ptr 2017-07-18 18:03:57 +01:00
Phil Nash
c7931f6f18 Reuse ostringstream in XML reporter 2017-07-18 08:35:41 +01:00
Phil Nash
01a21f67f7 Converted a load of spelt out iterators to auto 2017-07-18 08:08:17 +01:00
Martin Hořeňovský
7ccf11da29 Split out catch_run_context into cpp and hpp file 2017-07-15 16:48:21 +02:00
Phil Nash
cf6f9e3253 Initialise unexpectedExceptions in JUnitReporter 2017-07-13 10:10:39 +01:00
Phil Nash
f193698fb3 Removed all (that I could find) redundant second macro args to TEST_CASE and SECTION
- now we can rely on variadic macros
2017-07-13 09:20:37 +01:00
Phil Nash
c89bdf842e Removed failing enum test from test run 2017-07-13 09:18:40 +01:00
Phil Nash
c874a99c6c Enabled c++11 tests in approvals 2017-07-13 08:52:51 +01:00
Phil Nash
e4456aa243 Some clean-ups 2017-07-13 08:29:12 +01:00
Phil Nash
d2d5910479 Suppress clang-tidy warnings about inline asm 2017-07-13 08:26:08 +01:00
Phil Nash
e01ed48a70 Made everything used in test case registration noexcept
- this prevents warnings about startup-time exceptions
2017-07-13 08:25:47 +01:00
Phil Nash
989222eceb Fixed up OcMethod base 2017-07-12 23:26:13 +01:00
Phil Nash
720fdf1d02 Simplified test case registration and started using StringRefs 2017-07-12 23:11:41 +01:00
Phil Nash
79627cdcdb Changed some names in test case registry
- in preparation for a bigger refactoring
2017-07-12 23:11:41 +01:00
Phil Nash
10c36aa74c added override keyword to overrides in compact reporter 2017-07-12 23:11:41 +01:00
Martin Hořeňovský
bc73189c52 Rebase baselines to take into account the removed test 2017-07-12 16:27:09 +02:00
Phil Nash
e3e6453229 Removed spurious "inline" (was causing linker errors) and fixed broken macOS detection 2017-07-12 15:24:35 +01:00
Martin Hořeňovský
878bd140e6 Removed superfluous inline keywords 2017-07-12 16:16:55 +02:00
Martin Hořeňovský
d8df83ee2f Don't rely on transitive <string> include 2017-07-12 16:07:52 +02:00
Martin Hořeňovský
8d8f481597 Moved couple function's bodies out of common-include path 2017-07-12 16:07:27 +02:00
Martin Hořeňovský
3f6c078173 Use = delete instead of private, unimplemented copy operations 2017-07-12 15:11:23 +02:00
Martin Hořeňovský
0bb9f52a99 Removed declared-but-undefined function 2017-07-12 15:10:55 +02:00
Martin Hořeňovský
91c1556078 Moved Catch NotImplementedException out of the common include path
We could probably toss it away completely, currently it is used
only by TeamCity reporter.
2017-07-12 15:05:01 +02:00
Martin Hořeňovský
4332b84c9b Moved leak detector to its own file 2017-07-12 15:03:52 +02:00
Martin Hořeňovský
9c318af987 Remove obsolete GENERATE macro 2017-07-12 14:46:49 +02:00
Martin Hořeňovský
1d3bfa0353 More include and impl refactoring 2017-07-10 14:25:38 +02:00
Martin Hořeňovský
5f3f19de08 Default included reporters are now also in .cpp files
The non-default ones remain as header files.
2017-07-10 11:33:18 +02:00
Martin Hořeňovský
93f84b5b0d Modified generateSingleHeader script to work with .cpp files better
Also fixed the scripts to take into account renamed version file
2017-07-09 21:02:36 +02:00
Baruch Burstein
af05ccfe5d Merge remote-tracking branch 'upstream/dev-modernize' into dev-better-verbosity 2017-07-09 12:48:29 +03:00
Baruch Burstein
058b21e604 Previous implementation didn't work
It relied on calling a virtual method from a base constructer
2017-07-09 12:46:53 +03:00
Martin Hořeňovský
fc32165d48 Started work on splitting out .cpp files from header files 2017-07-06 22:28:42 +02:00
Baruch Burstein
f749347523 Check that reporter supports requested verbosity 2017-07-06 01:25:49 +03:00
Baruch Burstein
bb9f2bb3ad Use new formatting capabilities 2017-07-04 18:16:42 +03:00
Baruch Burstein
694fe61ae3 Add ability to format any streamable class
This should probably be done at the source of this external file, but I couldn't find where that is. Perhaps it should be mentioned in the file header comment?
2017-07-02 11:52:29 +03:00
Phil Nash
0016362f69 explicit conversion from size_t to size_type 2017-06-29 16:31:05 +01:00
Phil Nash
63a8017ba7 Minor session tweaks 2017-06-29 14:27:53 +01:00
Phil Nash
03afbdfec9 Made more of StringRef noexcept 2017-06-29 11:47:09 +01:00
Phil Nash
f9ce8fd03b Added some missing cstring includes 2017-06-29 11:43:20 +01:00
Phil Nash
60f25c7ffd Added string tests to approvals 2017-06-29 11:19:08 +01:00
Phil Nash
78e7994435 Added string classes 2017-06-29 11:18:14 +01:00
Phil Nash
cb0a5194af Updated overview docs a bit 2017-06-27 11:45:47 +01:00
Phil Nash
4c1880b35f Clamp exit code internally, so it doesn’t have to be done in every main() implies 2017-06-27 11:37:50 +01:00
Martin Hořeňovský
fae0fa4ec1 Merge branch 'dev-second-string-argument-removal' into dev-modernize
It is no longer true that an assertion macro has either 1 or 2 args,
so...
2017-06-26 20:48:41 +02:00
Martin Hořeňovský
c5bac73cad Merge branch 'master' into dev-modernize
This includes the performance commits done recently
2017-06-26 19:08:42 +02:00
Baruch Burstein
1e7000ed55 Merged implemention of #934, but using 'verbose' option on command line instead.
(see 616f7235ef on master for original merge)
2017-06-26 17:15:28 +01:00
Martin Hořeňovský
9382534d59 Added "How to test changes in PR" section to documentation
Also linked it from PR template.

Closes #936
2017-06-26 16:54:14 +01:00
Martin Hořeňovský
7bcfdf8e94 Disable deprecation warning of std::uncaught_exception
We might prefer to use `std::uncaught_exceptions` in the future, but I
would prefer not to bring in more configuration into Catch Classic

Closes #927
2017-06-26 16:50:23 +01:00
Martin Hořeňovský
8d5f6c8e2e Fix how GCC version is detected when checking for __COUNTER__
Fixes #928
2017-06-26 16:49:34 +01:00
Phil Nash
e62a9aa444 Removed const refs from NSString/ NSObject overloads (effectively reapplies PR #855 originally applied to "1.x" master) 2017-06-26 16:48:38 +01:00
Phil Nash
059a33d555 Fixed indentation 2017-06-26 16:47:40 +01:00
Phil Nash
af66106500 Updated Clara with handling for / on Windows 2017-06-23 09:08:44 +01:00
Martin Hořeňovský
0eb101e165 Remove "second argument" from result builder and assertion result
This is not quite complete removal (it doesn't pass approval tests),
but it should be representative of full perf improvements from doing so
2017-06-22 18:13:05 +02:00
Phil Nash
2462dff088 Updated Clara with VS ICE workaround 2017-06-22 16:07:05 +01:00
Phil Nash
0470b300a8 Reverted previous two commits as they didn’t fix anything 2017-06-22 15:53:24 +01:00
Phil Nash
3bb16e8418 Reorganised CLI again in another attempt to get past VS ICEs 2017-06-21 11:42:53 +01:00
Phil Nash
e0c6c4aee7 Another attempt to fix VS ICEs - split cli parser up. 2017-06-21 09:40:52 +01:00
Phil Nash
c43d5f673f Moved command line lambdas out-of-line in an attempt to fix VS ICEs 2017-06-21 08:54:53 +01:00
philsquared
d81c1eb006 added version of Clara that has virtual destructors
(just to silence warnings - they are not actually needed)
2017-06-20 22:35:35 +01:00
Phil Nash
da5964af78 Updated version of Clara (should fix Windows compile issues)
- embedded using new embed script
2017-06-20 18:03:47 +01:00
Martin Hořeňovský
ee0defb939 Silence unused argument warning in Catch 2017-06-15 11:34:29 +02:00
Phil Nash
e62b3beef4 Fixed issue with different result types in Clara 2017-06-13 08:29:56 +01:00
Phil Nash
c41a45e79c Rebased following Clara changes 2017-06-12 23:13:27 +01:00
Phil Nash
1c223b63ba Integrated (all) new version of Clara 2017-06-12 23:07:10 +01:00
Phil Nash
6d9171aadb Updated approvals following Junit changes 2017-06-12 22:30:33 +01:00
Martin Hořeňovský
ebb3371cbf Merge remote-tracking branch 'tsondergaard/improve-junit-xml-for-jenkins' into dev-modernize 2017-06-06 16:52:02 +02:00
Martin Hořeňovský
b6d9976fbb Make generateSingleHeader.py Python 2.7 compatible 2017-06-06 16:32:45 +02:00
Martin Hořeňovský
6583284731 Fix erroneous result disposition for {REQUIRE,CHECK}_THAT
This fixes result disposition being ContinueOnFailure |
ContinueOnFailure for CHECK_THAT (obviously an error) and Normal |
ContinueOnFailure for REQUIRE_THAT (less obviously an error, but worse,
as that signals to the pipeline that assertion failure should both abort
and continue the test with ???? happening).
2017-06-06 15:12:03 +02:00
Martin Hořeňovský
07ef028483 Update baselines 2017-06-06 15:07:57 +02:00
Martin Hořeňovský
47eb9b3d68 Fix #914 being removed during last merge 2017-06-06 15:07:34 +02:00
Martin Hořeňovský
8fde7abf31 Add tests for *_THROWS_MATCHES
Closes #641, closes #818
2017-06-05 19:15:17 +02:00
Martin Hořeňovský
c465fbd0ea Slight documentation improvements 2017-06-05 18:42:04 +02:00
Martin Hořeňovský
950cae9040 Added new assertion macros: *_THROWS_WITH
It combines `*_THROWS_AS` and `*_THROWS_WITH` macros, so that the
exception type matches expectetations and its contents match a specific
matcher.
2017-06-05 18:40:50 +02:00
Martin Hořeňovský
7f6773bb4d Merge branch 'master' into dev-modernize
Hopefully nothing went too wrong.
2017-06-05 17:19:42 +02:00
Martin Hořeňovský
b459bb4c43 Silence GCC's Wunused-function firing in compilation tests
The whole GCC kinda sucks around warnings, this is yet another place
where pragmas manipulating warnings don't work properly and thus a
warning has to be disabled globally... luckily, this time it is
happening in selftest file and thus it isn't too problematic to just
turn that warning of for the entire file.
2017-06-05 16:59:31 +02:00
Martin Hořeňovský
1e16be0b9e Purge deprecated generators 2017-06-05 16:49:10 +02:00
Thomas Sondergaard
69ff7fcf42 Include suite name in junit classname attrib for grouping in jenkins
Jenkins groups junit test results by loosely interpreting the
classname attribute of the <testcase> element as a package-qualified
java class name such as java.util.String. It ignores the <testsuite>
elements in the xml. To organize test results we therefore need to
embed the suite name in the classname attribute as if it was a java
package name.

Fixes #922.
2017-06-05 12:51:56 +02:00
Thomas Sondergaard
a6b03031ba Use [#filename] tag for junit testcase classname attribute
If [#filename] is present in tags, use it for the classname attribute,
rather than "global". If the test fixture is present that still takes
precedence.
2017-06-05 12:51:56 +02:00
Martin Hořeňovský
47c8994a61 Inherit from NonCopyable to disable RegisterHub copies 2017-06-04 22:56:57 +02:00
Martin Hořeňovský
860de28b8d Catch and register startup exceptions in autoregistrars
Previously they were registered where they would be thrown otherwise
2017-06-04 22:37:59 +02:00
Martin Hořeňovský
da0edcbe25 Collect startup exceptions instead of throwing them
Previously, some errors in Catch configuration would cause exceptions to
be thrown before main was even entered. This leads to call to
`std::terminate`, which is not a particularly nice way of ending the
binary.

Now these exceptions are registered with a global collector and used
once Catch enters main. They can also be optionally ignored, if user
supplies his own main and opts not to check them (or ignored them
intentionally).

Closes #921
2017-06-04 21:39:27 +02:00
Martin Hořeňovský
0020747420 Generate single header even if output dir does not exist 2017-06-04 21:28:08 +02:00
Thomas Sondergaard
a64a0c6f06 Consistent junit reporting regardless of internal SECTIONS
Change it so the classname attribute on the <testcase> element is the
test fixture name or "global" regardless of whether the TEST_CASE
contains SECTIONs. This way the output is not changed substantially,
just because a SECTION is added to a TEST_CASE.
2017-05-30 17:10:14 +02:00
Martin Hořeňovský
169e260e8b Enable colourized output while in debugger 2017-05-22 00:41:31 +02:00
Martin Hořeňovský
67914d8b86 Move back to static StringMaker<T>::convert
This avoids some breakage from the modernization
2017-05-21 23:40:05 +02:00
Martin Hořeňovský
31f5e2ed81 Updated documentation about stringifying UDTs 2017-05-16 13:38:52 +02:00
Martin Hořeňovský
85aa770701 Disable unreachable code warning for TrickyTests.cpp
Somehow this only triggers for VS 2015, Win32 | Release configuration...
2017-05-08 01:26:06 +02:00
Martin Hořeňovský
f82e312552 Attempt at fixing compilation on OSX
Since I don't have actual access to OSX, this might be a tad optimistic.
2017-05-08 01:08:07 +02:00
Martin Hořeňovský
bffef1bffa Fix alignment for Catch::Option
This is so much easier in C++11...
2017-05-08 00:59:44 +02:00
Martin Hořeňovský
7e14232924 Fix C4702 (unreachable code) in generators
Generators might get removed anyway, but at least compilation wont
trigger Wx on MSVC in the meantime.
2017-05-08 00:58:44 +02:00
Martin Hořeňovský
d7eb041ab5 Fix compilation on non-OSX platforms 2017-05-08 00:54:53 +02:00
Phil Nash
8c757cc542 Removed need for Error class to capture stream inserted strings into exceptions 2017-05-05 18:39:49 +01:00
Phil Nash
bada67bb72 Rebased approvals 2017-05-05 18:28:04 +01:00
Phil Nash
4c5af2089a Added CATCH_ENFORCE (and updated CATCH_INTERNAL_ERROR to be stream based)
replaced all ad-hoc exceptions (where appropriate) with CATCH_ENFORCE or CATCH_INTERNAL_ERROR - no explicit ostringstreams.
2017-05-05 15:43:31 +01:00
Phil Nash
687437fcd1 converted IStreamingReporter to unique_ptr 2017-05-05 15:43:31 +01:00
Phil Nash
ef8b72c949 Changed dynamic_pointer_casts to static_pointer_casts 2017-05-05 15:43:31 +01:00
Martin Hořeňovský
a9128d0fac More macros are now variadic
Also added tests for them
2017-05-03 19:10:27 +02:00
Martin Hořeňovský
c5c3d368a2 Added std:: qualification to nullptr_t
Apparently Clang doesn't like it unqualfied 😄
2017-05-03 00:29:36 +02:00
Martin Hořeňovský
33ed1773f4 Reworked stringification layer, removed Catch::toString
Now the order of stringification checks is

1) StringMaker specialization
2) operator<<

toString overloads and specializations have been removed.
2017-05-02 23:51:03 +02:00
Martin Hořeňovský
40130e59b4 Fix order of arguments in CATCH_FAIL macro 2017-04-28 18:33:52 +02:00
Phil Nash
316cb28ea8 Added missing <memory> includes 2017-04-26 17:04:00 +01:00
Phil Nash
51c143b2c6 Added test for assertion with comma 2017-04-26 16:12:48 +01:00
Phil Nash
d17d94e45d Made INTERNAL_CATCH_TEST variadic so commas in assertions work 2017-04-26 16:10:18 +01:00
Phil Nash
8ccbf63f28 Removed Ptr, Shared and SharedImpl 2017-04-25 21:56:14 +01:00
Phil Nash
e6094a9503 migrated (Reporter) Nodes to std::shared_ptr 2017-04-25 21:56:14 +01:00
Phil Nash
851e40a4bb migrated Pattern to std::shared_ptr 2017-04-25 21:56:14 +01:00
Phil Nash
0807a6910f migrated ITracker to std::shared_ptr 2017-04-25 21:56:14 +01:00
Phil Nash
44cccde8b9 Migrated ITestCase to std::shared_ptr 2017-04-25 21:56:14 +01:00
Phil Nash
0844d6e867 Migrated IStreamingReporter from Ptr to std::shared_ptr 2017-04-25 21:56:14 +01:00
Phil Nash
a96f25c716 Some listener and factory clean-ups 2017-04-25 21:56:14 +01:00
Phil Nash
dd78824697 Migrated IReporterFactory to std::shared_ptr 2017-04-25 21:56:14 +01:00
Phil Nash
338ba6b9ba Migrated Config and IConfig to shared_ptr (from Ptr) 2017-04-25 21:56:14 +01:00
Phil Nash
41afd0c3d4 Removed copy ctor, assignment operator and swap from TestCaseInfo 2017-04-25 21:56:14 +01:00
Phil Nash
602b62f037 Removed legacy reporter support 2017-04-25 21:56:14 +01:00
Martin Hořeňovský
de348b9bdd Removed VS 2013 from AppVeyor
Does not support C++11 properly enough
2017-04-25 21:28:12 +02:00
Martin Hořeňovský
c1835ec203 Removed gcc 4.7 from travis
It wasn't able to deal with C++11 properly
2017-04-25 21:27:29 +02:00
Phil Nash
e749724a11 A load more C++11 tweaks - mostly moving initialisations from constructors to inline 2017-04-25 19:30:53 +01:00
Phil Nash
cc8206f4c3 Removed SafeBool 2017-04-25 19:30:53 +01:00
Martin Hořeňovský
e1bca7017d Most of Assertion macros are now variadic
This means that `REQUIRE(std::vector<int>{1, 2} == std::vector<int>{1,
2});` works as expected.

Note that assertion macros taking more than 1 argument are currently not
variadic, because variadic args have to come last, which would make the
interface of these ugly: `REQUIRE_THROWS_AS(std::exception const&, ....
)`
2017-04-25 20:20:46 +02:00
Martin Hořeňovský
53864dee7b Fix MSVC compilation error
MSVC's `std::vector` requires its allocator to have copy constructor
from the same allocator kind, but templated over different type.
2017-04-25 19:54:22 +02:00
Martin Hořeňovský
b245eaa7d1 Fix double-to-float conversion warning in tests 2017-04-25 17:48:28 +02:00
Phil Nash
be0fc60c07 Updated version number for v2 development and removed single include (for now). 2017-04-25 14:43:13 +00:00
Phil Nash
61ac34045c Enabled SFINAE stream test 2017-04-25 14:57:58 +01:00
Phil Nash
569d355b36 Removed C++11 config macro docs 2017-04-25 14:57:47 +01:00
Phil Nash
79650e44f4 Removed more C++98/03 compatibility 2017-04-25 12:40:52 +01:00
Phil Nash
5c8ea03cc8 Removed debug break support for PowerPC Macs 2017-04-25 12:27:26 +01:00
Phil Nash
242022460d Use std::chrono for Timer to eliminate platform dependency 2017-04-25 12:24:34 +01:00
Phil Nash
67005d290c Removed more redundant compatibility stuff from timer 2017-04-25 12:13:16 +01:00
Phil Nash
f57f96f190 Removed pre-C++11 versions of Clang (3.4) and GCC (4.4) 2017-04-25 12:10:04 +01:00
Martin Hořeňovský
71df66365e Gutted catch_compiler_capabilities
All C++11 toggles are now removed. What is left is either platform
specific (POSIX_SIGNALS, WINDOWS_SEH), or possibly still needed
(USE_COUNTER).

If current CLion is compatible with `__COUNTER__`, then we should also
force `__COUNTER__` usage.

Changed
* CATCH_AUTO_PTR    -> std::unique_ptr
* CATCH_OVERRIDE    -> override
* CATCH_NULL        -> nullptr
* CATCH_NOEXCEPT    -> noexcept
* CATCH_NOEXCEPT_IS -> noexcept

Removed
* CATCH_CONFIG_CPP11_UNIQUE_PTR
* CATCH_CONFIG_CPP11_SHUFFLE
* CATCH_CONFIG_CPP11_TYPE_TRAITS
* CATCH_CONFIG_CPP11_OVERRIDE
* CATCH_CONFIG_CPP11_LONG_LONG
* CATCH_CONFIG_CPP11_TUPLE
* CATCH_CONFIG_CPP11_IS_ENUM
* CATCH_CONFIG_CPP11_GENERATED_METHODS
* CATCH_CONFIG_CPP11_NOEXCEPT
* CATCH_CONFIG_CPP11_NULLPTR
* CATCH_CONFIG_VARIADIC_MACROS
2017-04-25 12:43:19 +02:00
Phil Nash
97707afae1 Removed catch_type_traits from CMakeLists.txt 2017-04-25 11:09:06 +01:00
Phil Nash
1f3ba8a0b6 Converted (almost) all for-loops with iterators or indices to range-based 2017-04-25 11:07:02 +01:00
Phil Nash
073377a4e4 CMake defaults to C++11 2017-04-25 11:07:02 +01:00
Martin Hořeňovský
6a09425de1 Remove C++98 backcompat from evaluate 2017-04-25 11:28:40 +02:00
Martin Hořeňovský
c6e5738d54 Remove c++98 backcompat from timer 2017-04-25 11:25:49 +02:00
Martin Hořeňovský
c6980ec2d8 Remove C++98 backcompat from toString 2017-04-25 11:21:22 +02:00
Martin Hořeňovský
7c900660ef Removed superfluous reimplementation of type traits 2017-04-25 11:19:01 +02:00
Martin Hořeňovský
2fdd81a33f Removed C++98 backcompat from Approx
Now it always uses type traits to work with all types convertible to
double
2017-04-25 11:11:26 +02:00
214 changed files with 21096 additions and 24311 deletions

View File

@@ -5,19 +5,6 @@ matrix:
include: include:
# 1/ Linux Clang Builds # 1/ Linux Clang Builds
- os: linux
compiler: clang
addons: &clang34
apt:
sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test']
packages: ['clang']
env: COMPILER='clang++' BUILD_TYPE='Release'
- os: linux
compiler: clang
addons: *clang34
env: COMPILER='clang++' BUILD_TYPE='Debug'
- os: linux - os: linux
compiler: clang compiler: clang
addons: &clang35 addons: &clang35
@@ -75,34 +62,6 @@ matrix:
# 2/ Linux GCC Builds # 2/ Linux GCC Builds
- os: linux
compiler: gcc
addons: &gcc44
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.4']
env: COMPILER='g++-4.4' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: *gcc44
env: COMPILER='g++-4.4' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc47
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.7']
env: COMPILER='g++-4.7' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: *gcc47
env: COMPILER='g++-4.7' BUILD_TYPE='Debug'
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: &gcc48 addons: &gcc48
@@ -191,7 +150,7 @@ matrix:
addons: *gcc6 addons: *gcc6
env: COMPILER='g++-6' BUILD_TYPE='Debug' CPP14=1 env: COMPILER='g++-6' BUILD_TYPE='Debug' CPP14=1
# 4b/ Linux C++14 Clang builds # # 4b/ Linux C++14 Clang builds
# - os: linux # - os: linux
# compiler: clang # compiler: clang
# addons: *clang38 # addons: *clang38

View File

@@ -10,13 +10,13 @@ set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark) set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
set(HEADER_DIR ${CATCH_DIR}/include) set(HEADER_DIR ${CATCH_DIR}/include)
if(USE_CPP11) if(USE_CPP14)
## 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") message(STATUS "Enabling C++14")
set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
else()
message(STATUS "Enabling C++11")
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
endif() endif()
if(USE_WMAIN) if(USE_WMAIN)
@@ -55,6 +55,7 @@ endfunction()
set(TEST_SOURCES set(TEST_SOURCES
${SELF_TEST_DIR}/ApproxTests.cpp ${SELF_TEST_DIR}/ApproxTests.cpp
${SELF_TEST_DIR}/BDDTests.cpp ${SELF_TEST_DIR}/BDDTests.cpp
${SELF_TEST_DIR}/Benchmark.tests.cpp
${SELF_TEST_DIR}/ClassTests.cpp ${SELF_TEST_DIR}/ClassTests.cpp
${SELF_TEST_DIR}/CmdLineTests.cpp ${SELF_TEST_DIR}/CmdLineTests.cpp
${SELF_TEST_DIR}/CompilationTests.cpp ${SELF_TEST_DIR}/CompilationTests.cpp
@@ -62,7 +63,6 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/DecompositionTests.cpp ${SELF_TEST_DIR}/DecompositionTests.cpp
${SELF_TEST_DIR}/EnumToString.cpp ${SELF_TEST_DIR}/EnumToString.cpp
${SELF_TEST_DIR}/ExceptionTests.cpp ${SELF_TEST_DIR}/ExceptionTests.cpp
${SELF_TEST_DIR}/GeneratorTests.cpp
${SELF_TEST_DIR}/MessageTests.cpp ${SELF_TEST_DIR}/MessageTests.cpp
${SELF_TEST_DIR}/MiscTests.cpp ${SELF_TEST_DIR}/MiscTests.cpp
${SELF_TEST_DIR}/PartTrackerTests.cpp ${SELF_TEST_DIR}/PartTrackerTests.cpp
@@ -76,33 +76,30 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/TrickyTests.cpp ${SELF_TEST_DIR}/TrickyTests.cpp
${SELF_TEST_DIR}/VariadicMacrosTests.cpp ${SELF_TEST_DIR}/VariadicMacrosTests.cpp
${SELF_TEST_DIR}/MatchersTests.cpp ${SELF_TEST_DIR}/MatchersTests.cpp
${SELF_TEST_DIR}/StringRef.tests.cpp
) )
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR}) CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
# A set of impl files that just #include a single header # A set of impl files that just #include a single header
# Please keep these ordered alphabetically # Please keep these ordered alphabetically
set(IMPL_SOURCES set(SURROGATE_SOURCES
${SELF_TEST_DIR}/SurrogateCpps/catch_common.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.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_registry_hub.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.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_option.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_ptr.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
) )
CheckFileList(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps) CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
# Please keep these ordered alphabetically # Please keep these ordered alphabetically
@@ -115,8 +112,7 @@ CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
# Please keep these ordered alphabetically # Please keep these ordered alphabetically
set(EXTERNAL_HEADERS set(EXTERNAL_HEADERS
${HEADER_DIR}/external/clara.h ${HEADER_DIR}/external/clara.hpp
${HEADER_DIR}/external/tbc_text_format.h
) )
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
@@ -124,76 +120,64 @@ CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
# Please keep these ordered alphabetically # Please keep these ordered alphabetically
set(INTERNAL_HEADERS set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_approx.hpp ${HEADER_DIR}/internal/catch_approx.hpp
${HEADER_DIR}/internal/catch_assertionhandler.h
${HEADER_DIR}/internal/catch_assertioninfo.h
${HEADER_DIR}/internal/catch_assertionresult.h ${HEADER_DIR}/internal/catch_assertionresult.h
${HEADER_DIR}/internal/catch_assertionresult.hpp
${HEADER_DIR}/internal/catch_capture.hpp ${HEADER_DIR}/internal/catch_capture.hpp
${HEADER_DIR}/internal/catch_capture_matchers.h
${HEADER_DIR}/internal/catch_clara.h ${HEADER_DIR}/internal/catch_clara.h
${HEADER_DIR}/internal/catch_commandline.hpp ${HEADER_DIR}/internal/catch_commandline.hpp
${HEADER_DIR}/internal/catch_common.h ${HEADER_DIR}/internal/catch_common.h
${HEADER_DIR}/internal/catch_common.hpp
${HEADER_DIR}/internal/catch_compiler_capabilities.h ${HEADER_DIR}/internal/catch_compiler_capabilities.h
${HEADER_DIR}/internal/catch_config.hpp ${HEADER_DIR}/internal/catch_config.hpp
${HEADER_DIR}/internal/catch_console_colour.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.h
${HEADER_DIR}/internal/catch_context_impl.hpp
${HEADER_DIR}/internal/catch_debugger.h ${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_debugger.hpp ${HEADER_DIR}/internal/catch_decomposer.h
${HEADER_DIR}/internal/catch_default_main.hpp ${HEADER_DIR}/internal/catch_default_main.hpp
${HEADER_DIR}/internal/catch_errno_guard.hpp ${HEADER_DIR}/internal/catch_enforce.h
${HEADER_DIR}/internal/catch_evaluate.hpp ${HEADER_DIR}/internal/catch_errno_guard.h
${HEADER_DIR}/internal/catch_exception_translator_registry.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.h
${HEADER_DIR}/internal/catch_expression_lhs.hpp ${HEADER_DIR}/internal/catch_external_interfaces.h
${HEADER_DIR}/internal/catch_fatal_condition.hpp ${HEADER_DIR}/internal/catch_fatal_condition.h
${HEADER_DIR}/internal/catch_generators.hpp
${HEADER_DIR}/internal/catch_generators_impl.hpp
${HEADER_DIR}/internal/catch_impl.hpp ${HEADER_DIR}/internal/catch_impl.hpp
${HEADER_DIR}/internal/catch_interfaces_capture.h ${HEADER_DIR}/internal/catch_interfaces_capture.h
${HEADER_DIR}/internal/catch_interfaces_config.h ${HEADER_DIR}/internal/catch_interfaces_config.h
${HEADER_DIR}/internal/catch_interfaces_exception.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_registry_hub.h
${HEADER_DIR}/internal/catch_interfaces_reporter.h ${HEADER_DIR}/internal/catch_interfaces_reporter.h
${HEADER_DIR}/internal/catch_interfaces_runner.h ${HEADER_DIR}/internal/catch_interfaces_runner.h
${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h ${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h
${HEADER_DIR}/internal/catch_interfaces_testcase.h ${HEADER_DIR}/internal/catch_interfaces_testcase.h
${HEADER_DIR}/internal/catch_legacy_reporter_adapter.h ${HEADER_DIR}/internal/catch_leak_detector.h
${HEADER_DIR}/internal/catch_legacy_reporter_adapter.hpp ${HEADER_DIR}/internal/catch_list.h
${HEADER_DIR}/internal/catch_list.hpp
${HEADER_DIR}/internal/catch_matchers.hpp ${HEADER_DIR}/internal/catch_matchers.hpp
${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_string.h
${HEADER_DIR}/internal/catch_matchers_string.hpp
${HEADER_DIR}/internal/catch_matchers_vector.h ${HEADER_DIR}/internal/catch_matchers_vector.h
${HEADER_DIR}/internal/catch_message.h ${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.h
${HEADER_DIR}/internal/catch_notimplemented_exception.hpp
${HEADER_DIR}/internal/catch_objc.hpp ${HEADER_DIR}/internal/catch_objc.hpp
${HEADER_DIR}/internal/catch_objc_arc.hpp ${HEADER_DIR}/internal/catch_objc_arc.hpp
${HEADER_DIR}/internal/catch_option.hpp ${HEADER_DIR}/internal/catch_option.hpp
${HEADER_DIR}/internal/catch_platform.h ${HEADER_DIR}/internal/catch_platform.h
${HEADER_DIR}/internal/catch_ptr.hpp
${HEADER_DIR}/internal/catch_reenable_warnings.h ${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_registrars.hpp
${HEADER_DIR}/internal/catch_reporter_registry.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_result_type.h
${HEADER_DIR}/internal/catch_run_context.hpp ${HEADER_DIR}/internal/catch_run_context.hpp
${HEADER_DIR}/internal/catch_benchmark.h
${HEADER_DIR}/internal/catch_section.h ${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.h
${HEADER_DIR}/internal/catch_section_info.hpp ${HEADER_DIR}/internal/catch_startup_exception_registry.h
${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_stream.h
${HEADER_DIR}/internal/catch_stream.hpp
${HEADER_DIR}/internal/catch_streambuf.h ${HEADER_DIR}/internal/catch_streambuf.h
${HEADER_DIR}/internal/catch_stringref.h
${HEADER_DIR}/internal/catch_string_manip.h
${HEADER_DIR}/internal/catch_suppress_warnings.h ${HEADER_DIR}/internal/catch_suppress_warnings.h
${HEADER_DIR}/internal/catch_tag_alias.h ${HEADER_DIR}/internal/catch_tag_alias.h
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h
${HEADER_DIR}/internal/catch_tag_alias_registry.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.h
${HEADER_DIR}/internal/catch_test_case_info.hpp
${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp ${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp
${HEADER_DIR}/internal/catch_test_case_tracker.hpp ${HEADER_DIR}/internal/catch_test_case_tracker.hpp
${HEADER_DIR}/internal/catch_test_registry.hpp ${HEADER_DIR}/internal/catch_test_registry.hpp
@@ -201,32 +185,82 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_test_spec_parser.hpp ${HEADER_DIR}/internal/catch_test_spec_parser.hpp
${HEADER_DIR}/internal/catch_text.h ${HEADER_DIR}/internal/catch_text.h
${HEADER_DIR}/internal/catch_timer.h ${HEADER_DIR}/internal/catch_timer.h
${HEADER_DIR}/internal/catch_timer.hpp
${HEADER_DIR}/internal/catch_tostring.h ${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_tostring.hpp
${HEADER_DIR}/internal/catch_totals.hpp ${HEADER_DIR}/internal/catch_totals.hpp
${HEADER_DIR}/internal/catch_type_traits.hpp
${HEADER_DIR}/internal/catch_version.h ${HEADER_DIR}/internal/catch_version.h
${HEADER_DIR}/internal/catch_version.hpp
${HEADER_DIR}/internal/catch_wildcard_pattern.hpp ${HEADER_DIR}/internal/catch_wildcard_pattern.hpp
${HEADER_DIR}/internal/catch_windows_h_proxy.h ${HEADER_DIR}/internal/catch_windows_h_proxy.h
${HEADER_DIR}/internal/catch_xmlwriter.hpp ${HEADER_DIR}/internal/catch_xmlwriter.hpp
) )
CheckFileList(INTERNAL_HEADERS ${HEADER_DIR}/internal) set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_approx.cpp
${HEADER_DIR}/internal/catch_assertionhandler.cpp
${HEADER_DIR}/internal/catch_assertionresult.cpp
${HEADER_DIR}/internal/catch_benchmark.cpp
${HEADER_DIR}/internal/catch_capture_matchers.cpp
${HEADER_DIR}/internal/catch_commandline.cpp
${HEADER_DIR}/internal/catch_common.cpp
${HEADER_DIR}/internal/catch_config.cpp
${HEADER_DIR}/internal/catch_console_colour.cpp
${HEADER_DIR}/internal/catch_context.cpp
${HEADER_DIR}/internal/catch_debugger.cpp
${HEADER_DIR}/internal/catch_decomposer.cpp
${HEADER_DIR}/internal/catch_errno_guard.cpp
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
${HEADER_DIR}/internal/catch_fatal_condition.cpp
${HEADER_DIR}/internal/catch_list.cpp
${HEADER_DIR}/internal/catch_leak_detector.cpp
${HEADER_DIR}/internal/catch_matchers.cpp
${HEADER_DIR}/internal/catch_matchers_string.cpp
${HEADER_DIR}/internal/catch_message.cpp
${HEADER_DIR}/internal/catch_notimplemented_exception.cpp
${HEADER_DIR}/internal/catch_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
${HEADER_DIR}/internal/catch_result_type.cpp
${HEADER_DIR}/internal/catch_run_context.cpp
${HEADER_DIR}/internal/catch_section.cpp
${HEADER_DIR}/internal/catch_section_info.cpp
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
${HEADER_DIR}/internal/catch_stream.cpp
${HEADER_DIR}/internal/catch_stringref.cpp
${HEADER_DIR}/internal/catch_string_manip.cpp
${HEADER_DIR}/internal/catch_tag_alias.cpp
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.cpp
${HEADER_DIR}/internal/catch_tag_alias_registry.cpp
${HEADER_DIR}/internal/catch_test_case_info.cpp
${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp
${HEADER_DIR}/internal/catch_test_case_tracker.cpp
${HEADER_DIR}/internal/catch_test_registry.cpp
${HEADER_DIR}/internal/catch_test_spec.cpp
${HEADER_DIR}/internal/catch_test_spec_parser.cpp
${HEADER_DIR}/internal/catch_timer.cpp
${HEADER_DIR}/internal/catch_tostring.cpp
${HEADER_DIR}/internal/catch_totals.cpp
${HEADER_DIR}/internal/catch_version.cpp
${HEADER_DIR}/internal/catch_wildcard_pattern.cpp
${HEADER_DIR}/internal/catch_xmlwriter.cpp
)
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal)
# Please keep these ordered alphabetically # Please keep these ordered alphabetically
set(REPORTER_HEADERS set(REPORTER_HEADERS
${HEADER_DIR}/reporters/catch_reporter_automake.hpp ${HEADER_DIR}/reporters/catch_reporter_automake.hpp
${HEADER_DIR}/reporters/catch_reporter_bases.hpp ${HEADER_DIR}/reporters/catch_reporter_bases.hpp
${HEADER_DIR}/reporters/catch_reporter_compact.hpp ${HEADER_DIR}/reporters/catch_reporter_multi.h
${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_tap.hpp ${HEADER_DIR}/reporters/catch_reporter_tap.hpp
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
${HEADER_DIR}/reporters/catch_reporter_xml.hpp
) )
CheckFileList(REPORTER_HEADERS ${HEADER_DIR}/reporters) set(REPORTER_SOURCES
${HEADER_DIR}/reporters/catch_reporter_bases.cpp
${HEADER_DIR}/reporters/catch_reporter_compact.cpp
${HEADER_DIR}/reporters/catch_reporter_console.cpp
${HEADER_DIR}/reporters/catch_reporter_junit.cpp
${HEADER_DIR}/reporters/catch_reporter_multi.cpp
${HEADER_DIR}/reporters/catch_reporter_xml.cpp
)
set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})
CheckFileList(REPORTER_FILES ${HEADER_DIR}/reporters)
# Specify the headers, too, so CLion recognises them as project files # Specify the headers, too, so CLion recognises them as project files
set(HEADERS set(HEADERS
@@ -245,17 +279,19 @@ CheckFileList(BENCH_SOURCES ${BENCHMARK_DIR})
# Provide some groupings for IDEs # Provide some groupings for IDEs
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES}) SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
SOURCE_GROUP("Surrogates" FILES ${IMPL_SOURCES}) SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES}) SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES})
# configure the executable # configure the executable
include_directories(${HEADER_DIR}) include_directories(${HEADER_DIR})
add_definitions( -DCATCH_CONFIG_FULL_PROJECT )
# Projects consuming Catch via ExternalProject_Add might want to use install step # Projects consuming Catch via ExternalProject_Add might want to use install step
# without building all of our selftests. # without building all of our selftests.
if (NOT NO_SELFTEST) if (NOT NO_SELFTEST)
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${HEADERS}) add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
add_executable(Benchmark ${BENCH_SOURCES} ${HEADERS}) add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${HEADERS})
# Add desired warnings # Add desired warnings
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )

View File

@@ -1,15 +1,18 @@
![catch logo](catch-logo-small.png) ![catch logo](catch-logo-small.png)
[![Github Releases](https://img.shields.io/github/release/philsquared/catch.svg)](https://github.com/philsquared/catch/releases) [![Github Releases](https://img.shields.io/github/release/philsquared/catch.svg)](https://github.com/philsquared/catch/releases)
[![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch) [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=catch2)](https://travis-ci.org/philsquared/Catch?branch=catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master) [![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/catch2?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/jG7wnHX9VAcxpSHy)
<a href="https://github.com/philsquared/Catch/releases/download/v1.12.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a> <a href="https://github.com/philsquared/Catch/releases/download/v2.0.0-develop.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## What's the Catch? ## What's the Catch?
Catch stands for C++ Automated Test Cases in Headers and is a multi-paradigm automated test framework for C++ and Objective-C (and, maybe, C). It is implemented entirely in a set of header files, but is packaged up as a single header for extra convenience. Catch stands for C++ Automated Test Cases in Headers and is a
multi-paradigm test framework for C++. which also supports Objective-C
and, maybe, C.
It is primarily distributed as a single header file, although certain
extensions may require additional headers.
## How to use it ## How to use it
This documentation comprises these three parts: This documentation comprises these three parts:
@@ -22,7 +25,3 @@ This documentation comprises these three parts:
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues) * 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) * For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
* See [who else is using Catch](docs/opensource-users.md) * See [who else is using Catch](docs/opensource-users.md)
## Help us out
We're currently running [a survey](https://www.surveymonkey.co.uk/r/TLLYQJW) to help us shape the future of Catch.
Please take a few moments to fill it out (there's only ten questions).

View File

@@ -4,7 +4,6 @@ version: "{build}"
os: os:
- Visual Studio 2017 - Visual Studio 2017
- Visual Studio 2015 - Visual Studio 2015
- Visual Studio 2013
environment: environment:
matrix: matrix:

View File

@@ -4,7 +4,7 @@ from conans import ConanFile
class CatchConan(ConanFile): class CatchConan(ConanFile):
name = "Catch" name = "Catch"
version = "1.12.2" version = "2.0.0-develop.2"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared" author = "philsquared"
generators = "cmake" generators = "cmake"
@@ -14,6 +14,3 @@ class CatchConan(ConanFile):
def package(self): def package(self):
self.copy(pattern="catch.hpp", src="single_include", dst="include") self.copy(pattern="catch.hpp", src="single_include", dst="include")
def package_id(self):
self.info.header_only()

View File

@@ -36,8 +36,6 @@
# -- adds fixture class name to the test name # # -- adds fixture class name to the test name #
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) # # PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
# -- adds cmake target name to the test name # # -- adds cmake target name to the test name #
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
# # # #
#==================================================================================================# #==================================================================================================#
@@ -47,7 +45,6 @@ option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OF
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF) option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON) option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON) option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
function(PrintDebugMessage) function(PrintDebugMessage)
if(PARSE_CATCH_TESTS_VERBOSE) if(PARSE_CATCH_TESTS_VERBOSE)
@@ -88,15 +85,6 @@ function(ParseFile SourceFile TestTarget)
# Find definition of test names # Find definition of test names
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}") string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
set_property(
DIRECTORY
APPEND
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
)
endif()
foreach(TestName ${Tests}) foreach(TestName ${Tests})
# Strip newlines # Strip newlines
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}") string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")

View File

@@ -57,7 +57,7 @@ This way `Approx` is constructed with reasonable defaults, covering most simple
* __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`. * __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`.
* __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`. * __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`.
* __scale__ - scale serves to adjust the base for comparison used by epsilon. By default set to `1.0`. * __scale__ - scale serves to adjust the base for comparison used by epsilon, can be used when By default set to `1.0`.
#### epsilon example #### epsilon example
```cpp ```cpp
@@ -77,7 +77,7 @@ Approx target = Approx(100).margin(5);
``` ```
#### scale #### scale
Scale can be useful if the computation leading to the result worked on different scale, than is used by the results (and thus expected errors are on a different scale than would be expected based on the results alone), i.e. an additional not scaling difference will be accepted, because | current - target | < eps_rel + eps_abs (while eps_rel = max(current, target) * epsilon, eps_abs = epsilon * scale) will be checked. Scale can be useful if the computation leading to the result worked on different scale, than is used by the results (and thus expected errors are on a different scale than would be expected based on the results alone).
## Exceptions ## Exceptions
@@ -95,7 +95,7 @@ Expects that an exception (of any type) is be thrown during evaluation of the ex
* **REQUIRE_THROWS_AS(** _expression_, _exception type_ **)** and * **REQUIRE_THROWS_AS(** _expression_, _exception type_ **)** and
* **CHECK_THROWS_AS(** _expression_, _exception type_ **)** * **CHECK_THROWS_AS(** _expression_, _exception type_ **)**
Expects that an exception of the _specified type_ is thrown during evaluation of the expression. Note that the _exception type_ is used verbatim and you should include (const) reference. Expects that an exception of the _specified type_ is thrown during evaluation of the expression. Note that the _exception type_ is extended with `const&` and you should not include it yourself.
* **REQUIRE_THROWS_WITH(** _expression_, _string or string matcher_ **)** and * **REQUIRE_THROWS_WITH(** _expression_, _string or string matcher_ **)** and
* **CHECK_THROWS_WITH(** _expression_, _string or string matcher_ **)** * **CHECK_THROWS_WITH(** _expression_, _string or string matcher_ **)**
@@ -108,8 +108,13 @@ REQUIRE_THROWS_WITH( openThePodBayDoors(), Contains( "afraid" ) && Contains( "ca
REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" ); REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" );
``` ```
* **REQUIRE_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** and
* **CHECK_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)**
Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function. Expects that exception of _exception type_ is thrown and it matches provided matcher (see next section for Matchers).
_Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function._
```cpp ```cpp
REQUIRE_NOTHROW([&](){ REQUIRE_NOTHROW([&](){
@@ -122,6 +127,8 @@ REQUIRE_NOTHROW([&](){
}()); }());
``` ```
## Matcher expressions ## Matcher expressions
To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md). To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md).

View File

@@ -15,7 +15,7 @@ The XML Reporter writes in an XML format that is specific to Catch.
The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing. The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course. The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course.
## JUnit Reporter ## JUnit Reporter
```-r junit``` ```-r junit```

View File

@@ -29,6 +29,7 @@ Click one of the followings links to take you straight to that option - or scrol
<a href="#rng-seed"> ` --rng-seed`</a><br /> <a href="#rng-seed"> ` --rng-seed`</a><br />
<a href="#libidentify"> ` --libidentify`</a><br /> <a href="#libidentify"> ` --libidentify`</a><br />
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br /> <a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
</br> </br>
@@ -228,6 +229,13 @@ See [The LibIdentify repo for more information and examples](https://github.com/
Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing - Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing -
either before running any tests, after running all tests - or both, depending on the argument. either before running any tests, after running all tests - or both, depending on the argument.
<a id="benchmark-resolution-multiple"></a>
## Specify multiples of clock resolution to run benchmarks for
<pre>--benchmark-resolution-multiple &lt;multiplier&gt;</pre>
When running benchmarks the clock resolution is estimated. Benchmarks are then run for exponentially increasing
numbers of iterations until some multiple of the estimated resolution is exceed. By default that multiple is 100, but
it can be overriden here.
<a id="usage"></a> <a id="usage"></a>
## Usage ## Usage

View File

@@ -51,63 +51,16 @@ Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly
This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems. This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
# Default reporter
CATCH_CONFIG_DEFAULT_REPORTER <reporter>
The default reporter (reporter used when no reporters are explicitly specified) can be overriden during compilation time by using the above macro. Note that desired value of the macro is a C string and quotes have to be escaped during compilation: `clang++ test.cpp -DCATCH_CONFIG_DEFAULT_REPORTER=\"xml\"`.
# C++ conformance toggles
CATCH_CONFIG_CPP11_NULLPTR // nullptr is supported?
CATCH_CONFIG_CPP11_NOEXCEPT // noexcept is supported?
CATCH_CONFIG_CPP11_GENERATED_METHODS // delete and default keywords for methods
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_CONFIG_CPP11_TYPE_TRAITS // Use std::enable_if and <type_traits>
CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK // Use C++11 expression SFINAE to check if class can be inserted to std::ostream
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.
You may also suppress any of these features by using the `_NO_` form, e.g. `CATCH_CONFIG_CPP11_NO_NULLPTR`.
All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11`
## `CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK`
This flag is off by default, but allows you to resolve problems caused by types with private base class that are streamable, but the classes themselves are not. Without it, the following code will cause a compilation error:
```cpp
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
struct A {};
std::ostream &operator<< (std::ostream &o, const A &v) { return o << 0; }
struct B : private A {
bool operator==(int){ return true;}
};
B f ();
std::ostream g ();
TEST_CASE ("Error in streamable check") {
B x;
REQUIRE (x == 4);
}
```
# Other toggles # Other toggles
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows
CATCH_CONFIG_FAST_COMPILE // Sacrifices some (rather minor) features for compilation speed CATCH_CONFIG_FAST_COMPILE // Sacrifices some (rather minor) features for compilation speed
CATCH_CONFIG_DISABLE_MATCHERS // Do not compile Matchers in this compilation unit
CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals
CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support. Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
@@ -115,7 +68,7 @@ Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC,
`CATCH_CONFIG_WINDOWS_CRTDBG` is off by default. If enabled, Windows's CRT is used to check for memory leaks, and displays them after the tests finish running. `CATCH_CONFIG_WINDOWS_CRTDBG` is off by default. If enabled, Windows's CRT is used to check for memory leaks, and displays them after the tests finish running.
Just as with the C++11 conformance toggles, these toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`. These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
## `CATCH_CONFIG_FAST_COMPILE` ## `CATCH_CONFIG_FAST_COMPILE`
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes: Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:
@@ -124,9 +77,12 @@ Defining this flag speeds up compilation of test files by ~20%, by making 2 chan
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable. `CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable.
## `CATCH_CONFIG_DISABLE_STRINGIFICATION`
This toggle enables a workaround for VS 2017 bug. For details see ## `CATCH_CONFIG_DISABLE_MATCHERS`
[known limitations](limitations.md#visual-studio-2017----raw-string-literal-in-assert-fails-to-compile). When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU.
_Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._
# Windows header clutter # Windows header clutter

View File

@@ -50,38 +50,6 @@ Both of these solutions have their problems, but should let you wring parallelis
## 3rd party bugs ## 3rd party bugs
This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes). This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes).
### Visual Studio 2017 -- raw string literal in assert fails to compile
There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error:
```cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("test") {
CHECK(std::string(R"("\)") == "\"\\");
}
```
Catch provides a workaround, it is possible to disable stringification of original expressions by defining `CATCH_CONFIG_DISABLE_STRINGIFICATION`:
```cpp
#define CATCH_CONFIG_FAST_COMPILE
#define CATCH_CONFIG_DISABLE_STRINGIFICATION
#include "catch.hpp"
TEST_CASE("test") {
CHECK(std::string(R"("\)") == "\"\\");
}
```
_Do note that this changes the output somewhat_
```
catchwork\test1.cpp(6):
PASSED:
CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
with expansion:
""\" == ""\"
```
### Visual Studio 2013 -- do-while loop withing range based for fails to compile (C2059) ### Visual Studio 2013 -- do-while loop withing range based for fails to compile (C2059)
There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error
```cpp ```cpp

View File

@@ -1,6 +1,6 @@
# Open Source projects using Catch # Open Source projects using Catch
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution Catch is great for open source. With it's [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
it's easy to just drop the header into your project and start writing tests - what's not to like? it's easy to just drop the header into your project and start writing tests - what's not to like?
As a result Catch is now being used in many Open Source projects, including some quite well known ones. As a result Catch is now being used in many Open Source projects, including some quite well known ones.

View File

@@ -16,15 +16,14 @@ If you just need to have code that executes before and/ or after Catch this is t
#define CATCH_CONFIG_RUNNER #define CATCH_CONFIG_RUNNER
#include "catch.hpp" #include "catch.hpp"
int main( int argc, char* argv[] ) int main( int argc, char* argv[] ) {
{
// global setup... // global setup...
int result = Catch::Session().run( argc, argv ); int result = Catch::Session().run( argc, argv );
// global clean-up... // global clean-up...
return ( result < 0xff ? result : 0xff ); return result;
} }
``` ```
@@ -43,6 +42,21 @@ int main( int argc, char* argv[] )
// writing to session.configData() here sets defaults // writing to session.configData() here sets defaults
// this is the preferred way to set them // this is the preferred way to set them
// Verify that all tests, aliases, etc registered properly
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
if ( !exceptions.empty() ) {
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
std::rethrow_exception(ex_ptr);
} catch (std::exception const& ex) {
Catch::cerr() << ex.what();
}
}
// Indicate that an error occured before main
return 1;
}
int returnCode = session.applyCommandLine( argc, argv ); int returnCode = session.applyCommandLine( argc, argv );
if( returnCode != 0 ) // Indicates a command line error if( returnCode != 0 ) // Indicates a command line error
return returnCode; return returnCode;
@@ -52,10 +66,10 @@ int main( int argc, char* argv[] )
// only do this if you know you need to // only do this if you know you need to
int numFailed = session.run(); int numFailed = session.run();
// Note that on unices only the lower 8 bits are usually used, clamping // numFailed is clamped to 255 as some unices only use the lower 8 bits.
// the return value to 255 prevents false negative when some multiple // This clamping has already been applied, so just return it here
// of 256 tests has failed // You can also do any post run clean-up here
return ( numFailed < 0xff ? numFailed : 0xff ); return numFailed;
} }
``` ```

View File

@@ -1,79 +1,3 @@
# 1.12.2
### Fixes
* Fixed missing <cassert> include
# 1.12.1
### Fixes
* Fixed deprecation warning in `ScopedMessage::~ScopedMessage`
* All uses of `min` or `max` identifiers are now wrapped in parentheses
* This avoids problems when Windows headers define `min` and `max` macros
# 1.12.0
### Fixes
* Fixed compilation for strict C++98 mode (ie not gnu++98) and older compilers (#1103)
* `INFO` messages are included in the `xml` reporter output even without `-s` specified.
# 1.11.0
### Fixes
* The original expression in `REQUIRE_FALSE( expr )` is now reporter properly as `!( expr )` (#1051)
* Previously the parentheses were missing and `x != y` would be expanded as `!x != x`
* `Approx::Margin` is now inclusive (#952)
* Previously it was meant and documented as inclusive, but the check itself wasn't
* This means that `REQUIRE( 0.25f == Approx( 0.0f ).margin( 0.25f ) )` passes, instead of fails
* `RandomNumberGenerator::result_type` is now unsigned (#1050)
### Improvements
* `__JETBRAINS_IDE__` macro handling is now CLion version specific (#1017)
* When CLion 2017.3 or newer is detected, `__COUNTER__` is used instead of
* TeamCity reporter now explicitly flushes output stream after each report (#1057)
* On some platforms, output from redirected streams would show up only after the tests finished running
* `ParseAndAddCatchTests` now can add test files as dependency to CMake configuration
* This means you do not have to manually rerun CMake configuration step to detect new tests
# 1.10.0
### Fixes
* Evaluation layer has been rewritten (backported from Catch 2)
* The new layer is much simpler and fixes some issues (#981)
* Implemented workaround for VS 2017 raw string literal stringification bug (#995)
* Fixed interaction between `[!shouldfail]` and `[!mayfail]` tags and sections
* Previously sections with failing assertions would be marked as failed, not failed-but-ok
### Improvements
* Added [libidentify](https://github.com/janwilmans/LibIdentify) support
* Added "wait-for-keypress" option
# 1.9.7
### Fixes
* Various warnings from clang-tidy, Resharper-C++ and PVS Studio have been addressed (#957)
* Dynamically generated sections are now properly reported (#963)
* Writes to `std::clog` are redirected for reporters (#989)
* Previously only `std::cerr` writes were redirected
* Interleaved writes to `std::cerr` and `std::clog` are combined properly
* Assertions failed before signals/structured exceptions fails test case are properly reported as failed (#990)
### Improvements
* Catch's runtime overhead has been decreased further (#940)
* Added support for IBM i ILE c++ compiler (#976)
* This means that AS/400 is now supported.
* The default reporter can be configured at compile time (#978)
* That is, the reporter used if no reporter is explicitly specified
### Other
* `ParseAndAddCatchTests` cmake script has couple new customization options
# 1.9.6 # 1.9.6
### Improvements ### Improvements

View File

@@ -22,7 +22,7 @@ Because of the way the junit format is structured the run must complete before a
* `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively. * `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively.
There are a few additional reporters, for specific build systems, in the Catch repository (in `include\reporters`) which you can `#include` in your project if you would like to make use of them. There are a few additional reporters, for specific build systems, in the Catch repository (in `include\reporters`) which you can `#include` in your project if you would like to make use of them.
Do this in one source file - typically the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`. Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`.
* `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands. * `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands.
Use this when building as part of a TeamCity build to see results as they happen. Use this when building as part of a TeamCity build to see results as they happen.

View File

@@ -38,19 +38,19 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
* `[!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`. * `[!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`.
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests. * `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests.
* `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes. * `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes.
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers. * `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`. * `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
* `[@<alias>]` - tag aliases all begin with `@` (see below). * `[@<alias>]` - tag aliases all begin with `@` (see below).
## Tag aliases ## Tag aliases
Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. This can be done, in code, using the following form: Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form:
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> ) CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )

View File

@@ -1,7 +1,7 @@
# String conversions # String conversions
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
Most built-in or std types are supported out of the box but there are three ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
## operator << overload for std::ostream ## operator << overload for std::ostream
@@ -16,30 +16,15 @@ std::ostream& operator << ( std::ostream& os, T const& value ) {
(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function). (where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
You should put this function in the same namespace as your type and it has to be declared before including Catch's header. You should put this function in the same namespace as your type and have it declared before including Catch's header.
## Catch::toString overload
If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide an overload for ```Catch::toString()``` for your type.
```
namespace Catch {
std::string toString( T const& value ) {
return convertMyTypeToString( value );
}
}
```
Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace and must be declared _before_ Catch's header is included.
**Please note that overloading `Catch::toString` is currently considered legacy and will not be supported in the next major version of Catch.**
## Catch::StringMaker<T> specialisation ## Catch::StringMaker<T> specialisation
Another way of telling Catch how to convert a type to string is specialising `Catch::StringMaker` template. This allows you to have separate way of stringifying types for Catch, than you have for writing it to a stream and also doesn't require you to declare it before including Catch's header. If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide a specialization for `Catch::StringMaker<T>`:
``` ```
namespace Catch { namespace Catch {
template<> struct StringMaker<T> { template<>
struct StringMaker<T> {
static std::string convert( T const& value ) { static std::string convert( T const& value ) {
return convertMyTypeToString( value ); return convertMyTypeToString( value );
} }

View File

@@ -1,45 +1,44 @@
# Why do we need yet another C++ test framework? # Why do we need yet another C++ test framework?
Good question. For C++ there are quite a number of established frameworks, including (but not limited to), [CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page), [Google Test](http://code.google.com/p/googletest/), [Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html), [Aeryn](https://launchpad.net/aeryn), [Cute](http://r2.ifs.hsr.ch/cute), [Fructose](http://fructose.sourceforge.net/) and [many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B). Even for Objective-C there are a few, including OCUnit - which now comes bundled with XCode. Good question. For C++ there are quite a number of established frameworks,
including (but not limited to),
[Google Test](http://code.google.com/p/googletest/),
[Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html),
[CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page),
[Cute](http://r2.ifs.hsr.ch/cute),
[many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B).
So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course. So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course.
## Key Features ## Key Features
* Really easy to get started. Just download catch.hpp, #include it and you're away. * Quick and Really easy to get started. Just download catch.hpp, `#include` it and you're away.
* No external dependencies. As long as you can compile C++98 and have a C++ standard library available. * No external dependencies. As long as you can compile C++11 and have a C++ standard library available.
* Write test cases as, self-registering, functions or methods. * Write test cases as, self-registering, functions (or methods, if you prefer).
* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures!) * Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures).
* Use BDD-style Given-When-Then sections as well as traditional unit test cases. * Use BDD-style Given-When-Then sections as well as traditional unit test cases.
* Only one core assertion macro for comparisons. Standard C/C++ operators are used for the comparison - yet the full expression is decomposed and lhs and rhs values are logged. * Only one core assertion macro for comparisons. Standard C/C++ operators are used for the comparison - yet the full expression is decomposed and lhs and rhs values are logged.
* Tests are named using free-form strings - no more couching names in legal identifiers.
## Other core features ## Other core features
* Tests are named using free-form strings - no more couching names in legal identifiers.
* Tests can be tagged for easily running ad-hoc groups of tests. * Tests can be tagged for easily running ad-hoc groups of tests.
* Failures can (optionally) break into the debugger on Windows and Mac. * Failures can (optionally) break into the debugger on Windows and Mac.
* Output is through modular reporter objects. Basic textual and XML reporters are included. Custom reporters can easily be added. * Output is through modular reporter objects. Basic textual and XML reporters are included. Custom reporters can easily be added.
* JUnit xml output is supported for integration with third-party tools, such as CI servers. * JUnit xml output is supported for integration with third-party tools, such as CI servers.
* A default main() function is provided (in a header), but you can supply your own for complete control (e.g. integration into your own test runner GUI). * A default main() function is provided, but you can supply your own for complete control (e.g. integration into your own test runner GUI).
* A command line parser is provided and can still be used if you choose to provided your own main() function. * A command line parser is provided and can still be used if you choose to provided your own main() function.
* Catch can test itself. * Catch can test itself.
* Alternative assertion macro(s) report failures but don't abort the test case * Alternative assertion macro(s) report failures but don't abort the test case
* Floating point tolerance comparisons are built in using an expressive Approx() syntax. * Floating point tolerance comparisons are built in using an expressive Approx() syntax.
* Internal and friendly macros are isolated so name clashes can be managed * Internal and friendly macros are isolated so name clashes can be managed
* Support for Matchers (early stages) * Matchers
## Objective-C-specific features
* Automatically detects if you are using it from an Objective-C project
* Works with and without ARC with no additional configuration
* Implement test fixtures using Obj-C classes too (like OCUnit)
* Additional built in matchers that work with Obj-C types (e.g. string matchers)
## Who else is using Catch? ## Who else is using Catch?
See the list of [open source projects using Catch](opensource-users.md). See the list of [open source projects using Catch](opensource-users.md).
See the [tutorial](tutorial.md) to get more of a taste of using CATCH in practice See the [tutorial](tutorial.md) to get more of a taste of using Catch in practice
--- ---

View File

@@ -19,6 +19,7 @@
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL # define CATCH_IMPL
# define CATCH_CONFIG_EXTERNAL_INTERFACES
#endif #endif
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
@@ -28,19 +29,21 @@
# endif # endif
#endif #endif
#include "internal/catch_notimplemented_exception.h"
#include "internal/catch_context.h" #include "internal/catch_context.h"
#include "internal/catch_tag_alias_autoregistrar.h"
#include "internal/catch_test_registry.hpp" #include "internal/catch_test_registry.hpp"
#include "internal/catch_capture.hpp" #include "internal/catch_capture.hpp"
#include "internal/catch_section.h" #include "internal/catch_section.h"
#include "internal/catch_generators.hpp" #include "internal/catch_benchmark.h"
#include "internal/catch_interfaces_exception.h" #include "internal/catch_interfaces_exception.h"
#include "internal/catch_approx.hpp" #include "internal/catch_approx.hpp"
#include "internal/catch_matchers_string.h"
#include "internal/catch_matchers_vector.h"
#include "internal/catch_compiler_capabilities.h" #include "internal/catch_compiler_capabilities.h"
#include "internal/catch_interfaces_tag_alias_registry.h" #include "internal/catch_interfaces_tag_alias_registry.h"
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
#include "internal/catch_capture_matchers.h"
#endif
// These files are included here so the single_include script doesn't put them // These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections // in the conditionally compiled sections
#include "internal/catch_test_case_info.h" #include "internal/catch_test_case_info.h"
@@ -50,30 +53,11 @@
#include "internal/catch_objc.hpp" #include "internal/catch_objc.hpp"
#endif #endif
#ifdef CATCH_IMPL #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
#include "internal/catch_external_interfaces.h"
// !TBD: Move the leak detector code into a separate header
#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
#include <crtdbg.h>
class LeakDetector {
public:
LeakDetector() {
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
flag |= _CRTDBG_LEAK_CHECK_DF;
flag |= _CRTDBG_ALLOC_MEM_DF;
_CrtSetDbgFlag(flag);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
// Change this to leaking allocation's number to break there
_CrtSetBreakAlloc(-1);
}
};
#else
class LeakDetector {};
#endif #endif
LeakDetector leakDetector; #ifdef CATCH_IMPL
#include "internal/catch_impl.hpp" #include "internal/catch_impl.hpp"
#endif #endif
@@ -87,133 +71,103 @@ LeakDetector leakDetector;
#endif #endif
////// //////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL #ifdef CATCH_CONFIG_PREFIX_ALL
#if defined(CATCH_CONFIG_FAST_COMPILE) #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
#else
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
#endif
#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
#endif// CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
#if defined(CATCH_CONFIG_FAST_COMPILE)
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
#else
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
#endif #endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#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_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_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_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#else
#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_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
#define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
#endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#else #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc )
#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc )
#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
#endif #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc )
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else #else
#if defined(CATCH_CONFIG_FAST_COMPILE) #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
#else #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr )
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
#endif
#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
#if defined(CATCH_CONFIG_FAST_COMPILE)
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
#else
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
#endif #endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __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 METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
@@ -222,40 +176,21 @@ LeakDetector leakDetector;
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#else #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
#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( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
#define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
#endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
#endif #endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#else
#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #define WHEN( desc ) SECTION( std::string(" When: ") + desc )
#endif #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) #define THEN( desc ) SECTION( std::string(" Then: ") + desc )
#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc )
#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
using Catch::Detail::Approx; using Catch::Detail::Approx;

View File

@@ -9,62 +9,57 @@
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
#include "internal/catch_commandline.hpp" #include "internal/catch_commandline.hpp"
#include "internal/catch_list.hpp" #include "internal/catch_console_colour.hpp"
#include "internal/catch_enforce.h"
#include "internal/catch_list.h"
#include "internal/catch_run_context.hpp" #include "internal/catch_run_context.hpp"
#include "internal/catch_test_spec.hpp" #include "internal/catch_test_spec.hpp"
#include "internal/catch_version.h" #include "internal/catch_version.h"
#include "internal/catch_interfaces_reporter.h"
#include "internal/catch_startup_exception_registry.h"
#include "internal/catch_text.h" #include "internal/catch_text.h"
#include <fstream> #include <fstream>
#include <stdlib.h> #include <cstdlib>
#include <limits> #include <limits>
#include <iomanip>
namespace Catch { namespace Catch {
Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) { IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) {
Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config );
if( !reporter ) { CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" );
std::ostringstream oss;
oss << "No reporter registered with name: '" << reporterName << "'";
throw std::domain_error( oss.str() );
}
return reporter; return reporter;
} }
#if !defined(CATCH_CONFIG_DEFAULT_REPORTER) #ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console" #define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif #endif
Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) { IStreamingReporterPtr makeReporter( std::shared_ptr<Config> const& config ) {
std::vector<std::string> reporters = config->getReporterNames(); auto const& reporterNames = config->getReporterNames();
if( reporters.empty() ) if( reporterNames.empty() )
reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER ); return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config );
Ptr<IStreamingReporter> reporter; IStreamingReporterPtr reporter;
for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end(); for( auto const& name : reporterNames )
it != itEnd; addReporter( reporter, createReporter( name, config ) );
++it )
reporter = addReporter( reporter, createReporter( *it, config ) );
return reporter; return reporter;
} }
Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) { void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) {
IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); auto const& listeners = getRegistryHub().getReporterRegistry().getListeners();
for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); for( auto const& listener : listeners )
it != itEnd; addReporter(reporters, listener->create( ReporterConfig( config ) ) );
++it )
reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
return reporters;
} }
Totals runTests( Ptr<Config> const& config ) { Totals runTests( std::shared_ptr<Config> const& config ) {
Ptr<IConfig const> iconfig = config.get(); IStreamingReporterPtr reporter = makeReporter( config );
addListeners( reporter, config );
Ptr<IStreamingReporter> reporter = makeReporter( config ); RunContext context( config, std::move( reporter ) );
reporter = addListeners( iconfig, reporter );
RunContext context( iconfig, reporter );
Totals totals; Totals totals;
@@ -74,27 +69,24 @@ namespace Catch {
if( !testSpec.hasFilters() ) if( !testSpec.hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig ); std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *config );
for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); for( auto const& testCase : allTestCases ) {
it != itEnd; if( !context.aborting() && matchTest( testCase, testSpec, *config ) )
++it ) { totals += context.runTest( testCase );
if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
totals += context.runTest( *it );
else else
reporter->skipTest( *it ); context.reporter().skipTest( testCase );
} }
context.testGroupEnded( iconfig->name(), totals, 1, 1 ); context.testGroupEnded( config->name(), totals, 1, 1 );
return totals; return totals;
} }
void applyFilenamesAsTags( IConfig const& config ) { void applyFilenamesAsTags( IConfig const& config ) {
std::vector<TestCase> const& tests = getAllTestCasesSorted( config ); auto& tests = const_cast<std::vector<TestCase>&>( getAllTestCasesSorted( config ) );
for(std::size_t i = 0; i < tests.size(); ++i ) { for( auto& testCase : tests ) {
TestCase& test = const_cast<TestCase&>( tests[i] ); auto tags = testCase.tags;
std::set<std::string> tags = test.tags;
std::string filename = test.lineInfo.file; std::string filename = testCase.lineInfo.file;
std::string::size_type lastSlash = filename.find_last_of( "\\/" ); std::string::size_type lastSlash = filename.find_last_of( "\\/" );
if( lastSlash != std::string::npos ) if( lastSlash != std::string::npos )
filename = filename.substr( lastSlash+1 ); filename = filename.substr( lastSlash+1 );
@@ -103,36 +95,32 @@ namespace Catch {
if( lastDot != std::string::npos ) if( lastDot != std::string::npos )
filename = filename.substr( 0, lastDot ); filename = filename.substr( 0, lastDot );
tags.insert( '#' + filename ); tags.push_back( '#' + filename );
setTags( test, tags ); setTags( testCase, tags );
} }
} }
class Session : NonCopyable { class Session : NonCopyable {
static bool alreadyInstantiated; static const int MaxExitCode;
public: public:
struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; Session() {
static bool alreadyInstantiated = false;
Session() if( alreadyInstantiated )
: m_cli( makeCommandLineParser() ) { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" );
if( alreadyInstantiated ) {
std::string msg = "Only one instance of Catch::Session can ever be used";
Catch::cerr() << msg << std::endl;
throw std::logic_error( msg );
}
alreadyInstantiated = true; alreadyInstantiated = true;
m_cli = makeCommandLineParser( m_configData );
} }
~Session() { ~Session() override {
Catch::cleanUp(); Catch::cleanUp();
} }
void showHelp( std::string const& processName ) { void showHelp() const {
Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; Catch::cout()
<< "\nCatch v" << libraryVersion() << "\n"
m_cli.usage( Catch::cout(), processName ); << m_cli << std::endl
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; << "For more detailed usage please see the project docs\n" << std::endl;
} }
void libIdentify() { void libIdentify() {
Catch::cout() Catch::cout()
@@ -142,37 +130,45 @@ namespace Catch {
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
} }
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { int applyCommandLine( int argc, char* argv[] ) {
try { auto result = m_cli.parse( clara::Args( argc, argv ) );
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); if( !result ) {
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); Catch::cerr()
<< Colour( Colour::Red )
<< "\nError(s) in input:\n"
<< Column( result.errorMessage() ).indent( 2 )
<< "\n\n";
Catch::cerr() << "Run with -? for usage\n" << std::endl;
return MaxExitCode;
}
if( m_configData.showHelp ) if( m_configData.showHelp )
showHelp( m_configData.processName ); showHelp();
if( m_configData.libIdentify ) if( m_configData.libIdentify )
libIdentify(); libIdentify();
m_config.reset(); m_config.reset();
}
catch( std::exception& ex ) {
{
Colour colourGuard( Colour::Red );
Catch::cerr()
<< "\nError(s) in input:\n"
<< Text( ex.what(), TextAttributes().setIndent(2) )
<< "\n\n";
}
m_cli.usage( Catch::cout(), m_configData.processName );
return (std::numeric_limits<int>::max)();
}
return 0; return 0;
} }
void useConfigData( ConfigData const& _configData ) { void useConfigData( ConfigData const& configData ) {
m_configData = _configData; m_configData = configData;
m_config.reset(); m_config.reset();
} }
int run( int argc, char const* const* const argv ) { int run( int argc, char* argv[] ) {
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
if ( !exceptions.empty() ) {
Catch::cerr() << "Errors occured during startup!" << '\n';
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
std::rethrow_exception(ex_ptr);
} catch ( std::exception const& ex ) {
Catch::cerr() << ex.what() << '\n';
}
}
return 1;
}
int returnCode = applyCommandLine( argc, argv ); int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 ) if( returnCode == 0 )
returnCode = run(); returnCode = run();
@@ -180,7 +176,7 @@ namespace Catch {
} }
#if defined(WIN32) && defined(UNICODE) #if defined(WIN32) && defined(UNICODE)
int run( int argc, wchar_t const* const* const argv ) { int run( int argc, wchar_t* const argv[] ) {
char **utf8Argv = new char *[ argc ]; char **utf8Argv = new char *[ argc ];
@@ -192,9 +188,7 @@ namespace Catch {
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
} }
int returnCode = applyCommandLine( argc, utf8Argv ); int returnCode = run( argc, utf8Argv );
if( returnCode == 0 )
returnCode = run();
for ( int i = 0; i < argc; ++i ) for ( int i = 0; i < argc; ++i )
delete [] utf8Argv[ i ]; delete [] utf8Argv[ i ];
@@ -204,36 +198,34 @@ namespace Catch {
return returnCode; return returnCode;
} }
#endif #endif
int run() { int run() {
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before starting" << std::endl; Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
static_cast<void>(std::getchar()); std::getchar();
} }
int exitCode = runInternal(); int exitCode = runInternal();
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
static_cast<void>(std::getchar()); std::getchar();
} }
return exitCode; return exitCode;
} }
Clara::CommandLine<ConfigData> const& cli() const { clara::Parser const& cli() const {
return m_cli; return m_cli;
} }
std::vector<Clara::Parser::Token> const& unusedTokens() const { void cli( clara::Parser const& newParser ) {
return m_unusedTokens; m_cli = newParser;
} }
ConfigData& configData() { ConfigData& configData() {
return m_configData; return m_configData;
} }
Config& config() { Config& config() {
if( !m_config ) if( !m_config )
m_config = new Config( m_configData ); m_config = std::make_shared<Config>( m_configData );
return *m_config; return *m_config;
} }
private: private:
int runInternal() { int runInternal() {
if( m_configData.showHelp || m_configData.libIdentify ) if( m_configData.showHelp || m_configData.libIdentify )
return 0; return 0;
@@ -251,21 +243,20 @@ namespace Catch {
if( Option<std::size_t> listed = list( config() ) ) if( Option<std::size_t> listed = list( config() ) )
return static_cast<int>( *listed ); return static_cast<int>( *listed );
return static_cast<int>( runTests( m_config ).assertions.failed ); return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
} }
catch( std::exception& ex ) { catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl; Catch::cerr() << ex.what() << std::endl;
return (std::numeric_limits<int>::max)(); return MaxExitCode;
} }
} }
Clara::CommandLine<ConfigData> m_cli; clara::Parser m_cli;
std::vector<Clara::Parser::Token> m_unusedTokens;
ConfigData m_configData; ConfigData m_configData;
Ptr<Config> m_config; std::shared_ptr<Config> m_config;
}; };
bool Session::alreadyInstantiated = false; const int Session::MaxExitCode = 255;
} // end namespace Catch } // end namespace Catch

1054
include/external/clara.h vendored

File diff suppressed because it is too large Load Diff

1230
include/external/clara.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,168 +0,0 @@
/*
* Created by Phil on 18/4/2013.
* Copyright 2013 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)
*/
// Only use header guard if we are not using an outer namespace
#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
# endif
# else
# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
# endif
#endif
#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
#include <string>
#include <vector>
#include <sstream>
// Use optional outer namespace
#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
#endif
namespace Tbc {
#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
#else
const unsigned int consoleWidth = 80;
#endif
struct TextAttributes {
TextAttributes()
: initialIndent( std::string::npos ),
indent( 0 ),
width( consoleWidth-1 )
{}
TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
std::size_t initialIndent; // indent of first line, or npos
std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
std::size_t width; // maximum width of text, including indent. Longer text will wrap
};
class Text {
public:
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
: attr( _attr )
{
const std::string wrappableBeforeChars = "[({<\t";
const std::string wrappableAfterChars = "])}>-,./|\\";
const std::string wrappableInsteadOfChars = " \n\r";
std::string indent = _attr.initialIndent != std::string::npos
? std::string( _attr.initialIndent, ' ' )
: std::string( _attr.indent, ' ' );
typedef std::string::const_iterator iterator;
iterator it = _str.begin();
const iterator strEnd = _str.end();
while( it != strEnd ) {
if( lines.size() >= 1000 ) {
lines.push_back( "... message truncated due to excessive size" );
return;
}
std::string suffix;
std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
iterator itEnd = it+width;
iterator itNext = _str.end();
iterator itNewLine = std::find( it, itEnd, '\n' );
if( itNewLine != itEnd )
itEnd = itNewLine;
if( itEnd != strEnd ) {
bool foundWrapPoint = false;
iterator findIt = itEnd;
do {
if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
itEnd = findIt+1;
itNext = findIt+1;
foundWrapPoint = true;
}
else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
itEnd = findIt;
itNext = findIt;
foundWrapPoint = true;
}
else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
itNext = findIt+1;
itEnd = findIt;
foundWrapPoint = true;
}
if( findIt == it )
break;
else
--findIt;
}
while( !foundWrapPoint );
if( !foundWrapPoint ) {
// No good wrap char, so we'll break mid word and add a hyphen
--itEnd;
itNext = itEnd;
suffix = "-";
}
else {
while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
--itEnd;
}
}
lines.push_back( indent + std::string( it, itEnd ) + suffix );
if( indent.size() != _attr.indent )
indent = std::string( _attr.indent, ' ' );
it = itNext;
}
}
typedef std::vector<std::string>::const_iterator const_iterator;
const_iterator begin() const { return lines.begin(); }
const_iterator end() const { return lines.end(); }
std::string const& last() const { return lines.back(); }
std::size_t size() const { return lines.size(); }
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
std::string toString() const {
std::ostringstream oss;
oss << *this;
return oss.str();
}
inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
it != itEnd; ++it ) {
if( it != _text.begin() )
_stream << "\n";
_stream << *it;
}
return _stream;
}
private:
std::string str;
TextAttributes attr;
std::vector<std::string> lines;
};
} // end namespace Tbc
#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
} // end outer namespace
#endif
#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED

View File

@@ -0,0 +1,46 @@
/*
* Created by Martin on 19/07/2017.
* Copyright 2017 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)
*/
#include "catch_approx.hpp"
#include <limits>
namespace Catch {
namespace Detail {
double max(double lhs, double rhs) {
if (lhs < rhs) {
return rhs;
}
return lhs;
}
Approx::Approx ( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_margin( 0.0 ),
m_scale( 1.0 ),
m_value( value )
{}
Approx Approx::custom() {
return Approx( 0 );
}
std::string Approx::toString() const {
std::ostringstream oss;
oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
return oss.str();
}
} // end namespace Detail
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
return value.toString();
}
} // end namespace Catch

View File

@@ -11,32 +11,22 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include <cmath> #include <cmath>
#include <limits>
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
#include <type_traits> #include <type_traits>
#endif
namespace Catch { namespace Catch {
namespace Detail { namespace Detail {
double max(double lhs, double rhs);
class Approx { class Approx {
public: public:
explicit Approx ( double value ) explicit Approx ( double value );
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_margin( 0.0 ),
m_scale( 1.0 ),
m_value( value )
{}
static Approx custom() { static Approx custom();
return Approx( 0 );
}
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx operator()( T value ) { Approx operator()( T const& value ) {
Approx approx( static_cast<double>(value) ); Approx approx( static_cast<double>(value) );
approx.epsilon( m_epsilon ); approx.epsilon( m_epsilon );
approx.margin( m_margin ); approx.margin( m_margin );
@@ -45,20 +35,19 @@ namespace Detail {
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
explicit Approx( T value ): Approx(static_cast<double>(value)) explicit Approx( T const& value ): Approx(static_cast<double>(value))
{} {}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator == ( const T& lhs, Approx const& rhs ) { friend bool operator == ( const T& lhs, Approx const& rhs ) {
// Thanks to Richard Harris for his help refining this formula // Thanks to Richard Harris for his help refining this formula
auto lhs_v = double(lhs); auto lhs_v = static_cast<double>(lhs);
bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
if (relativeOK) { if (relativeOK) {
return true; return true;
} }
return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
@@ -67,122 +56,54 @@ namespace Detail {
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator != ( T lhs, Approx const& rhs ) { friend bool operator != ( T const& lhs, Approx const& rhs ) {
return !operator==( lhs, rhs ); return !operator==( lhs, rhs );
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator != ( Approx const& lhs, T rhs ) { friend bool operator != ( Approx const& lhs, T const& rhs ) {
return !operator==( rhs, lhs ); return !operator==( rhs, lhs );
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator <= ( T lhs, Approx const& rhs ) { friend bool operator <= ( T const& lhs, Approx const& rhs ) {
return double(lhs) < rhs.m_value || lhs == rhs; return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator <= ( Approx const& lhs, T rhs ) { friend bool operator <= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value < double(rhs) || lhs == rhs; return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator >= ( T lhs, Approx const& rhs ) { friend bool operator >= ( T const& lhs, Approx const& rhs ) {
return double(lhs) > rhs.m_value || lhs == rhs; return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator >= ( Approx const& lhs, T rhs ) { friend bool operator >= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value > double(rhs) || lhs == rhs; return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& epsilon( T newEpsilon ) { Approx& epsilon( T const& newEpsilon ) {
m_epsilon = double(newEpsilon); m_epsilon = static_cast<double>(newEpsilon);
return *this; return *this;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& margin( T newMargin ) { Approx& margin( T const& newMargin ) {
m_margin = double(newMargin); m_margin = static_cast<double>(newMargin);
return *this; return *this;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& scale( T newScale ) { Approx& scale( T const& newScale ) {
m_scale = double(newScale); m_scale = static_cast<double>(newScale);
return *this; return *this;
} }
#else std::string toString() const;
Approx operator()( double value ) {
Approx approx( value );
approx.epsilon( m_epsilon );
approx.margin( m_margin );
approx.scale( m_scale );
return approx;
}
friend bool operator == ( double lhs, Approx const& rhs ) {
// Thanks to Richard Harris for his help refining this formula
bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
if (relativeOK) {
return true;
}
return std::fabs(lhs - rhs.m_value) <= rhs.m_margin;
}
friend bool operator == ( Approx const& lhs, double rhs ) {
return operator==( rhs, lhs );
}
friend bool operator != ( double lhs, Approx const& rhs ) {
return !operator==( lhs, rhs );
}
friend bool operator != ( Approx const& lhs, double rhs ) {
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;
}
Approx& margin( double newMargin ) {
m_margin = newMargin;
return *this;
}
Approx& scale( double newScale ) {
m_scale = newScale;
return *this;
}
#endif
std::string toString() const {
std::ostringstream oss;
oss << "Approx( " << Catch::toString( m_value ) << " )";
return oss.str();
}
private: private:
double m_epsilon; double m_epsilon;
@@ -193,9 +114,9 @@ namespace Detail {
} }
template<> template<>
inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { struct StringMaker<Catch::Detail::Approx> {
return value.toString(); static std::string convert(Catch::Detail::Approx const& value);
} };
} // end namespace Catch } // end namespace Catch

View File

@@ -0,0 +1,147 @@
/*
* Created by Phil on 8/8/2017.
* Copyright 2017 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)
*/
#include "catch_assertionhandler.h"
#include "catch_assertionresult.h"
#include "catch_interfaces_capture.h"
#include "catch_interfaces_runner.h"
#include "catch_interfaces_config.h"
#include "catch_context.h"
#include "catch_debugger.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_capture_matchers.h"
#include <cassert>
namespace Catch {
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
expr.streamReconstructedExpression( os );
return os;
}
LazyExpression::LazyExpression( bool isNegated )
: m_isNegated( isNegated )
{}
LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}
LazyExpression::operator bool() const {
return m_transientExpression != nullptr;
}
auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {
if( lazyExpr.m_isNegated )
os << "!";
if( lazyExpr ) {
if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
os << "(" << *lazyExpr.m_transientExpression << ")";
else
os << *lazyExpr.m_transientExpression;
}
else {
os << "{** error - unchecked empty expression requested **}";
}
return os;
}
AssertionHandler::AssertionHandler
( StringRef macroName,
SourceLineInfo const& lineInfo,
StringRef capturedExpression,
ResultDisposition::Flags resultDisposition )
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }
{
getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo );
}
AssertionHandler::~AssertionHandler() {
if ( m_inExceptionGuard ) {
handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" );
getCurrentContext().getResultCapture()->exceptionEarlyReported();
}
}
void AssertionHandler::handle( ITransientExpression const& expr ) {
bool negated = isFalseTest( m_assertionInfo.resultDisposition );
bool result = expr.getResult() != negated;
handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated );
}
void AssertionHandler::handle( ResultWas::OfType resultType ) {
handle( resultType, nullptr, false );
}
void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) {
AssertionResultData data( resultType, LazyExpression( false ) );
data.message = message;
handle( data, nullptr );
}
void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) {
AssertionResultData data( resultType, LazyExpression( negated ) );
handle( data, expr );
}
void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) {
getResultCapture().assertionRun();
AssertionResult assertionResult{ m_assertionInfo, resultData };
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
getResultCapture().assertionEnded( assertionResult );
if( !assertionResult.isOk() ) {
m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak();
m_shouldThrow =
getCurrentContext().getRunner()->aborting() ||
(m_assertionInfo.resultDisposition & ResultDisposition::Normal);
}
}
auto AssertionHandler::allowThrows() const -> bool {
return getCurrentContext().getConfig()->allowThrows();
}
auto AssertionHandler::shouldDebugBreak() const -> bool {
return m_shouldDebugBreak;
}
void AssertionHandler::reactWithDebugBreak() const {
if (m_shouldDebugBreak) {
///////////////////////////////////////////////////////////////////
// To inspect the state during test, you need to go one level up the callstack
// To go back to the test and change execution, jump over the reactWithoutDebugBreak() call
///////////////////////////////////////////////////////////////////
CATCH_BREAK_INTO_DEBUGGER();
}
reactWithoutDebugBreak();
}
void AssertionHandler::reactWithoutDebugBreak() const {
if( m_shouldThrow )
throw Catch::TestFailureException();
}
void AssertionHandler::useActiveException() {
handle( ResultWas::ThrewException, Catch::translateActiveException() );
}
void AssertionHandler::setExceptionGuard() {
assert( m_inExceptionGuard == false );
m_inExceptionGuard = true;
}
void AssertionHandler::unsetExceptionGuard() {
assert( m_inExceptionGuard == true );
m_inExceptionGuard = false;
}
// This is the overload that takes a string and infers the Equals matcher from it
// The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) {
handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
}
} // namespace Catch

View File

@@ -0,0 +1,73 @@
/*
* Created by Phil on 8/8/2017.
* Copyright 2017 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_ASSERTIONHANDLER_H_INCLUDED
#define TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED
#include "catch_decomposer.h"
#include "catch_assertioninfo.h"
namespace Catch {
struct TestFailureException{};
struct AssertionResultData;
class LazyExpression {
friend class AssertionHandler;
friend struct AssertionStats;
ITransientExpression const* m_transientExpression = nullptr;
bool m_isNegated;
public:
LazyExpression( bool isNegated );
LazyExpression( LazyExpression const& other );
LazyExpression& operator = ( LazyExpression const& ) = delete;
explicit operator bool() const;
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
};
class AssertionHandler {
AssertionInfo m_assertionInfo;
bool m_shouldDebugBreak = false;
bool m_shouldThrow = false;
bool m_inExceptionGuard = false;
public:
AssertionHandler
( StringRef macroName,
SourceLineInfo const& lineInfo,
StringRef capturedExpression,
ResultDisposition::Flags resultDisposition );
~AssertionHandler();
void handle( ITransientExpression const& expr );
template<typename T>
void handle( ExprLhs<T> const& expr ) {
handle( expr.makeUnaryExpr() );
}
void handle( ResultWas::OfType resultType );
void handle( ResultWas::OfType resultType, StringRef const& message );
void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated );
void handle( AssertionResultData const& resultData, ITransientExpression const* expr );
auto shouldDebugBreak() const -> bool;
auto allowThrows() const -> bool;
void reactWithDebugBreak() const;
void reactWithoutDebugBreak() const;
void useActiveException();
void setExceptionGuard();
void unsetExceptionGuard();
};
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED

View File

@@ -0,0 +1,31 @@
/*
* Created by Phil on 8/8/2017.
* Copyright 2017 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_ASSERTIONINFO_H_INCLUDED
#define TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED
#include "catch_result_type.h"
#include "catch_common.h"
#include "catch_stringref.h"
namespace Catch {
struct AssertionInfo
{
StringRef macroName;
SourceLineInfo lineInfo;
StringRef capturedExpression;
ResultDisposition::Flags resultDisposition;
// We want to delete this constructor but a compiler bug in 4.8 means
// the struct is then treated as non-aggregate
//AssertionInfo() = delete;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED

View File

@@ -0,0 +1,96 @@
/*
* Created by Phil on 8/8/12
* Copyright 2012 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)
*/
#include "catch_assertionresult.h"
namespace Catch {
std::string AssertionResultData::reconstructExpression() const {
if( reconstructedExpression.empty() ) {
if( lazyExpression ) {
// !TBD Use stringstream for now, but rework above to pass stream in
std::ostringstream oss;
oss << lazyExpression;
reconstructedExpression = oss.str();
}
}
return reconstructedExpression;
}
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
: m_info( info ),
m_resultData( data )
{}
// Result was a success
bool AssertionResult::succeeded() const {
return Catch::isOk( m_resultData.resultType );
}
// Result was a success, or failure is suppressed
bool AssertionResult::isOk() const {
return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
}
ResultWas::OfType AssertionResult::getResultType() const {
return m_resultData.resultType;
}
bool AssertionResult::hasExpression() const {
return m_info.capturedExpression[0] != 0;
}
bool AssertionResult::hasMessage() const {
return !m_resultData.message.empty();
}
std::string AssertionResult::getExpression() const {
if (isFalseTest(m_info.resultDisposition))
return '!' + std::string(m_info.capturedExpression);
else
return m_info.capturedExpression;
}
std::string AssertionResult::getExpressionInMacro() const {
std::string expr;
if( m_info.macroName[0] == 0 )
expr = m_info.capturedExpression;
else {
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
expr += m_info.macroName;
expr += "( ";
expr += m_info.capturedExpression;
expr += " )";
}
return expr;
}
bool AssertionResult::hasExpandedExpression() const {
return hasExpression() && getExpandedExpression() != getExpression();
}
std::string AssertionResult::getExpandedExpression() const {
std::string expr = m_resultData.reconstructExpression();
return expr.empty()
? getExpression()
: expr;
}
std::string AssertionResult::getMessage() const {
return m_resultData.message;
}
SourceLineInfo AssertionResult::getSourceInfo() const {
return m_info.lineInfo;
}
std::string AssertionResult::getTestMacroName() const {
return m_info.macroName;
}
} // end namespace Catch

View File

@@ -9,100 +9,36 @@
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
#include <string> #include <string>
#include "catch_assertioninfo.h"
#include "catch_result_type.h" #include "catch_result_type.h"
#include "catch_common.h"
#include "catch_stringref.h"
#include "catch_assertionhandler.h"
namespace Catch { namespace Catch {
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
struct DecomposedExpression
{
virtual ~DecomposedExpression() {}
virtual bool isBinaryExpression() const {
return false;
}
virtual void reconstructExpression( std::string& dest ) const = 0;
// Only simple binary comparisons can be decomposed.
// If more complex check is required then wrap sub-expressions in parentheses.
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
private:
DecomposedExpression& operator = (DecomposedExpression const&);
};
struct AssertionInfo
{
AssertionInfo();
AssertionInfo( char const * _macroName,
SourceLineInfo const& _lineInfo,
char const * _capturedExpression,
ResultDisposition::Flags _resultDisposition,
char const * _secondArg = "");
char const * macroName;
SourceLineInfo lineInfo;
char const * capturedExpression;
ResultDisposition::Flags resultDisposition;
char const * secondArg;
};
struct AssertionResultData struct AssertionResultData
{ {
AssertionResultData() : decomposedExpression( CATCH_NULL ) AssertionResultData() = delete;
, resultType( ResultWas::Unknown )
, negated( false )
, parenthesized( false ) {}
void negate( bool parenthesize ) { AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression )
negated = !negated; : resultType( _resultType ),
parenthesized = parenthesize; lazyExpression( _lazyExpression )
if( resultType == ResultWas::Ok ) {}
resultType = ResultWas::ExpressionFailed;
else if( resultType == ResultWas::ExpressionFailed )
resultType = ResultWas::Ok;
}
std::string const& reconstructExpression() const { ResultWas::OfType resultType = ResultWas::Unknown;
if( decomposedExpression != CATCH_NULL ) {
decomposedExpression->reconstructExpression( reconstructedExpression );
if( parenthesized ) {
reconstructedExpression.insert( 0, 1, '(' );
reconstructedExpression.append( 1, ')' );
}
if( negated ) {
reconstructedExpression.insert( 0, 1, '!' );
}
decomposedExpression = CATCH_NULL;
}
return reconstructedExpression;
}
mutable DecomposedExpression const* decomposedExpression;
mutable std::string reconstructedExpression;
std::string message; std::string message;
ResultWas::OfType resultType;
bool negated; LazyExpression lazyExpression;
bool parenthesized;
std::string reconstructExpression() const;
mutable std::string reconstructedExpression;
}; };
class AssertionResult { class AssertionResult {
public: public:
AssertionResult(); AssertionResult() = delete;
AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
~AssertionResult();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionResult( AssertionResult const& ) = default;
AssertionResult( AssertionResult && ) = default;
AssertionResult& operator = ( AssertionResult const& ) = default;
AssertionResult& operator = ( AssertionResult && ) = default;
# endif
bool isOk() const; bool isOk() const;
bool succeeded() const; bool succeeded() const;
@@ -116,10 +52,8 @@ namespace Catch {
std::string getMessage() const; std::string getMessage() const;
SourceLineInfo getSourceInfo() const; SourceLineInfo getSourceInfo() const;
std::string getTestMacroName() const; std::string getTestMacroName() const;
void discardDecomposedExpression() const;
void expandDecomposedExpression() const;
protected: //protected:
AssertionInfo m_info; AssertionInfo m_info;
AssertionResultData m_resultData; AssertionResultData m_resultData;
}; };

View File

@@ -1,109 +0,0 @@
/*
* Created by Phil on 8/8/12
* Copyright 2012 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_ASSERTIONRESULT_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
#include "catch_assertionresult.h"
namespace Catch {
AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){}
AssertionInfo::AssertionInfo( char const * _macroName,
SourceLineInfo const& _lineInfo,
char const * _capturedExpression,
ResultDisposition::Flags _resultDisposition,
char const * _secondArg)
: macroName( _macroName ),
lineInfo( _lineInfo ),
capturedExpression( _capturedExpression ),
resultDisposition( _resultDisposition ),
secondArg( _secondArg )
{}
AssertionResult::AssertionResult() {}
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
: m_info( info ),
m_resultData( data )
{}
AssertionResult::~AssertionResult() {}
// Result was a success
bool AssertionResult::succeeded() const {
return Catch::isOk( m_resultData.resultType );
}
// Result was a success, or failure is suppressed
bool AssertionResult::isOk() const {
return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
}
ResultWas::OfType AssertionResult::getResultType() const {
return m_resultData.resultType;
}
bool AssertionResult::hasExpression() const {
return m_info.capturedExpression[0] != 0;
}
bool AssertionResult::hasMessage() const {
return !m_resultData.message.empty();
}
std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) {
return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"')
? capturedExpression
: std::string(capturedExpression) + ", " + secondArg;
}
std::string AssertionResult::getExpression() const {
if( isFalseTest( m_info.resultDisposition ) )
return "!(" + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + ")";
else
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
}
std::string AssertionResult::getExpressionInMacro() const {
if( m_info.macroName[0] == 0 )
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
else
return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )";
}
bool AssertionResult::hasExpandedExpression() const {
return hasExpression() && getExpandedExpression() != getExpression();
}
std::string AssertionResult::getExpandedExpression() const {
return m_resultData.reconstructExpression();
}
std::string AssertionResult::getMessage() const {
return m_resultData.message;
}
SourceLineInfo AssertionResult::getSourceInfo() const {
return m_info.lineInfo;
}
std::string AssertionResult::getTestMacroName() const {
return m_info.macroName;
}
void AssertionResult::discardDecomposedExpression() const {
m_resultData.decomposedExpression = CATCH_NULL;
}
void AssertionResult::expandDecomposedExpression() const {
m_resultData.reconstructExpression();
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED

View File

@@ -0,0 +1,35 @@
/*
* Created by Phil on 04/07/2017.
* Copyright 2017 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)
*/
#include "catch_benchmark.h"
#include "catch_capture.hpp"
#include "catch_interfaces_reporter.h"
namespace Catch {
auto BenchmarkLooper::getResolution() -> uint64_t {
return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();
}
void BenchmarkLooper::reportStart() {
getResultCapture().benchmarkStarting( { m_name } );
}
auto BenchmarkLooper::needsMoreIterations() -> bool {
auto elapsed = m_timer.getElapsedNanoseconds();
// Exponentially increasing iterations until we're confident in our timer resolution
if( elapsed < m_resolution ) {
m_iterationsToRun *= 10;
return true;
}
getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );
return false;
}
} // end namespace Catch

View File

@@ -0,0 +1,57 @@
/*
* Created by Phil on 04/07/2017.
* Copyright 2017 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_BENCHMARK_H_INCLUDED
#define TWOBLUECUBES_CATCH_BENCHMARK_H_INCLUDED
#include "catch_stringref.h"
#include "catch_timer.h"
#include <cstdint>
#include <string>
namespace Catch {
class BenchmarkLooper {
std::string m_name;
size_t m_count = 0;
size_t m_iterationsToRun = 1;
uint64_t m_resolution;
Timer m_timer;
static auto getResolution() -> uint64_t;
public:
// Keep most of this inline as it's on the code path that is being timed
BenchmarkLooper( StringRef name )
: m_name( name ),
m_resolution( getResolution() )
{
reportStart();
m_timer.start();
}
explicit operator bool() {
if( m_count < m_iterationsToRun )
return true;
return needsMoreIterations();
}
void increment() {
++m_count;
}
void reportStart();
auto needsMoreIterations() -> bool;
};
} // end namespace Catch
#define BENCHMARK( name ) \
for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
#endif // TWOBLUECUBES_CATCH_BENCHMARK_H_INCLUDED

View File

@@ -8,179 +8,149 @@
#ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
#include "catch_result_builder.h" #include "catch_assertionhandler.h"
#include "catch_message.h" #include "catch_message.h"
#include "catch_interfaces_capture.h" #include "catch_interfaces_capture.h"
#include "catch_debugger.h"
#include "catch_common.h"
#include "catch_tostring.h"
#include "catch_interfaces_runner.h"
#include "catch_compiler_capabilities.h"
#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
# define CATCH_INTERNAL_STRINGIFY(expr) #expr
#else
# define CATCH_INTERNAL_STRINGIFY(expr) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
#endif
#if defined(CATCH_CONFIG_FAST_COMPILE) #if defined(CATCH_CONFIG_FAST_COMPILE)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// We can speedup compilation significantly by breaking into debugger lower in // We can speedup compilation significantly by breaking into debugger lower in
// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
// macro in each assertion // macro in each assertion
#define INTERNAL_CATCH_REACT( resultBuilder ) \ #define INTERNAL_CATCH_REACT( handler ) \
resultBuilder.react(); handler.reactWithDebugBreak();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Another way to speed-up compilation is to omit local try-catch for REQUIRE* // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
// macros. // macros.
// This can potentially cause false negative, if the test code catches // This can potentially cause false negative, if the test code catches
// the exception before it propagates back up to the runner. // the exception before it propagates back up to the runner.
#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ #define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard();
do { \ #define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard();
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
__catchResult.setExceptionGuard(); \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
__catchResult.unsetExceptionGuard(); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ #else // CATCH_CONFIG_FAST_COMPILE
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ #include "catch_debugger.h"
__catchResult.setExceptionGuard(); \
__catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
__catchResult.unsetExceptionGuard(); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
#else
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// In the event of a failure works out if the debugger needs to be invoked // In the event of a failure works out if the debugger needs to be invoked
// and/or an exception thrown and takes appropriate action. // and/or an exception thrown and takes appropriate action.
// This needs to be done as a macro so the debugger will stop in the user // This needs to be done as a macro so the debugger will stop in the user
// source code rather than in Catch library code // source code rather than in Catch library code
#define INTERNAL_CATCH_REACT( resultBuilder ) \ #define INTERNAL_CATCH_REACT( handler ) \
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
resultBuilder.react(); handler.reactWithoutDebugBreak();
#define INTERNAL_CATCH_TRY( capturer ) try
#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); }
#endif #endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \
try { \ INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \ catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
catch( ... ) { \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
__catchResult.useActiveException( resultDisposition ); \ } while( Catch::isTrue( false && static_cast<bool>( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
} \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
if( Catch::getResultCapture().lastAssertionPassed() ) if( Catch::getResultCapture().lastAssertionPassed() )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
if( !Catch::getResultCapture().lastAssertionPassed() ) if( !Catch::getResultCapture().lastAssertionPassed() )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \
try { \ try { \
static_cast<void>(expr); \ static_cast<void>(__VA_ARGS__); \
__catchResult.captureResult( Catch::ResultWas::Ok ); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
} \ } \
catch( ... ) { \ catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \ catchAssertionHandler.useActiveException(); \
} \ } \
INTERNAL_CATCH_REACT( __catchResult ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( Catch::alwaysFalse() )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition, CATCH_INTERNAL_STRINGIFY(matcher) ); \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \
if( __catchResult.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
static_cast<void>(expr); \ static_cast<void>(__VA_ARGS__); \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \ } \
catch( ... ) { \ catch( ... ) { \
__catchResult.captureExpectedException( matcher ); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
} \ } \
else \ else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( __catchResult ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( Catch::alwaysFalse() )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
if( __catchResult.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
static_cast<void>(expr); \ static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \ } \
catch( exceptionType ) { \ catch( exceptionType const& ) { \
__catchResult.captureResult( Catch::ResultWas::Ok ); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
} \ } \
catch( ... ) { \ catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \ catchAssertionHandler.useActiveException(); \
} \ } \
else \ else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( __catchResult ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( Catch::alwaysFalse() )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
__catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
__catchResult.captureResult( messageType ); \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() ) } while( Catch::alwaysFalse() )
#else
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
__catchResult << log + ::Catch::StreamEndStop(); \
__catchResult.captureResult( messageType ); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_INFO( macroName, log ) \ #define INTERNAL_CATCH_INFO( macroName, log ) \
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ // Although this is matcher-based, it can be used with just a string
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
__catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \ static_cast<void>(__VA_ARGS__); \
} catch( ... ) { \ catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
} \ } \
INTERNAL_CATCH_REACT( __catchResult ) \ catch( ... ) { \
handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( Catch::alwaysFalse() )
#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED

View File

@@ -0,0 +1,24 @@
/*
* Created by Phil on 9/8/2017.
* Copyright 2017 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)
*/
#include "catch_capture_matchers.h"
#include "catch_interfaces_registry_hub.h"
namespace Catch {
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
// This is the general overload that takes a any string matcher
// There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers
// the Equals matcher (so the header does not mention matchers)
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
std::string exceptionMessage = Catch::translateActiveException();
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
handler.handle( expr );
}
} // namespace Catch

View File

@@ -0,0 +1,88 @@
/*
* Created by Phil on 9/8/2017
* Copyright 2017 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_CAPTURE_MATCHERS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
#include "catch_capture.hpp"
#include "catch_matchers.hpp"
#include "catch_matchers_string.h"
#include "catch_matchers_vector.h"
namespace Catch {
template<typename ArgT, typename MatcherT>
class MatchExpr : public ITransientExpression {
ArgT const& m_arg;
MatcherT m_matcher;
StringRef m_matcherString;
bool m_result;
public:
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
: m_arg( arg ),
m_matcher( matcher ),
m_matcherString( matcherString ),
m_result( matcher.match( arg ) )
{}
auto isBinaryExpression() const -> bool override { return true; }
auto getResult() const -> bool override { return m_result; }
void streamReconstructedExpression( std::ostream &os ) const override {
auto matcherAsString = m_matcher.toString();
os << Catch::Detail::stringify( m_arg ) << ' ';
if( matcherAsString == Detail::unprintableString )
os << m_matcherString;
else
os << matcherAsString;
}
};
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString );
template<typename ArgT, typename MatcherT>
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> {
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
}
} // namespace Catch
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \
try { \
static_cast<void>(__VA_ARGS__ ); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \
catch( exceptionType const& ex ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
} \
catch( ... ) { \
catchAssertionHandler.useActiveException(); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
#endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED

View File

@@ -11,21 +11,18 @@
// Use Catch's value for console width (store Clara's off to the side, if present) // Use Catch's value for console width (store Clara's off to the side, if present)
#ifdef CLARA_CONFIG_CONSOLE_WIDTH #ifdef CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#undef CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#endif #endif
#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
// Declare Clara inside the Catch namespace #include "../external/clara.hpp"
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
#include "../external/clara.h"
#undef STITCH_CLARA_OPEN_NAMESPACE
// Restore Clara's value for console width, if present // Restore Clara's value for console width, if present
#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#endif #endif

View File

@@ -0,0 +1,184 @@
/*
* Created by Phil on 02/11/2010.
* Copyright 2010 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)
*/
#include "catch_commandline.hpp"
#include "catch_string_manip.h"
#include <fstream>
#include <ctime>
namespace Catch {
clara::Parser makeCommandLineParser( ConfigData& config ) {
using namespace clara;
auto const setWarning = [&]( std::string const& warning ) {
if( warning != "NoAssertions" )
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
return ParserResult::ok( ParseResultType::Matched );
};
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
std::ifstream f( filename.c_str() );
if( !f.is_open() )
return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" );
std::string line;
while( std::getline( f, line ) ) {
line = trim(line);
if( !line.empty() && !startsWith( line, '#' ) ) {
if( !startsWith( line, '"' ) )
line = '"' + line + '"';
config.testsOrTags.push_back( line + ',' );
}
}
return ParserResult::ok( ParseResultType::Matched );
};
auto const setTestOrder = [&]( std::string const& order ) {
if( startsWith( "declared", order ) )
config.runOrder = RunTests::InDeclarationOrder;
else if( startsWith( "lexical", order ) )
config.runOrder = RunTests::InLexicographicalOrder;
else if( startsWith( "random", order ) )
config.runOrder = RunTests::InRandomOrder;
else
return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setRngSeed = [&]( std::string const& seed ) {
if( seed != "time" )
return clara::detail::convertInto( seed, config.rngSeed );
config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setColourUsage = [&]( std::string const& useColour ) {
auto mode = toLower( useColour );
if( mode == "yes" )
config.useColour = UseColour::Yes;
else if( mode == "no" )
config.useColour = UseColour::No;
else if( mode == "auto" )
config.useColour = UseColour::Auto;
else
return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setWaitForKeypress = [&]( std::string const& keypress ) {
auto keypressLc = toLower( keypress );
if( keypressLc == "start" )
config.waitForKeypress = WaitForKeypress::BeforeStart;
else if( keypressLc == "exit" )
config.waitForKeypress = WaitForKeypress::BeforeExit;
else if( keypressLc == "both" )
config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
else
return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setVerbosity = [&]( std::string const& verbosity ) {
auto lcVerbosity = toLower( verbosity );
if( lcVerbosity == "quiet" )
config.verbosity = Verbosity::Quiet;
else if( lcVerbosity == "normal" )
config.verbosity = Verbosity::Normal;
else if( lcVerbosity == "high" )
config.verbosity = Verbosity::High;
else
return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
return ParserResult::ok( ParseResultType::Matched );
};
auto cli
= ExeName( config.processName )
+ Help( config.showHelp )
+ Opt( config.listTests )
["-l"]["--list-tests"]
( "list all/matching test cases" )
+ Opt( config.listTags )
["-t"]["--list-tags"]
( "list all/matching tags" )
+ Opt( config.showSuccessfulTests )
["-s"]["--success"]
( "include successful tests in output" )
+ Opt( config.shouldDebugBreak )
["-b"]["--break"]
( "break into debugger on failure" )
+ Opt( config.noThrow )
["-e"]["--nothrow"]
( "skip exception tests" )
+ Opt( config.showInvisibles )
["-i"]["--invisibles"]
( "show invisibles (tabs, newlines)" )
+ Opt( config.outputFilename, "filename" )
["-o"]["--out"]
( "output filename" )
+ Opt( config.reporterNames, "name" )
["-r"]["--reporter"]
( "reporter to use (defaults to console)" )
+ Opt( config.name, "name" )
["-n"]["--name"]
( "suite name" )
+ Opt( [&]( bool ){ config.abortAfter = 1; } )
["-a"]["--abort"]
( "abort at first failure" )
+ Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
["-x"]["--abortx"]
( "abort after x failures" )
+ Opt( setWarning, "warning name" )
["-w"]["--warn"]
( "enable warnings" )
+ Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
["-d"]["--durations"]
( "show test durations" )
+ Opt( loadTestNamesFromFile, "filename" )
["-f"]["--input-file"]
( "load test names to run from a file" )
+ Opt( config.filenamesAsTags )
["-#"]["--filenames-as-tags"]
( "adds a tag for the filename" )
+ Opt( config.sectionsToRun, "section name" )
["-c"]["--section"]
( "specify section to run" )
+ Opt( setVerbosity, "quiet|normal|high" )
["-v"]["--verbosity"]
( "set output verbosity" )
+ Opt( config.listTestNamesOnly )
["--list-test-names-only"]
( "list all/matching test cases names only" )
+ Opt( config.listReporters )
["--list-reporters"]
( "list all reporters" )
+ Opt( setTestOrder, "decl|lex|rand" )
["--order"]
( "test case order (defaults to decl)" )
+ Opt( setRngSeed, "'time'|number" )
["--rng-seed"]
( "set a specific seed for random numbers" )
+ Opt( setColourUsage, "yes|no" )
["--use-colour"]
( "should output be colourised" )
+ Opt( config.libIdentify )
["--libidentify"]
( "report name and version according to libidentify standard" )
+ Opt( setWaitForKeypress, "start|exit|both" )
["--wait-for-keypress"]
( "waits for a keypress before exiting" )
+ Opt( config.benchmarkResolutionMultiple, "multiplier" )
["--benchmark-resolution-multiple"]
( "multiple of clock resolution to run benchmarks" )
+ Arg( config.testsOrTags, "test name|pattern|tags" )
( "which test or tests to use" );
return cli;
}
} // end namespace Catch

View File

@@ -9,231 +9,11 @@
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
#include "catch_config.hpp" #include "catch_config.hpp"
#include "catch_common.h"
#include "catch_clara.h" #include "catch_clara.h"
#include <fstream>
#include <ctime>
namespace Catch { namespace Catch {
inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } clara::Parser makeCommandLineParser( ConfigData& config );
inline void abortAfterX( ConfigData& config, int x ) {
if( x < 1 )
throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
config.abortAfter = x;
}
inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
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" )
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
else
throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
}
inline void setOrder( ConfigData& config, std::string const& order ) {
if( startsWith( "declared", order ) )
config.runOrder = RunTests::InDeclarationOrder;
else if( startsWith( "lexical", order ) )
config.runOrder = RunTests::InLexicographicalOrder;
else if( startsWith( "random", order ) )
config.runOrder = RunTests::InRandomOrder;
else
throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
}
inline void setRngSeed( ConfigData& config, std::string const& seed ) {
if( seed == "time" ) {
config.rngSeed = static_cast<unsigned int>( std::time(0) );
}
else {
std::stringstream ss;
ss << seed;
ss >> config.rngSeed;
if( ss.fail() )
throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
}
}
inline void setVerbosity( ConfigData& config, int level ) {
// !TBD: accept strings?
config.verbosity = static_cast<Verbosity::Level>( level );
}
inline void setShowDurations( ConfigData& config, bool _showDurations ) {
config.showDurations = _showDurations
? 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 setWaitForKeypress( ConfigData& config, std::string const& keypress ) {
std::string keypressLc = toLower( keypress );
if( keypressLc == "start" )
config.waitForKeypress = WaitForKeypress::BeforeStart;
else if( keypressLc == "exit" )
config.waitForKeypress = WaitForKeypress::BeforeExit;
else if( keypressLc == "both" )
config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
else
throw std::runtime_error( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
};
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() )
throw std::domain_error( "Unable to load input file: " + _filename );
std::string line;
while( std::getline( f, line ) ) {
line = trim(line);
if( !line.empty() && !startsWith( line, '#' ) ) {
if( !startsWith( line, '"' ) )
line = '"' + line + '"';
addTestOrTags( config, line + ',' );
}
}
}
inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
using namespace Clara;
CommandLine<ConfigData> cli;
cli.bindProcessName( &ConfigData::processName );
cli["-?"]["-h"]["--help"]
.describe( "display usage information" )
.bind( &ConfigData::showHelp );
cli["-l"]["--list-tests"]
.describe( "list all/matching test cases" )
.bind( &ConfigData::listTests );
cli["-t"]["--list-tags"]
.describe( "list all/matching tags" )
.bind( &ConfigData::listTags );
cli["-s"]["--success"]
.describe( "include successful tests in output" )
.bind( &ConfigData::showSuccessfulTests );
cli["-b"]["--break"]
.describe( "break into debugger on failure" )
.bind( &ConfigData::shouldDebugBreak );
cli["-e"]["--nothrow"]
.describe( "skip exception tests" )
.bind( &ConfigData::noThrow );
cli["-i"]["--invisibles"]
.describe( "show invisibles (tabs, newlines)" )
.bind( &ConfigData::showInvisibles );
cli["-o"]["--out"]
.describe( "output filename" )
.bind( &ConfigData::outputFilename, "filename" );
cli["-r"]["--reporter"]
// .placeholder( "name[:filename]" )
.describe( "reporter to use (defaults to console)" )
.bind( &addReporterName, "name" );
cli["-n"]["--name"]
.describe( "suite name" )
.bind( &ConfigData::name, "name" );
cli["-a"]["--abort"]
.describe( "abort at first failure" )
.bind( &abortAfterFirst );
cli["-x"]["--abortx"]
.describe( "abort after x failures" )
.bind( &abortAfterX, "no. failures" );
cli["-w"]["--warn"]
.describe( "enable warnings" )
.bind( &addWarning, "warning name" );
// - needs updating if reinstated
// cli.into( &setVerbosity )
// .describe( "level of verbosity (0=no output)" )
// .shortOpt( "v")
// .longOpt( "verbosity" )
// .placeholder( "level" );
cli[_]
.describe( "which test or tests to use" )
.bind( &addTestOrTags, "test name, pattern or tags" );
cli["-d"]["--durations"]
.describe( "show test durations" )
.bind( &setShowDurations, "yes|no" );
cli["-f"]["--input-file"]
.describe( "load test names to run from a file" )
.bind( &loadTestNamesFromFile, "filename" );
cli["-#"]["--filenames-as-tags"]
.describe( "adds a tag for the filename" )
.bind( &ConfigData::filenamesAsTags );
cli["-c"]["--section"]
.describe( "specify section to run" )
.bind( &addSectionToRun, "section name" );
// Less common commands which don't have a short form
cli["--list-test-names-only"]
.describe( "list all/matching test cases names only" )
.bind( &ConfigData::listTestNamesOnly );
cli["--list-extra-info"]
.describe( "list all/matching test cases with more info" )
.bind( &ConfigData::listExtraInfo );
cli["--list-reporters"]
.describe( "list all reporters" )
.bind( &ConfigData::listReporters );
cli["--order"]
.describe( "test case order (defaults to decl)" )
.bind( &setOrder, "decl|lex|rand" );
cli["--rng-seed"]
.describe( "set a specific seed for random numbers" )
.bind( &setRngSeed, "'time'|number" );
cli["--force-colour"]
.describe( "force colourised output (deprecated)" )
.bind( &forceColour );
cli["--use-colour"]
.describe( "should output be colourised" )
.bind( &setUseColour, "yes|no" );
cli["--libidentify"]
.describe( "report name and version according to libidentify standard" )
.bind( &ConfigData::libIdentify );
cli["--wait-for-keypress"]
.describe( "waits for a keypress before exiting" )
.bind( &setWaitForKeypress, "start|exit|both" );
return cli;
}
} // end namespace Catch } // end namespace Catch

View File

@@ -0,0 +1,57 @@
/*
* Created by Phil on 27/11/2013.
* Copyright 2013 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)
*/
#include "catch_common.h"
#include "catch_context.h"
#include "catch_interfaces_config.h"
#include <cstring>
#include <ostream>
namespace Catch {
SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept
: file( _file ),
line( _line )
{}
bool SourceLineInfo::empty() const noexcept {
return file[0] == '\0';
}
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
}
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
}
void seedRng( IConfig const& config ) {
if( config.rngSeed() != 0 )
std::srand( config.rngSeed() );
}
unsigned int rngSeed() {
return getCurrentContext().getConfig()->rngSeed();
}
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
#ifndef __GNUG__
os << info.file << '(' << info.line << ')';
#else
os << info.file << ':' << info.line;
#endif
return os;
}
bool isTrue( bool value ){ return value; }
bool alwaysTrue() { return true; }
bool alwaysFalse() { return false; }
std::string StreamEndStop::operator+() const {
return std::string();
}
}

View File

@@ -21,8 +21,9 @@
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
#include <sstream> #include <iosfwd>
#include <algorithm> #include <string>
#include <cstdint>
namespace Catch { namespace Catch {
@@ -34,79 +35,29 @@ namespace Catch {
}; }; }; };
class NonCopyable { class NonCopyable {
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable const& ) = delete;
NonCopyable( NonCopyable && ) = delete; NonCopyable( NonCopyable && ) = delete;
NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete;
NonCopyable& operator = ( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete;
#else
NonCopyable( NonCopyable const& info );
NonCopyable& operator = ( NonCopyable const& );
#endif
protected: protected:
NonCopyable() {} NonCopyable() {}
virtual ~NonCopyable(); virtual ~NonCopyable();
}; };
class SafeBool {
public:
typedef void (SafeBool::*type)() const;
static type makeSafe( bool value ) {
return value ? &SafeBool::trueValue : 0;
}
private:
void trueValue() const {}
};
template<typename ContainerT>
void deleteAll( ContainerT& container ) {
typename ContainerT::const_iterator it = container.begin();
typename ContainerT::const_iterator itEnd = container.end();
for(; it != itEnd; ++it )
delete *it;
}
template<typename AssociativeContainerT>
void deleteAllValues( AssociativeContainerT& container ) {
typename AssociativeContainerT::const_iterator it = container.begin();
typename AssociativeContainerT::const_iterator itEnd = container.end();
for(; it != itEnd; ++it )
delete it->second;
}
bool startsWith( std::string const& s, std::string const& prefix );
bool startsWith( std::string const& s, char prefix );
bool endsWith( std::string const& s, std::string const& suffix );
bool endsWith( std::string const& s, char suffix );
bool contains( std::string const& s, std::string const& infix );
void toLowerInPlace( std::string& s );
std::string toLower( std::string const& s );
std::string trim( std::string const& str );
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
struct pluralise {
pluralise( std::size_t count, std::string const& label );
friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
std::size_t m_count;
std::string m_label;
};
struct SourceLineInfo { struct SourceLineInfo {
SourceLineInfo(); SourceLineInfo() = delete;
SourceLineInfo( char const* _file, std::size_t _line ); SourceLineInfo( char const* _file, std::size_t _line ) noexcept;
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
SourceLineInfo(SourceLineInfo const& other) = default; SourceLineInfo( SourceLineInfo const& other ) = default;
SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo( SourceLineInfo && ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo& operator = ( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default;
# endif
bool empty() const; bool empty() const noexcept;
bool operator == ( SourceLineInfo const& other ) const; bool operator == ( SourceLineInfo const& other ) const noexcept;
bool operator < ( SourceLineInfo const& other ) const; bool operator < ( SourceLineInfo const& other ) const noexcept;
char const* file; char const* file;
std::size_t line; std::size_t line;
@@ -115,11 +66,9 @@ namespace Catch {
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals // This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue( bool value ){ return value; } bool isTrue( bool value );
inline bool alwaysTrue() { return true; } bool alwaysTrue();
inline bool alwaysFalse() { return false; } bool alwaysFalse();
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
void seedRng( IConfig const& config ); void seedRng( IConfig const& config );
unsigned int rngSeed(); unsigned int rngSeed();
@@ -129,9 +78,7 @@ namespace Catch {
// as well as // as well as
// >> stuff +StreamEndStop // >> stuff +StreamEndStop
struct StreamEndStop { struct StreamEndStop {
std::string operator+() { std::string operator+() const;
return std::string();
}
}; };
template<typename T> template<typename T>
T const& operator + ( T const& value, StreamEndStop ) { T const& operator + ( T const& value, StreamEndStop ) {
@@ -139,8 +86,8 @@ namespace Catch {
} }
} }
#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) #define CATCH_INTERNAL_LINEINFO \
#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
#endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED

View File

@@ -8,23 +8,9 @@
#ifndef TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler // Detect a number of compiler features - by compiler
// The following features are defined: // The following features are defined:
// //
// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
// 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_SHUFFLE : is std::shuffle supported?
// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
// 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? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
@@ -34,18 +20,13 @@
// **************** // ****************
// In general each macro has a _NO_<feature name> form // In general each macro has a _NO_<feature name> form
// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
// Many features, at point of detection, define an _INTERNAL_ macro, so they // Many features, at point of detection, define an _INTERNAL_ macro, so they
// can be combined, en-mass, with the _NO_ forms later. // can be combined, en-mass, with the _NO_ forms later.
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
#ifdef __cplusplus #ifdef __cplusplus
# if __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
# endif
# if __cplusplus >= 201402L # if __cplusplus >= 201402L
# define CATCH_CPP14_OR_GREATER # define CATCH_CPP14_OR_GREATER
# endif # endif
@@ -54,15 +35,7 @@
#ifdef __clang__ #ifdef __clang__
# if __has_feature(cxx_nullptr)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
# if __has_feature(cxx_noexcept)
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# endif
# if defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
_Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
@@ -74,7 +47,6 @@
_Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
_Pragma( "clang diagnostic pop" ) _Pragma( "clang diagnostic pop" )
# endif
#endif // __clang__ #endif // __clang__
@@ -129,14 +101,6 @@
// GCC // GCC
#ifdef __GNUC__ #ifdef __GNUC__
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
// - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below
#endif // __GNUC__ #endif // __GNUC__
@@ -146,132 +110,28 @@
#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
#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
#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
#endif
#endif // _MSC_VER #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 ) || \
( defined __GNUC__ && __GNUC__ >= 3 ) || \
( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
#endif
// Use __COUNTER__ if the compiler supports it // Use __COUNTER__ if the compiler supports it
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \
( defined __clang__ && __clang_major__ >= 3 ) ( defined __clang__ && __clang_major__ >= 3 )
// Use of __COUNTER__ is suppressed during code analysis in CLion/AppCode 2017.2.x and former, #define CATCH_INTERNAL_CONFIG_COUNTER
// because __COUNTER__ is not properly handled by it.
// This does not affect compilation
#if ( !defined __JETBRAINS_IDE__ || __JETBRAINS_IDE__ >= 20170300L )
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
#endif #endif
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
// catch all support for C++11
#if defined(CATCH_CPP11_OR_GREATER)
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# endif
# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# endif
# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
# endif
# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
# endif
# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
# endif
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
# 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
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
# endif
#endif // __cplusplus >= 201103L
// Now set the actual defines based on the above + anything the user has configured // Now set the actual defines based on the above + anything the user has configured
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_NULLPTR // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
#endif // analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) // This does not affect compilation
# define CATCH_CONFIG_CPP11_NOEXCEPT #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_GENERATED_METHODS
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_IS_ENUM
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_TUPLE
#endif
#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_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
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER # define CATCH_CONFIG_COUNTER
#endif #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_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_TYPE_TRAITS
# endif
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
# define CATCH_CONFIG_WINDOWS_SEH # define CATCH_CONFIG_WINDOWS_SEH
#endif #endif
@@ -289,35 +149,6 @@
# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
#endif #endif
// noexcept support:
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
# define CATCH_NOEXCEPT noexcept
# define CATCH_NOEXCEPT_IS(x) noexcept(x)
#else
# define CATCH_NOEXCEPT throw()
# define CATCH_NOEXCEPT_IS(x)
#endif
// nullptr support
#ifdef CATCH_CONFIG_CPP11_NULLPTR
# define CATCH_NULL nullptr
#else
# 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 #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED

View File

@@ -0,0 +1,72 @@
/*
* Created by Martin on 19/07/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)
*/
#include "catch_config.hpp"
#include "catch_enforce.h"
namespace Catch {
Config::Config( ConfigData const& data )
: m_data( data ),
m_stream( openStream() )
{
if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() );
for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags );
m_testSpec = parser.testSpec();
}
}
std::string const& Config::getFilename() const {
return m_data.outputFilename ;
}
bool Config::listTests() const { return m_data.listTests; }
bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; }
bool Config::listTags() const { return m_data.listTags; }
bool Config::listReporters() const { return m_data.listReporters; }
std::string Config::getProcessName() const { return m_data.processName; }
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
TestSpec const& Config::testSpec() const { return m_testSpec; }
bool Config::showHelp() const { return m_data.showHelp; }
// IConfig interface
bool Config::allowThrows() const { return !m_data.noThrow; }
std::ostream& Config::stream() const { return m_stream->stream(); }
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; }
UseColour::YesOrNo Config::useColour() const { return m_data.useColour; }
bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
int Config::abortAfter() const { return m_data.abortAfter; }
bool Config::showInvisibles() const { return m_data.showInvisibles; }
Verbosity Config::verbosity() const { return m_data.verbosity; }
IStream const* Config::openStream() {
if( m_data.outputFilename.empty() )
return new CoutStream();
else if( m_data.outputFilename[0] == '%' ) {
if( m_data.outputFilename == "%debug" )
return new DebugOutStream();
else
CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" );
}
else
return new FileStream( m_data.outputFilename );
}
} // end namespace Catch

View File

@@ -16,7 +16,6 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <string> #include <string>
#include <stdexcept>
#ifndef CATCH_CONFIG_CONSOLE_WIDTH #ifndef CATCH_CONFIG_CONSOLE_WIDTH
#define CATCH_CONFIG_CONSOLE_WIDTH 80 #define CATCH_CONFIG_CONSOLE_WIDTH 80
@@ -25,53 +24,29 @@
namespace Catch { namespace Catch {
struct ConfigData { struct ConfigData {
bool listTests = false;
bool listTags = false;
bool listReporters = false;
bool listTestNamesOnly = false;
ConfigData() bool showSuccessfulTests = false;
: listTests( false ), bool shouldDebugBreak = false;
listTags( false ), bool noThrow = false;
listReporters( false ), bool showHelp = false;
listTestNamesOnly( false ), bool showInvisibles = false;
listExtraInfo( false ), bool filenamesAsTags = false;
showSuccessfulTests( false ), bool libIdentify = false;
shouldDebugBreak( false ),
noThrow( false ),
showHelp( false ),
showInvisibles( false ),
filenamesAsTags( false ),
libIdentify( false ),
abortAfter( -1 ),
rngSeed( 0 ),
verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter ),
runOrder( RunTests::InDeclarationOrder ),
useColour( UseColour::Auto ),
waitForKeypress( WaitForKeypress::Never )
{}
bool listTests; int abortAfter = -1;
bool listTags; unsigned int rngSeed = 0;
bool listReporters; int benchmarkResolutionMultiple = 100;
bool listTestNamesOnly;
bool listExtraInfo;
bool showSuccessfulTests; Verbosity verbosity = Verbosity::Normal;
bool shouldDebugBreak; WarnAbout::What warnings = WarnAbout::Nothing;
bool noThrow; ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
bool showHelp; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
bool showInvisibles; UseColour::YesOrNo useColour = UseColour::Auto;
bool filenamesAsTags; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
bool libIdentify;
int abortAfter;
unsigned int rngSeed;
Verbosity::Level verbosity;
WarnAbout::What warnings;
ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder;
UseColour::YesOrNo useColour;
WaitForKeypress::When waitForKeypress;
std::string outputFilename; std::string outputFilename;
std::string name; std::string name;
@@ -83,80 +58,52 @@ namespace Catch {
}; };
class Config : public SharedImpl<IConfig> { class Config : public IConfig {
private:
Config( Config const& other );
Config& operator = ( Config const& other );
virtual void dummy(); virtual void dummy();
public: public:
Config() Config() = default;
{} Config( ConfigData const& data );
virtual ~Config() = default;
Config( ConfigData const& data ) std::string const& getFilename() const;
: m_data( data ),
m_stream( openStream() )
{
if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() );
for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
parser.parse( data.testsOrTags[i] );
m_testSpec = parser.testSpec();
}
}
virtual ~Config() {} bool listTests() const;
bool listTestNamesOnly() const;
bool listTags() const;
bool listReporters() const;
std::string const& getFilename() const { std::string getProcessName() const;
return m_data.outputFilename ;
}
bool listTests() const { return m_data.listTests; } std::vector<std::string> const& getReporterNames() const;
bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } std::vector<std::string> const& getSectionsToRun() const override;
bool listTags() const { return m_data.listTags; }
bool listReporters() const { return m_data.listReporters; }
bool listExtraInfo() const { return m_data.listExtraInfo; }
std::string getProcessName() const { return m_data.processName; } virtual TestSpec const& testSpec() const override;
std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; } bool showHelp() const;
std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
bool showHelp() const { return m_data.showHelp; }
// IConfig interface // IConfig interface
virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } bool allowThrows() const override;
virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } std::ostream& stream() const override;
virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } std::string name() const override;
virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } bool includeSuccessfulResults() const override;
virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } bool warnAboutMissingAssertions() const override;
virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } ShowDurations::OrNot showDurations() const override;
virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } RunTests::InWhatOrder runOrder() const override;
virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } unsigned int rngSeed() const override;
virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } int benchmarkResolutionMultiple() const override;
virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } UseColour::YesOrNo useColour() const override;
virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } bool shouldDebugBreak() const override;
virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } int abortAfter() const override;
bool showInvisibles() const override;
Verbosity verbosity() const override;
private: private:
IStream const* openStream() { 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; ConfigData m_data;
CATCH_AUTO_PTR( IStream const ) m_stream; std::unique_ptr<IStream const> m_stream;
TestSpec m_testSpec; TestSpec m_testSpec;
}; };

View File

@@ -5,17 +5,20 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying * 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) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
#include "catch_console_colour.hpp" #include "catch_console_colour.hpp"
#include "catch_errno_guard.hpp" #include "catch_enforce.h"
#include "catch_errno_guard.h"
#include "catch_interfaces_config.h"
#include "catch_stream.h"
#include "catch_context.h"
#include "catch_platform.h"
namespace Catch { namespace Catch {
namespace { namespace {
struct IColourImpl { struct IColourImpl {
virtual ~IColourImpl() {} virtual ~IColourImpl() = default;
virtual void use( Colour::Code _colourCode ) = 0; virtual void use( Colour::Code _colourCode ) = 0;
}; };
@@ -57,7 +60,7 @@ namespace {
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
} }
virtual void use( Colour::Code _colourCode ) { virtual void use( Colour::Code _colourCode ) override {
switch( _colourCode ) { switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -73,7 +76,7 @@ namespace {
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
case Colour::Bright: throw std::logic_error( "not a colour" ); case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
} }
} }
@@ -89,14 +92,12 @@ namespace {
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
static Win32ColourImpl s_instance; static Win32ColourImpl s_instance;
Ptr<IConfig const> config = getCurrentContext().getConfig(); IConfigPtr config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config UseColour::YesOrNo colourMode = config
? config->useColour() ? config->useColour()
: UseColour::Auto; : UseColour::Auto;
if( colourMode == UseColour::Auto ) if( colourMode == UseColour::Auto )
colourMode = !isDebuggerActive() colourMode = UseColour::Yes;
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes return colourMode == UseColour::Yes
? &s_instance ? &s_instance
: NoColourImpl::instance(); : NoColourImpl::instance();
@@ -118,7 +119,7 @@ namespace {
// https://github.com/philsquared/Catch/pull/131 // https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl { class PosixColourImpl : public IColourImpl {
public: public:
virtual void use( Colour::Code _colourCode ) { virtual void use( Colour::Code _colourCode ) override {
switch( _colourCode ) { switch( _colourCode ) {
case Colour::None: case Colour::None:
case Colour::White: return setColour( "[0m" ); case Colour::White: return setColour( "[0m" );
@@ -134,7 +135,7 @@ namespace {
case Colour::BrightGreen: return setColour( "[1;32m" ); case Colour::BrightGreen: return setColour( "[1;32m" );
case Colour::BrightWhite: return setColour( "[1;37m" ); case Colour::BrightWhite: return setColour( "[1;37m" );
case Colour::Bright: throw std::logic_error( "not a colour" ); case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
} }
} }
static IColourImpl* instance() { static IColourImpl* instance() {
@@ -150,12 +151,12 @@ namespace {
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
ErrnoGuard guard; ErrnoGuard guard;
Ptr<IConfig const> config = getCurrentContext().getConfig(); IConfigPtr config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config UseColour::YesOrNo colourMode = config
? config->useColour() ? config->useColour()
: UseColour::Auto; : UseColour::Auto;
if( colourMode == UseColour::Auto ) if( colourMode == UseColour::Auto )
colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) colourMode = isatty(STDOUT_FILENO)
? UseColour::Yes ? UseColour::Yes
: UseColour::No; : UseColour::No;
return colourMode == UseColour::Yes return colourMode == UseColour::Yes
@@ -178,8 +179,17 @@ namespace Catch {
namespace Catch { namespace Catch {
Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; } Colour::Colour( Colour&& rhs ) noexcept {
m_moved = rhs.m_moved;
rhs.m_moved = true;
}
Colour& Colour::operator=( Colour&& rhs ) noexcept {
m_moved = rhs.m_moved;
rhs.m_moved = true;
return *this;
}
Colour::~Colour(){ if( !m_moved ) use( None ); } Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) { void Colour::use( Code _colourCode ) {
@@ -187,6 +197,8 @@ namespace Catch {
impl->use( _colourCode ); impl->use( _colourCode );
} }
} // end namespace Catch std::ostream& operator << ( std::ostream& os, Colour const& ) {
return os;
}
#endif // TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED } // end namespace Catch

View File

@@ -50,17 +50,18 @@ namespace Catch {
// Use constructed object for RAII guard // Use constructed object for RAII guard
Colour( Code _colourCode ); Colour( Code _colourCode );
Colour( Colour const& other ); Colour( Colour&& other ) noexcept;
Colour& operator=( Colour&& other ) noexcept;
~Colour(); ~Colour();
// Use static method for one-shot changes // Use static method for one-shot changes
static void use( Code _colourCode ); static void use( Code _colourCode );
private: private:
bool m_moved; bool m_moved = false;
}; };
inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } std::ostream& operator << ( std::ostream& os, Colour const& );
} // end namespace Catch } // end namespace Catch

View File

@@ -0,0 +1,62 @@
/*
* Created by Phil on 31/12/2010.
* Copyright 2010 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)
*/
#include "catch_context.h"
#include "catch_common.h"
namespace Catch {
class Context : public IMutableContext, NonCopyable {
public: // IContext
virtual IResultCapture* getResultCapture() override {
return m_resultCapture;
}
virtual IRunner* getRunner() override {
return m_runner;
}
virtual IConfigPtr getConfig() const override {
return m_config;
}
public: // IMutableContext
virtual void setResultCapture( IResultCapture* resultCapture ) override {
m_resultCapture = resultCapture;
}
virtual void setRunner( IRunner* runner ) override {
m_runner = runner;
}
virtual void setConfig( IConfigPtr const& config ) override {
m_config = config;
}
friend IMutableContext& getCurrentMutableContext();
private:
IConfigPtr m_config;
IRunner* m_runner = nullptr;
IResultCapture* m_resultCapture = nullptr;
};
namespace {
Context* currentContext = nullptr;
}
IMutableContext& getCurrentMutableContext() {
if( !currentContext )
currentContext = new Context();
return *currentContext;
}
IContext& getCurrentContext() {
return getCurrentMutableContext();
}
void cleanUpContext() {
delete currentContext;
currentContext = nullptr;
}
}

View File

@@ -8,9 +8,7 @@
#ifndef TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
#include "catch_interfaces_generators.h" #include <memory>
#include "catch_ptr.hpp"
namespace Catch { namespace Catch {
@@ -18,18 +16,17 @@ namespace Catch {
class Stream; class Stream;
struct IResultCapture; struct IResultCapture;
struct IRunner; struct IRunner;
struct IGeneratorsForTest;
struct IConfig; struct IConfig;
using IConfigPtr = std::shared_ptr<IConfig const>;
struct IContext struct IContext
{ {
virtual ~IContext(); virtual ~IContext();
virtual IResultCapture* getResultCapture() = 0; virtual IResultCapture* getResultCapture() = 0;
virtual IRunner* getRunner() = 0; virtual IRunner* getRunner() = 0;
virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; virtual IConfigPtr getConfig() const = 0;
virtual bool advanceGeneratorsForCurrentTest() = 0;
virtual Ptr<IConfig const> getConfig() const = 0;
}; };
struct IMutableContext : IContext struct IMutableContext : IContext
@@ -37,14 +34,12 @@ namespace Catch {
virtual ~IMutableContext(); virtual ~IMutableContext();
virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
virtual void setRunner( IRunner* runner ) = 0; virtual void setRunner( IRunner* runner ) = 0;
virtual void setConfig( Ptr<IConfig const> const& config ) = 0; virtual void setConfig( IConfigPtr const& config ) = 0;
}; };
IContext& getCurrentContext(); IContext& getCurrentContext();
IMutableContext& getCurrentMutableContext(); IMutableContext& getCurrentMutableContext();
void cleanUpContext(); void cleanUpContext();
Stream createStream( std::string const& streamName );
} }
#endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED

View File

@@ -1,110 +0,0 @@
/*
* Created by Phil on 31/12/2010.
* Copyright 2010 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_CONTEXT_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
#include "catch_run_context.hpp"
#include "catch_context.h"
#include "catch_stream.hpp"
#include "catch_common.h"
namespace Catch {
class Context : public IMutableContext {
Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
Context( Context const& );
void operator=( Context const& );
public:
virtual ~Context() {
deleteAllValues( m_generatorsByTestName );
}
public: // IContext
virtual IResultCapture* getResultCapture() {
return m_resultCapture;
}
virtual IRunner* getRunner() {
return m_runner;
}
virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
return getGeneratorsForCurrentTest()
.getGeneratorInfo( fileInfo, totalSize )
.getCurrentIndex();
}
virtual bool advanceGeneratorsForCurrentTest() {
IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
return generators && generators->moveNext();
}
virtual Ptr<IConfig const> getConfig() const {
return m_config;
}
public: // IMutableContext
virtual void setResultCapture( IResultCapture* resultCapture ) {
m_resultCapture = resultCapture;
}
virtual void setRunner( IRunner* runner ) {
m_runner = runner;
}
virtual void setConfig( Ptr<IConfig const> const& config ) {
m_config = config;
}
friend IMutableContext& getCurrentMutableContext();
private:
IGeneratorsForTest* findGeneratorsForCurrentTest() {
std::string testName = getResultCapture()->getCurrentTestName();
std::map<std::string, IGeneratorsForTest*>::const_iterator it =
m_generatorsByTestName.find( testName );
return it != m_generatorsByTestName.end()
? it->second
: CATCH_NULL;
}
IGeneratorsForTest& getGeneratorsForCurrentTest() {
IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
if( !generators ) {
std::string testName = getResultCapture()->getCurrentTestName();
generators = createGeneratorsForTest();
m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
}
return *generators;
}
private:
Ptr<IConfig const> m_config;
IRunner* m_runner;
IResultCapture* m_resultCapture;
std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
};
namespace {
Context* currentContext = CATCH_NULL;
}
IMutableContext& getCurrentMutableContext() {
if( !currentContext )
currentContext = new Context();
return *currentContext;
}
IContext& getCurrentContext() {
return getCurrentMutableContext();
}
void cleanUpContext() {
delete currentContext;
currentContext = CATCH_NULL;
}
}
#endif // TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED

View File

@@ -6,11 +6,11 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
* *
*/ */
#ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#include "catch_debugger.h" #include "catch_debugger.h"
#include "catch_errno_guard.hpp" #include "catch_errno_guard.h"
#include "catch_stream.h"
#include "catch_platform.h"
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
@@ -49,7 +49,7 @@
// Call sysctl. // Call sysctl.
size = sizeof(info); size = sizeof(info);
if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
return false; return false;
} }
@@ -106,7 +106,7 @@
} }
#else #else
namespace Catch { namespace Catch {
inline bool isDebuggerActive() { return false; } bool isDebuggerActive() { return false; }
} }
#endif // Platform #endif // Platform
@@ -127,5 +127,3 @@
} }
} }
#endif // Platform #endif // Platform
#endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED

View File

@@ -21,15 +21,7 @@ namespace Catch{
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
// The following code snippet based on: #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
// http://cocoawithlove.com/2008/03/break-into-debugger.html
#if defined(__ppc64__) || defined(__ppc__)
#define CATCH_TRAP() \
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
: : : "memory","r0","r3","r4" ) /* NOLINT */
#else
#define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ )
#endif
#elif defined(CATCH_PLATFORM_LINUX) #elif defined(CATCH_PLATFORM_LINUX)
// If we can use inline assembler, do it because this allows us to break // If we can use inline assembler, do it because this allows us to break

View File

@@ -0,0 +1,22 @@
/*
* Created by Phil Nash on 8/8/2017.
* Copyright 2017 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)
*/
#include "catch_decomposer.h"
#include "catch_config.hpp"
namespace Catch {
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) {
if( lhs.size() + rhs.size() < 40 &&
lhs.find('\n') == std::string::npos &&
rhs.find('\n') == std::string::npos )
os << lhs << " " << op << " " << rhs;
else
os << lhs << "\n" << op << "\n" << rhs;
}
}

View File

@@ -0,0 +1,164 @@
/*
* Created by Phil Nash on 8/8/2017.
* Copyright 2017 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_DECOMPOSER_H_INCLUDED
#define TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED
#include "catch_tostring.h"
#include "catch_stringref.h"
#include <ostream>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
#endif
namespace Catch {
struct ITransientExpression {
virtual auto isBinaryExpression() const -> bool = 0;
virtual auto getResult() const -> bool = 0;
virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
// We don't actually need a virtual destructore, but many static analysers
// complain if it's not here :-(
virtual ~ITransientExpression() = default;
};
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs );
template<typename LhsT, typename RhsT>
class BinaryExpr : public ITransientExpression {
bool m_result;
LhsT m_lhs;
std::string m_op;
RhsT m_rhs;
auto isBinaryExpression() const -> bool override { return true; }
auto getResult() const -> bool override { return m_result; }
void streamReconstructedExpression( std::ostream &os ) const override {
formatReconstructedExpression
( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
}
public:
BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs )
: m_result( comparisionResult ),
m_lhs( lhs ),
m_op( op ),
m_rhs( rhs )
{}
};
template<typename LhsT>
class UnaryExpr : public ITransientExpression {
LhsT m_lhs;
auto isBinaryExpression() const -> bool override { return false; }
auto getResult() const -> bool override { return m_lhs ? true : false; }
void streamReconstructedExpression( std::ostream &os ) const override {
os << Catch::Detail::stringify( m_lhs );
}
public:
UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {}
};
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
template<typename LhsT, typename RhsT>
auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast<LhsT&>( lhs ) == rhs; };
template<typename T>
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); };
template<typename T>
auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; };
template<typename LhsT, typename RhsT>
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast<LhsT&>( lhs ) != rhs; };
template<typename T>
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); };
template<typename T>
auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; };
template<typename LhsT>
class ExprLhs {
LhsT m_lhs;
public:
ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
template<typename RhsT>
auto operator == ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
return BinaryExpr<LhsT, RhsT&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs );
}
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs );
}
template<typename RhsT>
auto operator != ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
return BinaryExpr<LhsT, RhsT&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs );
}
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs );
}
template<typename RhsT>
auto operator > ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs > rhs, m_lhs, ">", rhs );
}
template<typename RhsT>
auto operator < ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs < rhs, m_lhs, "<", rhs );
}
template<typename RhsT>
auto operator >= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs >= rhs, m_lhs, ">=", rhs );
}
template<typename RhsT>
auto operator <= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs <= rhs, m_lhs, "<=", rhs );
}
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
return UnaryExpr<LhsT>( m_lhs );
}
};
void handleExpression( ITransientExpression const& expr );
template<typename T>
void handleExpression( ExprLhs<T> const& expr ) {
handleExpression( expr.makeUnaryExpr() );
}
struct Decomposer {
template<typename T>
auto operator <= ( T& lhs ) -> ExprLhs<T&> {
return ExprLhs<T&>( lhs );
}
template<typename T>
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
return ExprLhs<T const&>( lhs );
}
auto operator <=( bool value ) -> ExprLhs<bool> {
return ExprLhs<bool>( value );
}
};
} // end namespace Catch
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED

View File

@@ -18,8 +18,7 @@ extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
#endif #endif
int result = Catch::Session().run( argc, argv ); return Catch::Session().run( argc, argv );
return ( result < 0xff ? result : 0xff );
} }
#else // __OBJC__ #else // __OBJC__
@@ -37,7 +36,7 @@ int main (int argc, char * const argv[]) {
[pool drain]; [pool drain];
#endif #endif
return ( result < 0xff ? result : 0xff ); return result;
} }
#endif // __OBJC__ #endif // __OBJC__

View File

@@ -0,0 +1,24 @@
/*
* Created by Martin on 01/08/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_ENFORCE_H_INCLUDED
#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
#include "catch_common.h"
#include <sstream>
#include <stdexcept>
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
type( static_cast<std::ostringstream&&>( std::ostringstream() << msg ).str() )
#define CATCH_INTERNAL_ERROR( msg ) \
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
#define CATCH_ERROR( msg ) \
throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg )
#define CATCH_ENFORCE( condition, msg ) \
do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
#endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED

View File

@@ -0,0 +1,15 @@
/*
* Created by Martin on 06/03/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)
*/
#include "catch_errno_guard.h"
#include <cerrno>
namespace Catch {
ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
}

View File

@@ -4,22 +4,19 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying * 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) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED
#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED #define TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED
#include <cerrno>
namespace Catch { namespace Catch {
class ErrnoGuard { class ErrnoGuard {
public: public:
ErrnoGuard():m_oldErrno(errno){} ErrnoGuard();
~ErrnoGuard() { errno = m_oldErrno; } ~ErrnoGuard();
private: private:
int m_oldErrno; int m_oldErrno;
}; };
} }
#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED

View File

@@ -1,220 +0,0 @@
/*
* Created by Phil on 04/03/2011.
* Copyright 2011 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_EVALUATE_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
#endif
#include <cstddef>
namespace Catch {
namespace Internal {
enum Operator {
IsEqualTo,
IsNotEqualTo,
IsLessThan,
IsGreaterThan,
IsLessThanOrEqualTo,
IsGreaterThanOrEqualTo
};
template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
template<typename T>
T& opCast(T const& t) { return const_cast<T&>(t); }
// nullptr_t support based on pull request #154 from Konstantin Baumann
#ifdef CATCH_CONFIG_CPP11_NULLPTR
inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
#endif // CATCH_CONFIG_CPP11_NULLPTR
// So the compare overloads can be operator agnostic we convey the operator as a template
// enum, which is used to specialise an Evaluator for doing the comparison.
template<typename T1, typename T2, Operator Op>
struct Evaluator{};
template<typename T1, typename T2>
struct Evaluator<T1, T2, IsEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& 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 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 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 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 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 bool( opCast( lhs ) <= opCast( rhs ) );
}
};
template<Operator Op, typename T1, typename T2>
bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
}
// This level of indirection allows us to specialise for integer types
// to avoid signed/ unsigned warnings
// "base" overload
template<Operator Op, typename T1, typename T2>
bool compare( T1 const& lhs, T2 const& rhs ) {
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
}
// unsigned X to int
template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
}
template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
}
template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
}
// unsigned X to long
template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
}
template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
}
template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
}
// int to unsigned X
template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
}
template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
}
template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
}
// long to unsigned X
template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
// pointer to long (when comparing against NULL)
template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
}
template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
}
// pointer to int (when comparing against NULL)
template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
}
template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
}
#ifdef CATCH_CONFIG_CPP11_LONG_LONG
// long long to unsigned X
template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
}
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 );
}
template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
}
template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
}
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 );
}
template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
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 ) {
return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
}
template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
}
#endif // CATCH_CONFIG_CPP11_NULLPTR
} // end of namespace Internal
} // end of namespace Catch
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED

View File

@@ -0,0 +1,62 @@
/*
* Created by Phil on 20/04/2011.
* Copyright 2011 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)
*/
#include "catch_assertionhandler.h"
#include "catch_exception_translator_registry.h"
#ifdef __OBJC__
#import "Foundation/Foundation.h"
#endif
namespace Catch {
ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
}
void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {
m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
}
std::string ExceptionTranslatorRegistry::translateActiveException() const {
try {
#ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@try {
return tryTranslators();
}
@catch (NSException *exception) {
return Catch::toString( [exception description] );
}
#else
return tryTranslators();
#endif
}
catch( TestFailureException& ) {
throw;
}
catch( std::exception& ex ) {
return ex.what();
}
catch( std::string& msg ) {
return msg;
}
catch( const char* msg ) {
return msg;
}
catch(...) {
return "Unknown exception";
}
}
std::string ExceptionTranslatorRegistry::tryTranslators() const {
if( m_translators.empty() )
throw;
else
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
}
}

View File

@@ -0,0 +1,30 @@
/*
* Created by Phil on 20/04/2011.
* Copyright 2011 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_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
#include "catch_interfaces_exception.h"
#include <vector>
#include <string>
#include <memory>
namespace Catch {
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
public:
~ExceptionTranslatorRegistry();
virtual void registerTranslator( const IExceptionTranslator* translator );
virtual std::string translateActiveException() const override;
std::string tryTranslators() const;
private:
std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
};
}
#endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED

View File

@@ -1,73 +0,0 @@
/*
* Created by Phil on 20/04/2011.
* Copyright 2011 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_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
#include "catch_interfaces_exception.h"
#include "catch_tostring.h"
#ifdef __OBJC__
#import "Foundation/Foundation.h"
#endif
namespace Catch {
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
public:
~ExceptionTranslatorRegistry() {
deleteAll( m_translators );
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_translators.push_back( translator );
}
virtual std::string translateActiveException() const {
try {
#ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@try {
return tryTranslators();
}
@catch (NSException *exception) {
return Catch::toString( [exception description] );
}
#else
return tryTranslators();
#endif
}
catch( TestFailureException& ) {
throw;
}
catch( std::exception& ex ) {
return ex.what();
}
catch( std::string& msg ) {
return msg;
}
catch( const char* msg ) {
return msg;
}
catch(...) {
return "Unknown exception";
}
}
std::string tryTranslators() const {
if( m_translators.empty() )
throw;
else
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
}
private:
std::vector<const IExceptionTranslator*> m_translators;
};
}
#endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED

View File

@@ -1,174 +0,0 @@
/*
* Created by Phil on 11/5/2012.
* Copyright 2012 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_EXPRESSION_LHS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
#include "catch_result_builder.h"
#include "catch_evaluate.hpp"
#include "catch_tostring.h"
namespace Catch {
template<typename LhsT, Internal::Operator Op, typename RhsT>
class BinaryExpression;
template<typename ArgT, typename MatcherT>
class MatchExpression;
// Wraps the LHS of an expression and overloads comparison operators
// for also capturing those and RHS (if any)
template<typename T>
class ExpressionLhs : public DecomposedExpression {
public:
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
ExpressionLhs& operator = ( const ExpressionLhs& );
template<typename RhsT>
BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
operator == ( RhsT const& rhs ) {
return captureExpression<Internal::IsEqualTo>( rhs );
}
template<typename RhsT>
BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
operator != ( RhsT const& rhs ) {
return captureExpression<Internal::IsNotEqualTo>( rhs );
}
template<typename RhsT>
BinaryExpression<T, Internal::IsLessThan, RhsT const&>
operator < ( RhsT const& rhs ) {
return captureExpression<Internal::IsLessThan>( rhs );
}
template<typename RhsT>
BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
operator > ( RhsT const& rhs ) {
return captureExpression<Internal::IsGreaterThan>( rhs );
}
template<typename RhsT>
BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
operator <= ( RhsT const& rhs ) {
return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
}
template<typename RhsT>
BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
operator >= ( RhsT const& rhs ) {
return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
}
BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
return captureExpression<Internal::IsEqualTo>( rhs );
}
BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
return captureExpression<Internal::IsNotEqualTo>( rhs );
}
void endExpression() {
m_truthy = m_lhs ? true : false;
m_rb
.setResultType( m_truthy )
.endExpression( *this );
}
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
dest = Catch::toString( m_lhs );
}
private:
template<Internal::Operator Op, typename RhsT>
BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
}
template<Internal::Operator Op>
BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
}
private:
ResultBuilder& m_rb;
T m_lhs;
bool m_truthy;
};
template<typename LhsT, Internal::Operator Op, typename RhsT>
class BinaryExpression : public DecomposedExpression {
public:
BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
: m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
BinaryExpression& operator = ( BinaryExpression& );
void endExpression() const {
m_rb
.setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
.endExpression( *this );
}
virtual bool isBinaryExpression() const CATCH_OVERRIDE {
return true;
}
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
std::string lhs = Catch::toString( m_lhs );
std::string rhs = Catch::toString( m_rhs );
char delim = lhs.size() + rhs.size() < 40 &&
lhs.find('\n') == std::string::npos &&
rhs.find('\n') == std::string::npos ? ' ' : '\n';
dest.reserve( 7 + lhs.size() + rhs.size() );
// 2 for spaces around operator
// 2 for operator
// 2 for parentheses (conditionally added later)
// 1 for negation (conditionally added later)
dest = lhs;
dest += delim;
dest += Internal::OperatorTraits<Op>::getName();
dest += delim;
dest += rhs;
}
private:
ResultBuilder& m_rb;
LhsT m_lhs;
RhsT m_rhs;
};
template<typename ArgT, typename MatcherT>
class MatchExpression : public DecomposedExpression {
public:
MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
: m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
virtual bool isBinaryExpression() const CATCH_OVERRIDE {
return true;
}
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
std::string matcherAsString = m_matcher.toString();
dest = Catch::toString( m_arg );
dest += ' ';
if( matcherAsString == Detail::unprintableString )
dest += m_matcherString;
else
dest += matcherAsString;
}
private:
ArgT m_arg;
MatcherT m_matcher;
char const* m_matcherString;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED

View File

@@ -0,0 +1,13 @@
/*
* Created by Martin on 17/08/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_EXTERNAL_INTERFACES_H
#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H
#include "../reporters/catch_reporter_bases.hpp"
#include "catch_reporter_registrars.hpp"
#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H

View File

@@ -0,0 +1,181 @@
/*
* Created by Phil on 21/08/2014
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
#include "catch_fatal_condition.h"
#include "catch_context.h"
#include "catch_interfaces_capture.h"
namespace Catch {
// Report the error condition
void reportFatal( std::string const& message ) {
IContext& context = Catch::getCurrentContext();
IResultCapture* resultCapture = context.getResultCapture();
resultCapture->handleFatalErrorCondition( message );
}
} // namespace Catch
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
void FatalConditionHandler::reset() {}
}
# else // CATCH_CONFIG_WINDOWS_SEH is defined
namespace Catch {
struct SignalDefs { DWORD id; const char* name; };
// There is no 1-1 mapping between signals and windows exceptions.
// Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently.
SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
};
LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reportFatal(signalDefs[i].name);
}
}
// If its not an exception we care about, pass it along.
// This stops us from eating debugger breaks etc.
return EXCEPTION_CONTINUE_SEARCH;
}
FatalConditionHandler::FatalConditionHandler() {
isSet = true;
// 32k seems enough for Catch to handle stack overflow,
// but the value was found experimentally, so there is no strong guarantee
guaranteeSize = 32 * 1024;
exceptionHandlerHandle = nullptr;
// Register as first handler in current chain
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
// Pass in guarantee size to be filled
SetThreadStackGuarantee(&guaranteeSize);
}
void FatalConditionHandler::reset() {
if (isSet) {
// Unregister handler and restore the old guarantee
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
SetThreadStackGuarantee(&guaranteeSize);
exceptionHandlerHandle = nullptr;
isSet = false;
}
}
FatalConditionHandler::~FatalConditionHandler() {
reset();
}
bool FatalConditionHandler::isSet = false;
ULONG FatalConditionHandler::guaranteeSize = 0;
PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
} // namespace Catch
# endif // CATCH_CONFIG_WINDOWS_SEH
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
namespace Catch {
void FatalConditionHandler::reset() {}
}
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
#include <signal.h>
namespace Catch {
struct SignalDefs {
int id;
const char* name;
};
SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" },
{ SIGFPE, "SIGFPE - Floating point error signal" },
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" },
{ SIGTERM, "SIGTERM - Termination request signal" },
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
};
void FatalConditionHandler::handleSignal( int sig ) {
std::string name = "<unknown signal>";
for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
SignalDefs &def = signalDefs[i];
if (sig == def.id) {
name = def.name;
break;
}
}
reset();
reportFatal(name);
raise( sig );
}
FatalConditionHandler::FatalConditionHandler() {
isSet = true;
stack_t sigStack;
sigStack.ss_sp = altStackMem;
sigStack.ss_size = SIGSTKSZ;
sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { };
sa.sa_handler = handleSignal;
sa.sa_flags = SA_ONSTACK;
for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
}
}
FatalConditionHandler::~FatalConditionHandler() {
reset();
}
void FatalConditionHandler::reset() {
if( isSet ) {
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
}
// Return the old stack
sigaltstack(&oldSigStack, nullptr);
isSet = false;
}
}
bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
} // namespace Catch
# endif // CATCH_CONFIG_POSIX_SIGNALS
#endif // not Windows

View File

@@ -0,0 +1,92 @@
/*
* Created by Phil on 21/08/2014
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
#include <string>
#include "catch_platform.h"
#include "catch_compiler_capabilities.h"
namespace Catch {
// Report the error condition
void reportFatal( std::string const& message );
} // namespace Catch
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
#include "catch_windows_h_proxy.h"
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
struct FatalConditionHandler {
void reset();
};
}
# else // CATCH_CONFIG_WINDOWS_SEH is defined
namespace Catch {
struct FatalConditionHandler {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
FatalConditionHandler();
static void reset();
~FatalConditionHandler();
private:
static bool isSet;
static ULONG guaranteeSize;
static PVOID exceptionHandlerHandle;
};
} // namespace Catch
# endif // CATCH_CONFIG_WINDOWS_SEH
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
namespace Catch {
struct FatalConditionHandler {
void reset();
};
}
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
#include <signal.h>
namespace Catch {
struct FatalConditionHandler {
static bool isSet;
static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)];
static stack_t oldSigStack;
static char altStackMem[];
static void handleSignal( int sig );
FatalConditionHandler();
~FatalConditionHandler();
static void reset();
};
} // namespace Catch
# endif // CATCH_CONFIG_POSIX_SIGNALS
#endif // not Windows
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED

View File

@@ -1,200 +0,0 @@
/*
* Created by Phil on 21/08/2014
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
namespace Catch {
// Report the error condition
inline void reportFatal( std::string const& message ) {
IContext& context = Catch::getCurrentContext();
IResultCapture* resultCapture = context.getResultCapture();
resultCapture->handleFatalErrorCondition( message );
}
} // namespace Catch
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
#include "catch_windows_h_proxy.h"
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
struct FatalConditionHandler {
void reset() {}
};
}
# else // CATCH_CONFIG_WINDOWS_SEH is defined
namespace Catch {
struct SignalDefs { DWORD id; const char* name; };
extern SignalDefs signalDefs[];
// There is no 1-1 mapping between signals and windows exceptions.
// Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently.
SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
};
struct FatalConditionHandler {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reportFatal(signalDefs[i].name);
}
}
// If its not an exception we care about, pass it along.
// This stops us from eating debugger breaks etc.
return EXCEPTION_CONTINUE_SEARCH;
}
FatalConditionHandler() {
isSet = true;
// 32k seems enough for Catch to handle stack overflow,
// but the value was found experimentally, so there is no strong guarantee
guaranteeSize = 32 * 1024;
exceptionHandlerHandle = CATCH_NULL;
// Register as first handler in current chain
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
// Pass in guarantee size to be filled
SetThreadStackGuarantee(&guaranteeSize);
}
static void reset() {
if (isSet) {
// Unregister handler and restore the old guarantee
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
SetThreadStackGuarantee(&guaranteeSize);
exceptionHandlerHandle = CATCH_NULL;
isSet = false;
}
}
~FatalConditionHandler() {
reset();
}
private:
static bool isSet;
static ULONG guaranteeSize;
static PVOID exceptionHandlerHandle;
};
bool FatalConditionHandler::isSet = false;
ULONG FatalConditionHandler::guaranteeSize = 0;
PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
} // namespace Catch
# endif // CATCH_CONFIG_WINDOWS_SEH
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
namespace Catch {
struct FatalConditionHandler {
void reset() {}
};
}
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
#include <signal.h>
namespace Catch {
struct SignalDefs {
int id;
const char* name;
};
extern SignalDefs signalDefs[];
SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" },
{ SIGFPE, "SIGFPE - Floating point error signal" },
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" },
{ SIGTERM, "SIGTERM - Termination request signal" },
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
};
struct FatalConditionHandler {
static bool isSet;
static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
static stack_t oldSigStack;
static char altStackMem[SIGSTKSZ];
static void handleSignal( int sig ) {
std::string name = "<unknown signal>";
for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
SignalDefs &def = signalDefs[i];
if (sig == def.id) {
name = def.name;
break;
}
}
reset();
reportFatal(name);
raise( sig );
}
FatalConditionHandler() {
isSet = true;
stack_t sigStack;
sigStack.ss_sp = altStackMem;
sigStack.ss_size = SIGSTKSZ;
sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { 0 };
sa.sa_handler = handleSignal;
sa.sa_flags = SA_ONSTACK;
for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
}
}
~FatalConditionHandler() {
reset();
}
static void reset() {
if( isSet ) {
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
}
// Return the old stack
sigaltstack(&oldSigStack, CATCH_NULL);
isSet = false;
}
}
};
bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
} // namespace Catch
# endif // CATCH_CONFIG_POSIX_SIGNALS
#endif // not Windows
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED

View File

@@ -1,189 +0,0 @@
/*
* Created by Phil on 27/01/2011.
* Copyright 2011 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_GENERATORS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
#include "catch_context.h"
#include <vector>
#include <string>
#include <stdlib.h>
namespace Catch {
template<typename T>
struct IGenerator {
virtual ~IGenerator() {}
virtual T getValue( std::size_t index ) const = 0;
virtual std::size_t size () const = 0;
};
template<typename T>
class BetweenGenerator : public IGenerator<T> {
public:
BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
virtual T getValue( std::size_t index ) const {
return m_from+static_cast<int>( index );
}
virtual std::size_t size() const {
return static_cast<std::size_t>( 1+m_to-m_from );
}
private:
T m_from;
T m_to;
};
template<typename T>
class ValuesGenerator : public IGenerator<T> {
public:
ValuesGenerator(){}
void add( T value ) {
m_values.push_back( value );
}
virtual T getValue( std::size_t index ) const {
return m_values[index];
}
virtual std::size_t size() const {
return m_values.size();
}
private:
std::vector<T> m_values;
};
template<typename T>
class CompositeGenerator {
public:
CompositeGenerator() : m_totalSize( 0 ) {}
// *** Move semantics, similar to auto_ptr ***
CompositeGenerator( CompositeGenerator& other )
: m_fileInfo( other.m_fileInfo ),
m_totalSize( 0 )
{
move( other );
}
CompositeGenerator& setFileInfo( const char* fileInfo ) {
m_fileInfo = fileInfo;
return *this;
}
~CompositeGenerator() {
deleteAll( m_composed );
}
operator T () const {
size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
for( size_t index = 0; it != itEnd; ++it )
{
const IGenerator<T>* generator = *it;
if( overallIndex >= index && overallIndex < index + generator->size() )
{
return generator->getValue( overallIndex-index );
}
index += generator->size();
}
CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
}
void add( const IGenerator<T>* generator ) {
m_totalSize += generator->size();
m_composed.push_back( generator );
}
CompositeGenerator& then( CompositeGenerator& other ) {
move( other );
return *this;
}
CompositeGenerator& then( T value ) {
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
valuesGen->add( value );
add( valuesGen );
return *this;
}
private:
void move( CompositeGenerator& other ) {
m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() );
m_totalSize += other.m_totalSize;
other.m_composed.clear();
}
std::vector<const IGenerator<T>*> m_composed;
std::string m_fileInfo;
size_t m_totalSize;
};
namespace Generators
{
template<typename T>
CompositeGenerator<T> between( T from, T to ) {
CompositeGenerator<T> generators;
generators.add( new BetweenGenerator<T>( from, to ) );
return generators;
}
template<typename T>
CompositeGenerator<T> values( T val1, T val2 ) {
CompositeGenerator<T> generators;
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
valuesGen->add( val1 );
valuesGen->add( val2 );
generators.add( valuesGen );
return generators;
}
template<typename T>
CompositeGenerator<T> values( T val1, T val2, T val3 ){
CompositeGenerator<T> generators;
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
valuesGen->add( val1 );
valuesGen->add( val2 );
valuesGen->add( val3 );
generators.add( valuesGen );
return generators;
}
template<typename T>
CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
CompositeGenerator<T> generators;
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
valuesGen->add( val1 );
valuesGen->add( val2 );
valuesGen->add( val3 );
valuesGen->add( val4 );
generators.add( valuesGen );
return generators;
}
} // end namespace Generators
using namespace Generators;
} // end namespace Catch
#define INTERNAL_CATCH_LINESTR2( line ) #line
#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED

View File

@@ -1,86 +0,0 @@
/*
* Created by Phil on 28/01/2011.
* Copyright 2011 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_GENERATORS_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
#include "catch_interfaces_generators.h"
#include "catch_common.h"
#include <vector>
#include <string>
#include <map>
namespace Catch {
struct GeneratorInfo : IGeneratorInfo {
GeneratorInfo( std::size_t size )
: m_size( size ),
m_currentIndex( 0 )
{}
bool moveNext() {
if( ++m_currentIndex == m_size ) {
m_currentIndex = 0;
return false;
}
return true;
}
std::size_t getCurrentIndex() const {
return m_currentIndex;
}
std::size_t m_size;
std::size_t m_currentIndex;
};
///////////////////////////////////////////////////////////////////////////
class GeneratorsForTest : public IGeneratorsForTest {
public:
~GeneratorsForTest() {
deleteAll( m_generatorsInOrder );
}
IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
if( it == m_generatorsByName.end() ) {
IGeneratorInfo* info = new GeneratorInfo( size );
m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
m_generatorsInOrder.push_back( info );
return *info;
}
return *it->second;
}
bool moveNext() {
std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
for(; it != itEnd; ++it ) {
if( (*it)->moveNext() )
return true;
}
return false;
}
private:
std::map<std::string, IGeneratorInfo*> m_generatorsByName;
std::vector<IGeneratorInfo*> m_generatorsInOrder;
};
IGeneratorsForTest* createGeneratorsForTest()
{
return new GeneratorsForTest();
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED

View File

@@ -16,91 +16,49 @@
#pragma clang diagnostic ignored "-Wweak-vtables" #pragma clang diagnostic ignored "-Wweak-vtables"
#endif #endif
#include "../catch_session.hpp"
#include "catch_registry_hub.hpp"
#include "catch_notimplemented_exception.hpp"
#include "catch_context_impl.hpp"
#include "catch_console_colour_impl.hpp"
#include "catch_generators_impl.hpp"
#include "catch_assertionresult.hpp"
#include "catch_test_case_info.hpp"
#include "catch_test_spec.hpp"
#include "catch_version.hpp"
#include "catch_message.hpp"
#include "catch_legacy_reporter_adapter.hpp"
#include "catch_timer.hpp"
#include "catch_common.hpp"
#include "catch_section.hpp"
#include "catch_debugger.hpp"
#include "catch_tostring.hpp"
#include "catch_result_builder.hpp"
#include "catch_tag_alias_registry.hpp"
#include "catch_test_case_tracker.hpp"
#include "catch_matchers_string.hpp"
#include "../reporters/catch_reporter_multi.hpp" #include "internal/catch_notimplemented_exception.h"
#include "../reporters/catch_reporter_xml.hpp"
#include "../reporters/catch_reporter_junit.hpp"
#include "../reporters/catch_reporter_console.hpp" // Temporary hack to fix separately provided reporters
#include "../reporters/catch_reporter_compact.hpp" #include "../reporters/catch_reporter_bases.hpp"
#include "catch_reporter_registrars.hpp"
//
#include "internal/catch_leak_detector.h"
#include "../catch_session.hpp"
#include "catch_test_spec.hpp"
#include "catch_test_case_tracker.hpp"
// Cpp files will be included in the single-header file here
// ~*~* CATCH_CPP_STITCH_PLACE *~*~
namespace Catch { namespace Catch {
LeakDetector leakDetector;
// These are all here to avoid warnings about not having any out of line // These are all here to avoid warnings about not having any out of line
// virtual methods // virtual methods
NonCopyable::~NonCopyable() {} NonCopyable::~NonCopyable() {}
IShared::~IShared() {} IStream::~IStream() noexcept {}
IStream::~IStream() CATCH_NOEXCEPT {} FileStream::~FileStream() noexcept {}
FileStream::~FileStream() CATCH_NOEXCEPT {} CoutStream::~CoutStream() noexcept {}
CoutStream::~CoutStream() CATCH_NOEXCEPT {} DebugOutStream::~DebugOutStream() noexcept {}
DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() noexcept {}
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
IContext::~IContext() {} IContext::~IContext() {}
IResultCapture::~IResultCapture() {} IResultCapture::~IResultCapture() {}
ITestCase::~ITestCase() {} ITestInvoker::~ITestInvoker() {}
ITestCaseRegistry::~ITestCaseRegistry() {} ITestCaseRegistry::~ITestCaseRegistry() {}
IRegistryHub::~IRegistryHub() {} IRegistryHub::~IRegistryHub() {}
IMutableRegistryHub::~IMutableRegistryHub() {} IMutableRegistryHub::~IMutableRegistryHub() {}
IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslator::~IExceptionTranslator() {}
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
IReporter::~IReporter() {}
IReporterFactory::~IReporterFactory() {}
IReporterRegistry::~IReporterRegistry() {}
IStreamingReporter::~IStreamingReporter() {}
AssertionStats::~AssertionStats() {}
SectionStats::~SectionStats() {}
TestCaseStats::~TestCaseStats() {}
TestGroupStats::~TestGroupStats() {}
TestRunStats::~TestRunStats() {}
CumulativeReporterBase::SectionNode::~SectionNode() {}
CumulativeReporterBase::~CumulativeReporterBase() {}
StreamingReporterBase::~StreamingReporterBase() {}
ConsoleReporter::~ConsoleReporter() {}
CompactReporter::~CompactReporter() {}
IRunner::~IRunner() {} IRunner::~IRunner() {}
IMutableContext::~IMutableContext() {} IMutableContext::~IMutableContext() {}
IConfig::~IConfig() {} IConfig::~IConfig() {}
XmlReporter::~XmlReporter() {}
JunitReporter::~JunitReporter() {}
TestRegistry::~TestRegistry() {}
FreeFunctionTestCase::~FreeFunctionTestCase() {}
IGeneratorInfo::~IGeneratorInfo() {}
IGeneratorsForTest::~IGeneratorsForTest() {}
WildcardPattern::~WildcardPattern() {}
TestSpec::Pattern::~Pattern() {}
TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {}
TestSpec::ExcludedPattern::~ExcludedPattern() {}
Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
void Config::dummy() {} void Config::dummy() {}
namespace TestCaseTracking {
ITracker::~ITracker() {}
TrackerBase::~TrackerBase() {}
SectionTracker::~SectionTracker() {}
IndexTracker::~IndexTracker() {}
}
} }
#ifdef __clang__ #ifdef __clang__

View File

@@ -9,8 +9,6 @@
#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
#include <string> #include <string>
#include "catch_result_type.h"
#include "catch_common.h"
namespace Catch { namespace Catch {
@@ -22,16 +20,23 @@ namespace Catch {
struct MessageInfo; struct MessageInfo;
class ScopedMessageBuilder; class ScopedMessageBuilder;
struct Counts; struct Counts;
struct BenchmarkInfo;
struct BenchmarkStats;
struct IResultCapture { struct IResultCapture {
virtual ~IResultCapture(); virtual ~IResultCapture();
virtual void assertionStarting( AssertionInfo const& info ) = 0;
virtual void assertionEnded( AssertionResult const& result ) = 0; virtual void assertionEnded( AssertionResult const& result ) = 0;
virtual bool sectionStarted( SectionInfo const& sectionInfo, virtual bool sectionStarted( SectionInfo const& sectionInfo,
Counts& assertions ) = 0; Counts& assertions ) = 0;
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0;

View File

@@ -8,19 +8,20 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
#include "catch_common.h"
#include <iosfwd> #include <iosfwd>
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory>
#include "catch_ptr.hpp"
namespace Catch { namespace Catch {
struct Verbosity { enum Level { enum class Verbosity {
NoOutput = 0, Quiet = 0,
Quiet, Normal,
Normal High
}; }; };
struct WarnAbout { enum What { struct WarnAbout { enum What {
Nothing = 0x00, Nothing = 0x00,
@@ -51,7 +52,7 @@ namespace Catch {
class TestSpec; class TestSpec;
struct IConfig : IShared { struct IConfig : NonCopyable {
virtual ~IConfig(); virtual ~IConfig();
@@ -67,10 +68,13 @@ namespace Catch {
virtual TestSpec const& testSpec() const = 0; virtual TestSpec const& testSpec() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0; virtual unsigned int rngSeed() const = 0;
virtual int benchmarkResolutionMultiple() const = 0;
virtual UseColour::YesOrNo useColour() const = 0; virtual UseColour::YesOrNo useColour() const = 0;
virtual std::vector<std::string> const& getSectionsToRun() const = 0; virtual std::vector<std::string> const& getSectionsToRun() const = 0;
virtual Verbosity verbosity() const = 0;
}; };
using IConfigPtr = std::shared_ptr<IConfig const>;
} }
#endif // TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #endif // TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED

View File

@@ -14,11 +14,10 @@
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
namespace Catch { namespace Catch {
using exceptionTranslateFunction = std::string(*)();
typedef std::string(*exceptionTranslateFunction)();
struct IExceptionTranslator; struct IExceptionTranslator;
typedef std::vector<const IExceptionTranslator*> ExceptionTranslators; using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
struct IExceptionTranslator { struct IExceptionTranslator {
virtual ~IExceptionTranslator(); virtual ~IExceptionTranslator();
@@ -40,7 +39,7 @@ namespace Catch {
: m_translateFunction( translateFunction ) : m_translateFunction( translateFunction )
{} {}
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
try { try {
if( it == itEnd ) if( it == itEnd )
throw; throw;

View File

@@ -1,32 +0,0 @@
/*
* Created by Phil on 7/8/2012.
* Copyright 2011 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_INTERFACES_GENERATORS_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
#include <string>
namespace Catch {
struct IGeneratorInfo {
virtual ~IGeneratorInfo();
virtual bool moveNext() = 0;
virtual std::size_t getCurrentIndex() const = 0;
};
struct IGeneratorsForTest {
virtual ~IGeneratorsForTest();
virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
virtual bool moveNext() = 0;
};
IGeneratorsForTest* createGeneratorsForTest();
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED

View File

@@ -8,9 +8,10 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
#include "catch_ptr.hpp" #include "catch_common.h"
#include <string> #include <string>
#include <memory>
namespace Catch { namespace Catch {
@@ -21,6 +22,9 @@ namespace Catch {
struct IReporterRegistry; struct IReporterRegistry;
struct IReporterFactory; struct IReporterFactory;
struct ITagAliasRegistry; struct ITagAliasRegistry;
class StartupExceptionRegistry;
using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
struct IRegistryHub { struct IRegistryHub {
virtual ~IRegistryHub(); virtual ~IRegistryHub();
@@ -30,15 +34,19 @@ namespace Catch {
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
}; };
struct IMutableRegistryHub { struct IMutableRegistryHub {
virtual ~IMutableRegistryHub(); virtual ~IMutableRegistryHub();
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0; virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0;
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
virtual void registerStartupException() noexcept = 0;
}; };
IRegistryHub& getRegistryHub(); IRegistryHub& getRegistryHub();

View File

@@ -0,0 +1,122 @@
/*
* Created by Martin on 19/07/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)
*/
#include "catch_interfaces_reporter.h"
#include "../reporters/catch_reporter_multi.h"
namespace Catch {
ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
std::ostream& ReporterConfig::stream() const { return *m_stream; }
IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }
TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}
GroupInfo::GroupInfo( std::string const& _name,
std::size_t _groupIndex,
std::size_t _groupsCount )
: name( _name ),
groupIndex( _groupIndex ),
groupsCounts( _groupsCount )
{}
AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages,
Totals const& _totals )
: assertionResult( _assertionResult ),
infoMessages( _infoMessages ),
totals( _totals )
{
assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
if( assertionResult.hasMessage() ) {
// Copy message into messages list.
// !TBD This should have been done earlier, somewhere
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
builder << assertionResult.getMessage();
builder.m_info.message = builder.m_stream.str();
infoMessages.push_back( builder.m_info );
}
}
SectionStats::SectionStats( SectionInfo const& _sectionInfo,
Counts const& _assertions,
double _durationInSeconds,
bool _missingAssertions )
: sectionInfo( _sectionInfo ),
assertions( _assertions ),
durationInSeconds( _durationInSeconds ),
missingAssertions( _missingAssertions )
{}
TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
Totals const& _totals,
std::string const& _stdOut,
std::string const& _stdErr,
bool _aborting )
: testInfo( _testInfo ),
totals( _totals ),
stdOut( _stdOut ),
stdErr( _stdErr ),
aborting( _aborting )
{}
TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
Totals const& _totals,
bool _aborting )
: groupInfo( _groupInfo ),
totals( _totals ),
aborting( _aborting )
{}
TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )
: groupInfo( _groupInfo ),
aborting( false )
{}
TestRunStats::TestRunStats( TestRunInfo const& _runInfo,
Totals const& _totals,
bool _aborting )
: runInfo( _runInfo ),
totals( _totals ),
aborting( _aborting )
{}
bool IStreamingReporter::isMulti() const { return false; }
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
if( !existingReporter ) {
existingReporter = std::move( additionalReporter );
return;
}
MultipleReporters* multi = nullptr;
if( existingReporter->isMulti() ) {
multi = static_cast<MultipleReporters*>( existingReporter.get() );
}
else {
auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters );
newMulti->add( std::move( existingReporter ) );
multi = newMulti.get();
existingReporter = std::move( newMulti );
}
multi->add( std::move( additionalReporter ) );
}
} // end namespace Catch

View File

@@ -10,46 +10,42 @@
#include "catch_section_info.h" #include "catch_section_info.h"
#include "catch_common.h" #include "catch_common.h"
#include "catch_totals.hpp"
#include "catch_ptr.hpp"
#include "catch_config.hpp" #include "catch_config.hpp"
#include "catch_context.h"
#include "catch_totals.hpp"
#include "catch_test_case_info.h" #include "catch_test_case_info.h"
#include "catch_assertionresult.h" #include "catch_assertionresult.h"
#include "catch_message.h" #include "catch_message.h"
#include "catch_option.hpp" #include "catch_option.hpp"
#include <string> #include <string>
#include <ostream> #include <iosfwd>
#include <map> #include <map>
#include <set>
#include <memory>
namespace Catch {
namespace Catch
{
struct ReporterConfig { struct ReporterConfig {
explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig ) explicit ReporterConfig( IConfigPtr const& _fullConfig );
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream ) ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
std::ostream& stream() const { return *m_stream; } std::ostream& stream() const;
Ptr<IConfig const> fullConfig() const { return m_fullConfig; } IConfigPtr fullConfig() const;
private: private:
std::ostream* m_stream; std::ostream* m_stream;
Ptr<IConfig const> m_fullConfig; IConfigPtr m_fullConfig;
}; };
struct ReporterPreferences { struct ReporterPreferences {
ReporterPreferences() bool shouldRedirectStdOut = false;
: shouldRedirectStdOut( false )
{}
bool shouldRedirectStdOut;
}; };
template<typename T> template<typename T>
struct LazyStat : Option<T> { struct LazyStat : Option<T> {
LazyStat() : used( false ) {}
LazyStat& operator=( T const& _value ) { LazyStat& operator=( T const& _value ) {
Option<T>::operator=( _value ); Option<T>::operator=( _value );
used = false; used = false;
@@ -59,21 +55,17 @@ namespace Catch
Option<T>::reset(); Option<T>::reset();
used = false; used = false;
} }
bool used; bool used = false;
}; };
struct TestRunInfo { struct TestRunInfo {
TestRunInfo( std::string const& _name ) : name( _name ) {} TestRunInfo( std::string const& _name );
std::string name; std::string name;
}; };
struct GroupInfo { struct GroupInfo {
GroupInfo( std::string const& _name, GroupInfo( std::string const& _name,
std::size_t _groupIndex, std::size_t _groupIndex,
std::size_t _groupsCount ) std::size_t _groupsCount );
: name( _name ),
groupIndex( _groupIndex ),
groupsCounts( _groupsCount )
{}
std::string name; std::string name;
std::size_t groupIndex; std::size_t groupIndex;
@@ -83,29 +75,13 @@ namespace Catch
struct AssertionStats { struct AssertionStats {
AssertionStats( AssertionResult const& _assertionResult, AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages, std::vector<MessageInfo> const& _infoMessages,
Totals const& _totals ) Totals const& _totals );
: assertionResult( _assertionResult ),
infoMessages( _infoMessages ),
totals( _totals )
{
if( assertionResult.hasMessage() ) {
// Copy message into messages list.
// !TBD This should have been done earlier, somewhere
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
builder << assertionResult.getMessage();
builder.m_info.message = builder.m_stream.str();
infoMessages.push_back( builder.m_info );
}
}
virtual ~AssertionStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats const& ) = default;
AssertionStats( AssertionStats && ) = default; AssertionStats( AssertionStats && ) = default;
AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats const& ) = default;
AssertionStats& operator = ( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats && ) = default;
# endif virtual ~AssertionStats() = default;
AssertionResult assertionResult; AssertionResult assertionResult;
std::vector<MessageInfo> infoMessages; std::vector<MessageInfo> infoMessages;
@@ -116,19 +92,12 @@ namespace Catch
SectionStats( SectionInfo const& _sectionInfo, SectionStats( SectionInfo const& _sectionInfo,
Counts const& _assertions, Counts const& _assertions,
double _durationInSeconds, double _durationInSeconds,
bool _missingAssertions ) bool _missingAssertions );
: sectionInfo( _sectionInfo ),
assertions( _assertions ),
durationInSeconds( _durationInSeconds ),
missingAssertions( _missingAssertions )
{}
virtual ~SectionStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
SectionStats( SectionStats const& ) = default; SectionStats( SectionStats const& ) = default;
SectionStats( SectionStats && ) = default; SectionStats( SectionStats && ) = default;
SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats const& ) = default;
SectionStats& operator = ( SectionStats && ) = default; SectionStats& operator = ( SectionStats && ) = default;
# endif virtual ~SectionStats() = default;
SectionInfo sectionInfo; SectionInfo sectionInfo;
Counts assertions; Counts assertions;
@@ -141,21 +110,13 @@ namespace Catch
Totals const& _totals, Totals const& _totals,
std::string const& _stdOut, std::string const& _stdOut,
std::string const& _stdErr, std::string const& _stdErr,
bool _aborting ) bool _aborting );
: testInfo( _testInfo ),
totals( _totals ),
stdOut( _stdOut ),
stdErr( _stdErr ),
aborting( _aborting )
{}
virtual ~TestCaseStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats const& ) = default;
TestCaseStats( TestCaseStats && ) = default; TestCaseStats( TestCaseStats && ) = default;
TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default;
TestCaseStats& operator = ( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default;
# endif virtual ~TestCaseStats() = default;
TestCaseInfo testInfo; TestCaseInfo testInfo;
Totals totals; Totals totals;
@@ -167,23 +128,14 @@ namespace Catch
struct TestGroupStats { struct TestGroupStats {
TestGroupStats( GroupInfo const& _groupInfo, TestGroupStats( GroupInfo const& _groupInfo,
Totals const& _totals, Totals const& _totals,
bool _aborting ) bool _aborting );
: groupInfo( _groupInfo ), TestGroupStats( GroupInfo const& _groupInfo );
totals( _totals ),
aborting( _aborting )
{}
TestGroupStats( GroupInfo const& _groupInfo )
: groupInfo( _groupInfo ),
aborting( false )
{}
virtual ~TestGroupStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats const& ) = default;
TestGroupStats( TestGroupStats && ) = default; TestGroupStats( TestGroupStats && ) = default;
TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default;
TestGroupStats& operator = ( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default;
# endif virtual ~TestGroupStats() = default;
GroupInfo groupInfo; GroupInfo groupInfo;
Totals totals; Totals totals;
@@ -193,38 +145,35 @@ namespace Catch
struct TestRunStats { struct TestRunStats {
TestRunStats( TestRunInfo const& _runInfo, TestRunStats( TestRunInfo const& _runInfo,
Totals const& _totals, Totals const& _totals,
bool _aborting ) bool _aborting );
: runInfo( _runInfo ),
totals( _totals ),
aborting( _aborting )
{}
virtual ~TestRunStats();
# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestRunStats( TestRunStats const& _other )
: runInfo( _other.runInfo ),
totals( _other.totals ),
aborting( _other.aborting )
{}
# else
TestRunStats( TestRunStats const& ) = default; TestRunStats( TestRunStats const& ) = default;
TestRunStats( TestRunStats && ) = default; TestRunStats( TestRunStats && ) = default;
TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats const& ) = default;
TestRunStats& operator = ( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats && ) = default;
# endif virtual ~TestRunStats() = default;
TestRunInfo runInfo; TestRunInfo runInfo;
Totals totals; Totals totals;
bool aborting; bool aborting;
}; };
struct BenchmarkInfo {
std::string name;
};
struct BenchmarkStats {
BenchmarkInfo info;
size_t iterations;
uint64_t elapsedTimeInNanoseconds;
};
class MultipleReporters; class MultipleReporters;
struct IStreamingReporter : IShared { struct IStreamingReporter {
virtual ~IStreamingReporter(); virtual ~IStreamingReporter() = default;
// Implementing class must also provide the following static method: // Implementing class must also provide the following static methods:
// static std::string getDescription(); // static std::string getDescription();
// static std::set<Verbosity> getSupportedVerbosities()
virtual ReporterPreferences getPreferences() const = 0; virtual ReporterPreferences getPreferences() const = 0;
@@ -236,11 +185,17 @@ namespace Catch
virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
// *** experimental ***
virtual void benchmarkStarting( BenchmarkInfo const& ) {}
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
// The return value indicates if the messages buffer should be cleared: // The return value indicates if the messages buffer should be cleared:
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
// *** experimental ***
virtual void benchmarkEnded( BenchmarkStats const& ) {}
virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
@@ -248,28 +203,29 @@ namespace Catch
virtual void skipTest( TestCaseInfo const& testInfo ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } virtual bool isMulti() const;
}; };
using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
struct IReporterFactory {
struct IReporterFactory : IShared { virtual ~IReporterFactory() = default;
virtual ~IReporterFactory(); virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
virtual std::string getDescription() const = 0; virtual std::string getDescription() const = 0;
}; };
using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
struct IReporterRegistry { struct IReporterRegistry {
typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap; using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
typedef std::vector<Ptr<IReporterFactory> > Listeners; using Listeners = std::vector<IReporterFactoryPtr>;
virtual ~IReporterRegistry(); virtual ~IReporterRegistry() = default;
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0; virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
virtual FactoryMap const& getFactories() const = 0; virtual FactoryMap const& getFactories() const = 0;
virtual Listeners const& getListeners() const = 0; virtual Listeners const& getListeners() const = 0;
}; };
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ); void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
} } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED

View File

@@ -8,14 +8,16 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
#include "catch_tag_alias.h" #include <string>
#include "catch_option.hpp"
namespace Catch { namespace Catch {
struct TagAlias;
struct ITagAliasRegistry { struct ITagAliasRegistry {
virtual ~ITagAliasRegistry(); virtual ~ITagAliasRegistry();
virtual Option<TagAlias> find( std::string const& alias ) const = 0; // Nullptr if not present
virtual TagAlias const* find( std::string const& alias ) const = 0;
virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
static ITagAliasRegistry const& get(); static ITagAliasRegistry const& get();

View File

@@ -8,20 +8,20 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
#include "catch_ptr.hpp"
#include <vector> #include <vector>
#include <memory>
namespace Catch { namespace Catch {
class TestSpec; class TestSpec;
struct ITestCase : IShared { struct ITestInvoker {
virtual void invoke () const = 0; virtual void invoke () const = 0;
protected: virtual ~ITestInvoker();
virtual ~ITestCase();
}; };
using ITestCasePtr = std::shared_ptr<ITestInvoker>;
class TestCase; class TestCase;
struct IConfig; struct IConfig;

View File

@@ -0,0 +1,33 @@
/*
* Created by Martin on 12/07/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)
*/
#include "catch_leak_detector.h"
namespace Catch {
#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
#include <crtdbg.h>
LeakDetector::LeakDetector() {
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
flag |= _CRTDBG_LEAK_CHECK_DF;
flag |= _CRTDBG_ALLOC_MEM_DF;
_CrtSetDbgFlag(flag);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
// Change this to leaking allocation's number to break there
_CrtSetBreakAlloc(-1);
}
#else
LeakDetector::LeakDetector(){}
#endif
}

View File

@@ -0,0 +1,17 @@
/*
* Created by Martin on 12/07/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_LEAK_DETECTOR_H_INCLUDED
#define TWOBLUECUBES_CATCH_LEAK_DETECTOR_H_INCLUDED
namespace Catch {
struct LeakDetector {
LeakDetector();
};
}
#endif // TWOBLUECUBES_CATCH_LEAK_DETECTOR_H_INCLUDED

View File

@@ -1,60 +0,0 @@
/*
* Created by Phil on 6th April 2013.
* Copyright 2013 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_LEGACY_REPORTER_ADAPTER_H_INCLUDED
#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
#include "catch_interfaces_reporter.h"
namespace Catch
{
// Deprecated
struct IReporter : IShared {
virtual ~IReporter();
virtual bool shouldRedirectStdout() const = 0;
virtual void StartTesting() = 0;
virtual void EndTesting( Totals const& totals ) = 0;
virtual void StartGroup( std::string const& groupName ) = 0;
virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
virtual void Aborted() = 0;
virtual void Result( AssertionResult const& result ) = 0;
};
class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
{
public:
LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
virtual ~LegacyReporterAdapter();
virtual ReporterPreferences getPreferences() const;
virtual void noMatchingTestCases( std::string const& );
virtual void testRunStarting( TestRunInfo const& );
virtual void testGroupStarting( GroupInfo const& groupInfo );
virtual void testCaseStarting( TestCaseInfo const& testInfo );
virtual void sectionStarting( SectionInfo const& sectionInfo );
virtual void assertionStarting( AssertionInfo const& );
virtual bool assertionEnded( AssertionStats const& assertionStats );
virtual void sectionEnded( SectionStats const& sectionStats );
virtual void testCaseEnded( TestCaseStats const& testCaseStats );
virtual void testGroupEnded( TestGroupStats const& testGroupStats );
virtual void testRunEnded( TestRunStats const& testRunStats );
virtual void skipTest( TestCaseInfo const& );
private:
Ptr<IReporter> m_legacyReporter;
};
}
#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED

View File

@@ -1,84 +0,0 @@
/*
* Created by Phil on 6th April 2013.
* Copyright 2013 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_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
#include "catch_legacy_reporter_adapter.h"
namespace Catch
{
LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
: m_legacyReporter( legacyReporter )
{}
LegacyReporterAdapter::~LegacyReporterAdapter() {}
ReporterPreferences LegacyReporterAdapter::getPreferences() const {
ReporterPreferences prefs;
prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
return prefs;
}
void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
m_legacyReporter->StartTesting();
}
void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
m_legacyReporter->StartGroup( groupInfo.name );
}
void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
m_legacyReporter->StartTestCase( testInfo );
}
void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
}
void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
// Not on legacy interface
}
bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
it != itEnd;
++it ) {
if( it->type == ResultWas::Info ) {
ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
rb << it->message;
rb.setResultType( ResultWas::Info );
AssertionResult result = rb.build();
m_legacyReporter->Result( result );
}
}
}
m_legacyReporter->Result( assertionStats.assertionResult );
return true;
}
void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
if( sectionStats.missingAssertions )
m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
}
void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
m_legacyReporter->EndTestCase
( testCaseStats.testInfo,
testCaseStats.totals,
testCaseStats.stdOut,
testCaseStats.stdErr );
}
void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
if( testGroupStats.aborting )
m_legacyReporter->Aborted();
m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
}
void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
m_legacyReporter->EndTesting( testRunStats.totals );
}
void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
}
}
#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED

View File

@@ -0,0 +1,164 @@
/*
* Created by Phil on 5/11/2010.
* Copyright 2010 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)
*/
#include "catch_list.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_interfaces_reporter.h"
#include "catch_interfaces_testcase.h"
#include "catch_text.h"
#include "catch_console_colour.hpp"
#include "catch_test_spec_parser.hpp"
#include "catch_tostring.h"
#include "catch_string_manip.h"
#include <limits>
#include <algorithm>
#include <iomanip>
namespace Catch {
std::size_t listTests( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() )
Catch::cout() << "Matching test cases:\n";
else {
Catch::cout() << "All available test cases:\n";
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
}
auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( auto const& testCaseInfo : matchedTestCases ) {
Colour::Code colour = testCaseInfo.isHidden()
? Colour::SecondaryText
: Colour::None;
Colour colourGuard( colour );
Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
if( config.verbosity() >= Verbosity::High ) {
Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;
std::string description = testCaseInfo.description;
if( description.empty() )
description = "(NO DESCRIPTION)";
Catch::cout() << Column( description ).indent(4) << std::endl;
}
if( !testCaseInfo.tags.empty() )
Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
}
if( !config.testSpec().hasFilters() )
Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
else
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
return matchedTestCases.size();
}
std::size_t listTestsNamesOnly( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( !config.testSpec().hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
std::size_t matchedTests = 0;
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( auto const& testCaseInfo : matchedTestCases ) {
matchedTests++;
if( startsWith( testCaseInfo.name, '#' ) )
Catch::cout() << '"' << testCaseInfo.name << '"';
else
Catch::cout() << testCaseInfo.name;
if ( config.verbosity() >= Verbosity::High )
Catch::cout() << "\t@" << testCaseInfo.lineInfo;
Catch::cout() << std::endl;
}
return matchedTests;
}
void TagInfo::add( std::string const& spelling ) {
++count;
spellings.insert( spelling );
}
std::string TagInfo::all() const {
std::string out;
for( auto const& spelling : spellings )
out += "[" + spelling + "]";
return out;
}
std::size_t listTags( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() )
Catch::cout() << "Tags for matching test cases:\n";
else {
Catch::cout() << "All available tags:\n";
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
}
std::map<std::string, TagInfo> tagCounts;
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( auto const& testCase : matchedTestCases ) {
for( auto const& tagName : testCase.getTestCaseInfo().tags ) {
std::string lcaseTagName = toLower( tagName );
auto countIt = tagCounts.find( lcaseTagName );
if( countIt == tagCounts.end() )
countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
countIt->second.add( tagName );
}
}
for( auto const& tagCount : tagCounts ) {
std::ostringstream oss;
oss << " " << std::setw(2) << tagCount.second.count << " ";
auto wrapper = Column( tagCount.second.all() )
.initialIndent( 0 )
.indent( oss.str().size() )
.width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
Catch::cout() << oss.str() << wrapper << '\n';
}
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
return tagCounts.size();
}
std::size_t listReporters( Config const& /*config*/ ) {
Catch::cout() << "Available reporters:\n";
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
std::size_t maxNameLen = 0;
for( auto const& factoryKvp : factories )
maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
for( auto const& factoryKvp : factories ) {
Catch::cout()
<< Column( factoryKvp.first + ":" )
.indent(2)
.width( 5+maxNameLen )
+ Column( factoryKvp.second->getDescription() )
.initialIndent(0)
.indent(2)
.width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
<< "\n";
}
Catch::cout() << std::endl;
return factories.size();
}
Option<std::size_t> list( Config const& config ) {
Option<std::size_t> listedCount;
if( config.listTests() )
listedCount = listedCount.valueOr(0) + listTests( config );
if( config.listTestNamesOnly() )
listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
if( config.listTags() )
listedCount = listedCount.valueOr(0) + listTags( config );
if( config.listReporters() )
listedCount = listedCount.valueOr(0) + listReporters( config );
return listedCount;
}
} // end namespace Catch

View File

@@ -0,0 +1,38 @@
/*
* Created by Phil on 5/11/2010.
* Copyright 2010 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_LIST_H_INCLUDED
#define TWOBLUECUBES_CATCH_LIST_H_INCLUDED
#include "catch_option.hpp"
#include "catch_config.hpp"
#include <set>
namespace Catch {
std::size_t listTests( Config const& config );
std::size_t listTestsNamesOnly( Config const& config );
struct TagInfo {
void add( std::string const& spelling );
std::string all() const;
std::set<std::string> spellings;
std::size_t count = 0;
};
std::size_t listTags( Config const& config );
std::size_t listReporters( Config const& /*config*/ );
Option<std::size_t> list( Config const& config );
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_LIST_H_INCLUDED

View File

@@ -1,190 +0,0 @@
/*
* Created by Phil on 5/11/2010.
* Copyright 2010 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_LIST_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
#include "catch_commandline.hpp"
#include "catch_text.h"
#include "catch_console_colour.hpp"
#include "catch_interfaces_reporter.h"
#include "catch_test_spec_parser.hpp"
#include <limits>
#include <algorithm>
namespace Catch {
inline std::size_t listTests( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() )
Catch::cout() << "Matching test cases:\n";
else {
Catch::cout() << "All available test cases:\n";
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
}
std::size_t matchedTests = 0;
TextAttributes nameAttr, descAttr, tagsAttr;
nameAttr.setInitialIndent( 2 ).setIndent( 4 );
descAttr.setIndent( 4 );
tagsAttr.setIndent( 6 );
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();
Colour::Code colour = testCaseInfo.isHidden()
? Colour::SecondaryText
: Colour::None;
Colour colourGuard( colour );
Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
if( config.listExtraInfo() ) {
Catch::cout() << " " << testCaseInfo.lineInfo << std::endl;
std::string description = testCaseInfo.description;
if( description.empty() )
description = "(NO DESCRIPTION)";
Catch::cout() << Text( description, descAttr ) << std::endl;
}
if( !testCaseInfo.tags.empty() )
Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
}
if( !config.testSpec().hasFilters() )
Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
else
Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
return matchedTests;
}
inline std::size_t listTestsNamesOnly( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( !config.testSpec().hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
std::size_t matchedTests = 0;
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();
if( startsWith( testCaseInfo.name, '#' ) )
Catch::cout() << '"' << testCaseInfo.name << '"';
else
Catch::cout() << testCaseInfo.name;
if ( config.listExtraInfo() )
Catch::cout() << "\t@" << testCaseInfo.lineInfo;
Catch::cout() << std::endl;
}
return matchedTests;
}
struct TagInfo {
TagInfo() : count ( 0 ) {}
void add( std::string const& spelling ) {
++count;
spellings.insert( spelling );
}
std::string all() const {
std::string out;
for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
it != itEnd;
++it )
out += "[" + *it + "]";
return out;
}
std::set<std::string> spellings;
std::size_t count;
};
inline std::size_t listTags( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() )
Catch::cout() << "Tags for matching test cases:\n";
else {
Catch::cout() << "All available tags:\n";
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
}
std::map<std::string, TagInfo> tagCounts;
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
tagItEnd = it->getTestCaseInfo().tags.end();
tagIt != tagItEnd;
++tagIt ) {
std::string tagName = *tagIt;
std::string lcaseTagName = toLower( tagName );
std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
if( countIt == tagCounts.end() )
countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
countIt->second.add( tagName );
}
}
for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
countItEnd = tagCounts.end();
countIt != countItEnd;
++countIt ) {
std::ostringstream oss;
oss << " " << std::setw(2) << countIt->second.count << " ";
Text wrapper( countIt->second.all(), TextAttributes()
.setInitialIndent( 0 )
.setIndent( oss.str().size() )
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
Catch::cout() << oss.str() << wrapper << '\n';
}
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
return tagCounts.size();
}
inline std::size_t listReporters( Config const& /*config*/ ) {
Catch::cout() << "Available reporters:\n";
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
std::size_t maxNameLen = 0;
for(it = itBegin; it != itEnd; ++it )
maxNameLen = (std::max)( maxNameLen, it->first.size() );
for(it = itBegin; it != itEnd; ++it ) {
Text wrapper( it->second->getDescription(), TextAttributes()
.setInitialIndent( 0 )
.setIndent( 7+maxNameLen )
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
Catch::cout() << " "
<< it->first
<< ':'
<< std::string( maxNameLen - it->first.size() + 2, ' ' )
<< wrapper << '\n';
}
Catch::cout() << std::endl;
return factories.size();
}
inline Option<std::size_t> list( Config const& config ) {
Option<std::size_t> listedCount;
if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) )
listedCount = listedCount.valueOr(0) + listTests( config );
if( config.listTestNamesOnly() )
listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
if( config.listTags() )
listedCount = listedCount.valueOr(0) + listTags( config );
if( config.listReporters() )
listedCount = listedCount.valueOr(0) + listReporters( config );
return listedCount;
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED

View File

@@ -0,0 +1,26 @@
/*
* Created by Phil Nash on 19/07/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)
*/
#include "catch_matchers.hpp"
namespace Catch {
namespace Matchers {
namespace Impl {
std::string MatcherUntypedBase::toString() const {
if( m_cachedToString.empty() )
m_cachedToString = describe();
return m_cachedToString;
}
} // namespace Impl
} // namespace Matchers
using namespace Matchers;
using Matchers::Impl::MatcherBase;
} // namespace Catch

View File

@@ -10,6 +10,9 @@
#include "catch_common.h" #include "catch_common.h"
#include <string>
#include <vector>
namespace Catch { namespace Catch {
namespace Matchers { namespace Matchers {
namespace Impl { namespace Impl {
@@ -20,18 +23,15 @@ namespace Matchers {
class MatcherUntypedBase { class MatcherUntypedBase {
public: public:
std::string toString() const { MatcherUntypedBase() = default;
if( m_cachedToString.empty() ) MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
m_cachedToString = describe(); MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
return m_cachedToString; std::string toString() const;
}
protected: protected:
virtual ~MatcherUntypedBase(); virtual ~MatcherUntypedBase() = default;
virtual std::string describe() const = 0; virtual std::string describe() const = 0;
mutable std::string m_cachedToString; mutable std::string m_cachedToString;
private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
}; };
template<typename ObjectT> template<typename ObjectT>
@@ -54,21 +54,24 @@ namespace Matchers {
template<typename ArgT> template<typename ArgT>
struct MatchAllOf : MatcherBase<ArgT> { struct MatchAllOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { bool match( ArgT const& arg ) const override {
for( std::size_t i = 0; i < m_matchers.size(); ++i ) { for( auto matcher : m_matchers ) {
if (!m_matchers[i]->match(arg)) if (!matcher->match(arg))
return false; return false;
} }
return true; return true;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
std::string description; std::string description;
description.reserve( 4 + m_matchers.size()*32 ); description.reserve( 4 + m_matchers.size()*32 );
description += "( "; description += "( ";
for( std::size_t i = 0; i < m_matchers.size(); ++i ) { bool first = true;
if( i != 0 ) for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " and "; description += " and ";
description += m_matchers[i]->toString(); description += matcher->toString();
} }
description += " )"; description += " )";
return description; return description;
@@ -84,21 +87,24 @@ namespace Matchers {
template<typename ArgT> template<typename ArgT>
struct MatchAnyOf : MatcherBase<ArgT> { struct MatchAnyOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { bool match( ArgT const& arg ) const override {
for( std::size_t i = 0; i < m_matchers.size(); ++i ) { for( auto matcher : m_matchers ) {
if (m_matchers[i]->match(arg)) if (matcher->match(arg))
return true; return true;
} }
return false; return false;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
std::string description; std::string description;
description.reserve( 4 + m_matchers.size()*32 ); description.reserve( 4 + m_matchers.size()*32 );
description += "( "; description += "( ";
for( std::size_t i = 0; i < m_matchers.size(); ++i ) { bool first = true;
if( i != 0 ) for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " or "; description += " or ";
description += m_matchers[i]->toString(); description += matcher->toString();
} }
description += " )"; description += " )";
return description; return description;
@@ -117,11 +123,11 @@ namespace Matchers {
MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { bool match( ArgT const& arg ) const override {
return !m_underlyingMatcher.match( arg ); return !m_underlyingMatcher.match( arg );
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "not " + m_underlyingMatcher.toString(); return "not " + m_underlyingMatcher.toString();
} }
MatcherBase<ArgT> const& m_underlyingMatcher; MatcherBase<ArgT> const& m_underlyingMatcher;

View File

@@ -6,7 +6,8 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#include "catch_matchers.hpp" #include "catch_matchers_string.h"
#include "catch_string_manip.h"
namespace Catch { namespace Catch {
namespace Matchers { namespace Matchers {

View File

@@ -10,6 +10,8 @@
#include "catch_matchers.hpp" #include "catch_matchers.hpp"
#include <string>
namespace Catch { namespace Catch {
namespace Matchers { namespace Matchers {
@@ -27,7 +29,7 @@ namespace Matchers {
struct StringMatcherBase : MatcherBase<std::string> { struct StringMatcherBase : MatcherBase<std::string> {
StringMatcherBase( std::string const& operation, CasedString const& comparator ); StringMatcherBase( std::string const& operation, CasedString const& comparator );
virtual std::string describe() const CATCH_OVERRIDE; std::string describe() const override;
CasedString m_comparator; CasedString m_comparator;
std::string m_operation; std::string m_operation;
@@ -35,19 +37,19 @@ namespace Matchers {
struct EqualsMatcher : StringMatcherBase { struct EqualsMatcher : StringMatcherBase {
EqualsMatcher( CasedString const& comparator ); EqualsMatcher( CasedString const& comparator );
virtual bool match( std::string const& source ) const CATCH_OVERRIDE; bool match( std::string const& source ) const override;
}; };
struct ContainsMatcher : StringMatcherBase { struct ContainsMatcher : StringMatcherBase {
ContainsMatcher( CasedString const& comparator ); ContainsMatcher( CasedString const& comparator );
virtual bool match( std::string const& source ) const CATCH_OVERRIDE; bool match( std::string const& source ) const override;
}; };
struct StartsWithMatcher : StringMatcherBase { struct StartsWithMatcher : StringMatcherBase {
StartsWithMatcher( CasedString const& comparator ); StartsWithMatcher( CasedString const& comparator );
virtual bool match( std::string const& source ) const CATCH_OVERRIDE; bool match( std::string const& source ) const override;
}; };
struct EndsWithMatcher : StringMatcherBase { struct EndsWithMatcher : StringMatcherBase {
EndsWithMatcher( CasedString const& comparator ); EndsWithMatcher( CasedString const& comparator );
virtual bool match( std::string const& source ) const CATCH_OVERRIDE; bool match( std::string const& source ) const override;
}; };
} // namespace StdString } // namespace StdString

View File

@@ -20,12 +20,17 @@ namespace Matchers {
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
bool match(std::vector<T> const &v) const CATCH_OVERRIDE { bool match(std::vector<T> const &v) const override {
return std::find(v.begin(), v.end(), m_comparator) != v.end(); for (auto const& el : v) {
if (el == m_comparator) {
return true;
}
}
return false;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "Contains: " + Catch::toString( m_comparator ); return "Contains: " + ::Catch::Detail::stringify( m_comparator );
} }
T const& m_comparator; T const& m_comparator;
@@ -36,17 +41,26 @@ namespace Matchers {
ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const CATCH_OVERRIDE { bool match(std::vector<T> const &v) const override {
// !TBD: see note in EqualsMatcher // !TBD: see note in EqualsMatcher
if (m_comparator.size() > v.size()) if (m_comparator.size() > v.size())
return false; return false;
for (size_t i = 0; i < m_comparator.size(); ++i) for (auto const& comparator : m_comparator) {
if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) auto present = false;
for (const auto& el : v) {
if (el == comparator) {
present = true;
break;
}
}
if (!present) {
return false; return false;
}
}
return true; return true;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "Contains: " + Catch::toString( m_comparator ); return "Contains: " + ::Catch::Detail::stringify( m_comparator );
} }
std::vector<T> const& m_comparator; std::vector<T> const& m_comparator;
@@ -57,7 +71,7 @@ namespace Matchers {
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const CATCH_OVERRIDE { bool match(std::vector<T> const &v) const override {
// !TBD: This currently works if all elements can be compared using != // !TBD: This currently works if all elements can be compared using !=
// - a more general approach would be via a compare template that defaults // - a more general approach would be via a compare template that defaults
// to using !=. but could be specialised for, e.g. std::vector<T> etc // to using !=. but could be specialised for, e.g. std::vector<T> etc
@@ -69,8 +83,8 @@ namespace Matchers {
return false; return false;
return true; return true;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "Equals: " + Catch::toString( m_comparator ); return "Equals: " + ::Catch::Detail::stringify( m_comparator );
} }
std::vector<T> const& m_comparator; std::vector<T> const& m_comparator;
}; };

View File

@@ -5,10 +5,9 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying * 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) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
#include "catch_message.h" #include "catch_message.h"
#include "catch_interfaces_capture.h"
namespace Catch { namespace Catch {
@@ -21,36 +20,40 @@ namespace Catch {
sequence( ++globalCount ) sequence( ++globalCount )
{} {}
bool MessageInfo::operator==( MessageInfo const& other ) const {
return sequence == other.sequence;
}
bool MessageInfo::operator<( MessageInfo const& other ) const {
return sequence < other.sequence;
}
// This may need protecting if threading support is added // This may need protecting if threading support is added
unsigned int MessageInfo::globalCount = 0; unsigned int MessageInfo::globalCount = 0;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
Catch::MessageBuilder::MessageBuilder( std::string const& macroName,
SourceLineInfo const& lineInfo,
ResultWas::OfType type )
:m_info(macroName, lineInfo, type) {}
////////////////////////////////////////////////////////////////////////////
ScopedMessage::ScopedMessage( MessageBuilder const& builder ) ScopedMessage::ScopedMessage( MessageBuilder const& builder )
: m_info( builder.m_info ) : m_info( builder.m_info )
{ {
m_info.message = builder.m_stream.str(); m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info ); getResultCapture().pushScopedMessage( m_info );
} }
ScopedMessage::ScopedMessage( ScopedMessage const& other )
: m_info( other.m_info )
{}
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
#endif
ScopedMessage::~ScopedMessage() { ScopedMessage::~ScopedMessage() {
if ( !std::uncaught_exception() ){ if ( !std::uncaught_exception() ){
getResultCapture().popScopedMessage(m_info); getResultCapture().popScopedMessage(m_info);
} }
} }
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED

View File

@@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
#include <string> #include <string>
#include <sstream>
#include "catch_result_type.h" #include "catch_result_type.h"
#include "catch_common.h" #include "catch_common.h"
@@ -25,22 +26,28 @@ namespace Catch {
std::string message; std::string message;
unsigned int sequence; unsigned int sequence;
bool operator == ( MessageInfo const& other ) const { bool operator == ( MessageInfo const& other ) const;
return sequence == other.sequence; bool operator < ( MessageInfo const& other ) const;
}
bool operator < ( MessageInfo const& other ) const {
return sequence < other.sequence;
}
private: private:
static unsigned int globalCount; static unsigned int globalCount;
}; };
struct MessageBuilder { struct MessageStream {
template<typename T>
MessageStream& operator << ( T const& value ) {
m_stream << value;
return *this;
}
// !TBD reuse a global/ thread-local stream
std::ostringstream m_stream;
};
struct MessageBuilder : MessageStream {
MessageBuilder( std::string const& macroName, MessageBuilder( std::string const& macroName,
SourceLineInfo const& lineInfo, SourceLineInfo const& lineInfo,
ResultWas::OfType type ) ResultWas::OfType type );
: m_info( macroName, lineInfo, type )
{}
template<typename T> template<typename T>
MessageBuilder& operator << ( T const& value ) { MessageBuilder& operator << ( T const& value ) {
@@ -49,13 +56,11 @@ namespace Catch {
} }
MessageInfo m_info; MessageInfo m_info;
std::ostringstream m_stream;
}; };
class ScopedMessage { class ScopedMessage {
public: public:
ScopedMessage( MessageBuilder const& builder ); ScopedMessage( MessageBuilder const& builder );
ScopedMessage( ScopedMessage const& other );
~ScopedMessage(); ~ScopedMessage();
MessageInfo m_info; MessageInfo m_info;

View File

@@ -5,26 +5,21 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying * 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) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
#include "catch_notimplemented_exception.h" #include "catch_notimplemented_exception.h"
#include <sstream> #include <sstream>
namespace Catch { namespace Catch {
NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) {
: m_lineInfo( lineInfo ) {
std::ostringstream oss; std::ostringstream oss;
oss << lineInfo << ": function "; oss << lineInfo << ": function ";
oss << "not implemented"; oss << "not implemented";
m_what = oss.str(); m_what = oss.str();
} }
const char* NotImplementedException::what() const CATCH_NOEXCEPT { const char* NotImplementedException::what() const noexcept {
return m_what.c_str(); return m_what.c_str();
} }
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED

View File

@@ -10,6 +10,8 @@
#include "catch_common.h" #include "catch_common.h"
#include <exception>
namespace Catch { namespace Catch {
class NotImplementedException : public std::exception class NotImplementedException : public std::exception
@@ -17,13 +19,12 @@ namespace Catch {
public: public:
NotImplementedException( SourceLineInfo const& lineInfo ); NotImplementedException( SourceLineInfo const& lineInfo );
virtual ~NotImplementedException() CATCH_NOEXCEPT {} virtual ~NotImplementedException() noexcept = default;
virtual const char* what() const CATCH_NOEXCEPT; virtual const char* what() const noexcept override;
private: private:
std::string m_what; std::string m_what;
SourceLineInfo m_lineInfo;
}; };
} // end namespace Catch } // end namespace Catch

View File

@@ -33,7 +33,7 @@
namespace Catch { namespace Catch {
class OcMethod : public SharedImpl<ITestCase> { class OcMethod : public ITestInvoker {
public: public:
OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
@@ -72,7 +72,7 @@ namespace Catch {
inline size_t registerTestMethods() { inline size_t registerTestMethods() {
size_t noTestMethods = 0; size_t noTestMethods = 0;
int noClasses = objc_getClassList( CATCH_NULL, 0 ); int noClasses = objc_getClassList( nullptr, 0 );
Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
objc_getClassList( classes, noClasses ); objc_getClassList( classes, noClasses );
@@ -101,6 +101,8 @@ namespace Catch {
return noTestMethods; return noTestMethods;
} }
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
namespace Matchers { namespace Matchers {
namespace Impl { namespace Impl {
namespace NSStringMatchers { namespace NSStringMatchers {
@@ -112,7 +114,7 @@ namespace Catch {
arcSafeRelease( m_substr ); arcSafeRelease( m_substr );
} }
virtual bool match( NSString* arg ) const CATCH_OVERRIDE { bool match( NSString* arg ) const override {
return false; return false;
} }
@@ -122,12 +124,12 @@ namespace Catch {
struct Equals : StringHolder { struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){} Equals( NSString* substr ) : StringHolder( substr ){}
virtual bool match( NSString* str ) const CATCH_OVERRIDE { bool match( NSString* str ) const override {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr]; [str isEqualToString:m_substr];
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "equals string: " + Catch::toString( m_substr ); return "equals string: " + Catch::toString( m_substr );
} }
}; };
@@ -135,12 +137,12 @@ namespace Catch {
struct Contains : StringHolder { struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){} Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( NSString* str ) const { bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound; [str rangeOfString:m_substr].location != NSNotFound;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "contains string: " + Catch::toString( m_substr ); return "contains string: " + Catch::toString( m_substr );
} }
}; };
@@ -148,24 +150,24 @@ namespace Catch {
struct StartsWith : StringHolder { struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){} StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( NSString* str ) const { bool match( NSString* str ) const override {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0; [str rangeOfString:m_substr].location == 0;
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "starts with: " + Catch::toString( m_substr ); return "starts with: " + Catch::toString( m_substr );
} }
}; };
struct EndsWith : StringHolder { struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){} EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( NSString* str ) const { bool match( NSString* str ) const override {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length]; [str rangeOfString:m_substr].location == [str length] - [m_substr length];
} }
virtual std::string describe() const CATCH_OVERRIDE { std::string describe() const override {
return "ends with: " + Catch::toString( m_substr ); return "ends with: " + Catch::toString( m_substr );
} }
}; };
@@ -189,6 +191,8 @@ namespace Catch {
using namespace Matchers; using namespace Matchers;
#endif // CATCH_CONFIG_DISABLE_MATCHERS
} // namespace Catch } // namespace Catch
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@@ -8,20 +8,18 @@
#ifndef TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
#include "catch_common.h"
namespace Catch { namespace Catch {
// An optional type // An optional type
template<typename T> template<typename T>
class Option { class Option {
public: public:
Option() : nullableValue( CATCH_NULL ) {} Option() : nullableValue( nullptr ) {}
Option( T const& _value ) Option( T const& _value )
: nullableValue( new( storage ) T( _value ) ) : nullableValue( new( storage ) T( _value ) )
{} {}
Option( Option const& _other ) Option( Option const& _other )
: nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
{} {}
~Option() { ~Option() {
@@ -45,7 +43,7 @@ namespace Catch {
void reset() { void reset() {
if( nullableValue ) if( nullableValue )
nullableValue->~T(); nullableValue->~T();
nullableValue = CATCH_NULL; nullableValue = nullptr;
} }
T& operator*() { return *nullableValue; } T& operator*() { return *nullableValue; }
@@ -57,27 +55,17 @@ namespace Catch {
return nullableValue ? *nullableValue : defaultValue; return nullableValue ? *nullableValue : defaultValue;
} }
bool some() const { return nullableValue != CATCH_NULL; } bool some() const { return nullableValue != nullptr; }
bool none() const { return nullableValue == CATCH_NULL; } bool none() const { return nullableValue == nullptr; }
bool operator !() const { return nullableValue == CATCH_NULL; } bool operator !() const { return nullableValue == nullptr; }
operator SafeBool::type() const { explicit operator bool() const {
return SafeBool::makeSafe( some() ); return some();
} }
private: private:
T *nullableValue; T *nullableValue;
union { alignas(alignof(T)) char storage[sizeof(T)];
char storage[sizeof(T)];
// These are here to force alignment for the storage
long double dummy1;
void (*dummy2)();
long double dummy3;
#ifdef CATCH_CONFIG_CPP11_LONG_LONG
long long dummy4;
#endif
};
}; };
} // end namespace Catch } // end namespace Catch

View File

@@ -9,20 +9,19 @@
#ifndef TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #ifdef __APPLE__
# include <TargetConditionals.h>
# if TARGET_OS_MAC == 1
# define CATCH_PLATFORM_MAC # define CATCH_PLATFORM_MAC
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) # elif TARGET_OS_IPHONE == 1
# define CATCH_PLATFORM_IPHONE # define CATCH_PLATFORM_IPHONE
# endif
#elif defined(linux) || defined(__linux) || defined(__linux__) #elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX # define CATCH_PLATFORM_LINUX
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) #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
#endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED

View File

@@ -1,93 +0,0 @@
/*
* Created by Phil on 02/05/2012.
* Copyright 2012 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_PTR_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
#include "catch_common.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif
namespace Catch {
// An intrusive reference counting smart pointer.
// T must implement addRef() and release() methods
// typically implementing the IShared interface
template<typename T>
class Ptr {
public:
Ptr() : m_p( CATCH_NULL ){}
Ptr( T* p ) : m_p( p ){
if( m_p )
m_p->addRef();
}
Ptr( Ptr const& other ) : m_p( other.m_p ){
if( m_p )
m_p->addRef();
}
~Ptr(){
if( m_p )
m_p->release();
}
void reset() {
if( m_p )
m_p->release();
m_p = CATCH_NULL;
}
Ptr& operator = ( T* p ){
Ptr temp( p );
swap( temp );
return *this;
}
Ptr& operator = ( Ptr const& other ){
Ptr temp( other );
swap( temp );
return *this;
}
void swap( Ptr& other ) { std::swap( m_p, other.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; }
operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
private:
T* m_p;
};
struct IShared : NonCopyable {
virtual ~IShared();
virtual void addRef() const = 0;
virtual void release() const = 0;
};
template<typename T = IShared>
struct SharedImpl : T {
SharedImpl() : m_rc( 0 ){}
virtual void addRef() const {
++m_rc;
}
virtual void release() const {
if( --m_rc == 0 )
delete this;
}
mutable unsigned int m_rc;
};
} // end namespace Catch
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif // TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED

View File

@@ -5,69 +5,72 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying * 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) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
#include "catch_test_case_registry_impl.hpp" #include "catch_test_case_registry_impl.hpp"
#include "catch_reporter_registry.hpp" #include "catch_reporter_registry.hpp"
#include "catch_exception_translator_registry.hpp" #include "catch_exception_translator_registry.h"
#include "catch_tag_alias_registry.h" #include "catch_tag_alias_registry.h"
#include "catch_startup_exception_registry.h"
namespace Catch { namespace Catch {
namespace { namespace {
class RegistryHub : public IRegistryHub, public IMutableRegistryHub { class RegistryHub : public IRegistryHub, public IMutableRegistryHub,
private NonCopyable {
RegistryHub( RegistryHub const& );
void operator=( RegistryHub const& );
public: // IRegistryHub public: // IRegistryHub
RegistryHub() { RegistryHub() {
} }
virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { IReporterRegistry const& getReporterRegistry() const override {
return m_reporterRegistry; return m_reporterRegistry;
} }
virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { ITestCaseRegistry const& getTestCaseRegistry() const override {
return m_testCaseRegistry; return m_testCaseRegistry;
} }
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override {
return m_exceptionTranslatorRegistry; return m_exceptionTranslatorRegistry;
} }
virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { ITagAliasRegistry const& getTagAliasRegistry() const override {
return m_tagAliasRegistry; return m_tagAliasRegistry;
} }
StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
return m_exceptionRegistry;
}
public: // IMutableRegistryHub public: // IMutableRegistryHub
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {
m_reporterRegistry.registerReporter( name, factory ); m_reporterRegistry.registerReporter( name, factory );
} }
virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { void registerListener( IReporterFactoryPtr const& factory ) override {
m_reporterRegistry.registerListener( factory ); m_reporterRegistry.registerListener( factory );
} }
virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { void registerTest( TestCase const& testInfo ) override {
m_testCaseRegistry.registerTest( testInfo ); m_testCaseRegistry.registerTest( testInfo );
} }
virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { void registerTranslator( const IExceptionTranslator* translator ) override {
m_exceptionTranslatorRegistry.registerTranslator( translator ); m_exceptionTranslatorRegistry.registerTranslator( translator );
} }
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
m_tagAliasRegistry.add( alias, tag, lineInfo ); m_tagAliasRegistry.add( alias, tag, lineInfo );
} }
void registerStartupException() noexcept override {
m_exceptionRegistry.add(std::current_exception());
}
private: private:
TestRegistry m_testCaseRegistry; TestRegistry m_testCaseRegistry;
ReporterRegistry m_reporterRegistry; ReporterRegistry m_reporterRegistry;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
TagAliasRegistry m_tagAliasRegistry; TagAliasRegistry m_tagAliasRegistry;
StartupExceptionRegistry m_exceptionRegistry;
}; };
// Single, global, instance // Single, global, instance
inline RegistryHub*& getTheRegistryHub() { RegistryHub*& getTheRegistryHub() {
static RegistryHub* theRegistryHub = CATCH_NULL; static RegistryHub* theRegistryHub = nullptr;
if( !theRegistryHub ) if( !theRegistryHub )
theRegistryHub = new RegistryHub(); theRegistryHub = new RegistryHub();
return theRegistryHub; return theRegistryHub;
@@ -82,7 +85,7 @@ namespace Catch {
} }
void cleanUp() { void cleanUp() {
delete getTheRegistryHub(); delete getTheRegistryHub();
getTheRegistryHub() = CATCH_NULL; getTheRegistryHub() = nullptr;
cleanUpContext(); cleanUpContext();
} }
std::string translateActiveException() { std::string translateActiveException() {
@@ -91,5 +94,3 @@ namespace Catch {
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED

View File

@@ -1,3 +1,4 @@
/* /*
* Created by Phil on 31/12/2010. * Created by Phil on 31/12/2010.
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved. * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
@@ -9,51 +10,19 @@
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
#include "catch_legacy_reporter_adapter.h"
namespace Catch { namespace Catch {
template<typename T>
class LegacyReporterRegistrar {
class ReporterFactory : public IReporterFactory {
virtual IStreamingReporter* create( ReporterConfig const& config ) const {
return new LegacyReporterAdapter( new T( config ) );
}
virtual std::string getDescription() const {
return T::getDescription();
}
};
public:
LegacyReporterRegistrar( std::string const& name ) {
getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
}
};
template<typename T> template<typename T>
class ReporterRegistrar { class ReporterRegistrar {
class ReporterFactory : public SharedImpl<IReporterFactory> { class ReporterFactory : public IReporterFactory {
// *** Please Note ***: virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
// - If you end up here looking at a compiler error because it's trying to register return std::unique_ptr<T>( new T( config ) );
// your custom reporter class be aware that the native reporter interface has changed
// to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
// an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
// However please consider updating to the new interface as the old one is now
// deprecated and will probably be removed quite soon!
// Please contact me via github if you have any questions at all about this.
// In fact, ideally, please contact me anyway to let me know you've hit this - as I have
// no idea who is actually using custom reporters at all (possibly no-one!).
// The new interface is designed to minimise exposure to interface changes in the future.
virtual IStreamingReporter* create( ReporterConfig const& config ) const {
return new T( config );
} }
virtual std::string getDescription() const { virtual std::string getDescription() const override {
return T::getDescription(); return T::getDescription();
} }
}; };
@@ -61,19 +30,19 @@ namespace Catch {
public: public:
ReporterRegistrar( std::string const& name ) { ReporterRegistrar( std::string const& name ) {
getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
} }
}; };
template<typename T> template<typename T>
class ListenerRegistrar { class ListenerRegistrar {
class ListenerFactory : public SharedImpl<IReporterFactory> { class ListenerFactory : public IReporterFactory {
virtual IStreamingReporter* create( ReporterConfig const& config ) const { virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return new T( config ); return std::unique_ptr<T>( new T( config ) );
} }
virtual std::string getDescription() const { virtual std::string getDescription() const override {
return std::string(); return std::string();
} }
}; };
@@ -81,21 +50,14 @@ namespace Catch {
public: public:
ListenerRegistrar() { ListenerRegistrar() {
getMutableRegistryHub().registerListener( new ListenerFactory() ); getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );
} }
}; };
} }
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ #define CATCH_REGISTER_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 ); } namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
// Deprecated - use the form without INTERNAL_
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
#define CATCH_REGISTER_LISTENER( listenerType ) \ #define CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }

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