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
205 changed files with 20921 additions and 23366 deletions

View File

@@ -5,19 +5,6 @@ matrix:
include:
# 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
compiler: clang
addons: &clang35
@@ -75,34 +62,6 @@ matrix:
# 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
compiler: gcc
addons: &gcc48
@@ -191,7 +150,7 @@ matrix:
addons: *gcc6
env: COMPILER='g++-6' BUILD_TYPE='Debug' CPP14=1
# 4b/ Linux C++14 Clang builds
# # 4b/ Linux C++14 Clang builds
# - os: linux
# compiler: clang
# addons: *clang38

View File

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

46
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@philnash.me. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,15 +1,18 @@
![catch logo](catch-logo-small.png)
[![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://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/y7uyNvTCS263P5VG)
[![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/catch2?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/catch2)
<a href="https://github.com/philsquared/Catch/releases/download/v1.9.6/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?
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
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)
* 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)
## 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:
- Visual Studio 2017
- Visual Studio 2015
- Visual Studio 2013
environment:
matrix:

View File

@@ -4,7 +4,7 @@ from conans import ConanFile
class CatchConan(ConanFile):
name = "Catch"
version = "1.9.6"
version = "2.0.0-develop.2"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared"
generators = "cmake"

View File

@@ -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
* **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
* **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_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
REQUIRE_NOTHROW([&](){
@@ -122,6 +127,8 @@ REQUIRE_NOTHROW([&](){
}());
```
## Matcher expressions
To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md).

View File

@@ -27,6 +27,9 @@ Click one of the followings links to take you straight to that option - or scrol
<a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br />
<a href="#order"> ` --order`</a><br />
<a href="#rng-seed"> ` --rng-seed`</a><br />
<a href="#libidentify"> ` --libidentify`</a><br />
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
</br>
@@ -213,6 +216,27 @@ Alternatively if the keyword ```time``` is provided then the result of calling `
In either case the actual value for the seed is printed as part of Catch's output so if an issue is discovered that is sensitive to test ordering the ordering can be reproduced - even if it was originally seeded from ```std::time(0)```.
<a id="libidentify"></a>
## Identify framework and version according to the libIdentify standard
<pre>--libidentify</pre>
See [The LibIdentify repo for more information and examples](https://github.com/janwilmans/LibIdentify).
<a id="wait-for-keypress"></a>
## Wait for key before continuing
<pre>--wait-for-keypress &lt;start|exit|both&gt;</pre>
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.
<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>
## Usage
<pre>-h, -?, --help</pre>

View File

@@ -43,61 +43,22 @@ By default a console width of 80 is assumed but this can be controlled by defini
CATCH_CONFIG_NOSTDOUT
Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them from ```Catch::cout()``` and ```Catch::cerr()``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly but gets them from ```Catch::cout()```, ```Catch::cerr()``` and ```Catch::clog``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
std::ostream& cout();
std::ostream& cerr();
std::ostream& clog();
This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems.
This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
# 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
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows
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_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
@@ -107,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.
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`
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:
@@ -116,6 +77,13 @@ 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_DISABLE_MATCHERS`
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
On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros:

View File

@@ -25,6 +25,9 @@ The core part of the Chakra Javascript engine that powers Microsoft Edge
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
### [Clara](https://github.com/philsquared/Clara)
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
The next-generation core storage and query engine for Couchbase Lite/
@@ -52,6 +55,9 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
A library of algorithms for values-distributed-in-time
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
A small, single-header-only, library for wrapping and composing columns of text
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
A thread safe header only mocking framework for C++14
@@ -63,6 +69,9 @@ A simple header-only C++ argument parser library.
### [ArangoDB](https://github.com/arangodb/arangodb)
ArangoDB is a native multi-model database with flexible data models for documents, graphs, and key-values.
### [Giada - Your Hardcore Loop Machine](https://github.com/monocasual/giada)
Minimal, open-source and cross-platform audio tool for live music production.
### [MAME](https://github.com/mamedev/mame)
MAME originally stood for Multiple Arcade Machine Emulator

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
#include "catch.hpp"
int main( int argc, char* argv[] )
{
int main( int argc, char* argv[] ) {
// global setup...
int result = Catch::Session().run( argc, argv );
// global clean-up...
return ( result < 0xff ? result : 0xff );
return result;
}
```
@@ -42,7 +41,22 @@ int main( int argc, char* argv[] )
// writing to session.configData() here sets defaults
// 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 );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
@@ -52,10 +66,10 @@ int main( int argc, char* argv[] )
// only do this if you know you need to
int numFailed = session.run();
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
return ( numFailed < 0xff ? numFailed : 0xff );
// numFailed is clamped to 255 as some unices only use the lower 8 bits.
// This clamping has already been applied, so just return it here
// You can also do any post run clean-up here
return numFailed;
}
```

View File

@@ -16,7 +16,7 @@ There should be no differences, as Approval tests should be updated when changes
### Incrementing version number
Catch uses a variant of [semantic versioning](http://semver.org/), with breaking API changes (and thus major version increments) being very rare. Thus, the release will usually increment the patch version, when it only contains couple of bugfixes, or minor version, when it contains new functionality, or larger changes in implementation of current functionality.
Catch uses a variant of [semantic versioning](http://semver.org/), with breaking API changes (and thus major version increments) being very rare. Thus, the release will usually increment the patch version, when it only contains couple of bugfixes, or minor version, when it contains new functionality, or larger changes in implementation of current functionality.
After deciding which part of version number should be incremented, you can use one of the `*Release.py` scripts to perform the required changes to Catch.
@@ -33,7 +33,7 @@ Once a release is ready, release notes need to be written. They should summarize
### Commit and push update to GitHub
After version number is incremented, single-include header is regenerated and release notes are updated, changes should be commited and pushed to GitHub.
After version number is incremented, single-include header is regenerated and release notes are updated, changes should be commited and pushed to GitHub.
### Release on GitHub

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.
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.
Use this when building as part of a TeamCity build to see results as they happen.

View File

@@ -1,7 +1,7 @@
# String conversions
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
Most built-in or std types are supported out of the box but there are 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
@@ -16,34 +16,19 @@ 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).
You should put this function in the same namespace as your type and it has to be 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.**
You should put this function in the same namespace as your type and have it declared before including Catch's header.
## 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 {
template<> struct StringMaker<T> {
template<>
struct StringMaker<T> {
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?
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.
## Key Features
* 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.
* Write test cases as, self-registering, functions or methods.
* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures!)
* 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++11 and have a C++ standard library available.
* 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).
* 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.
* Tests are named using free-form strings - no more couching names in legal identifiers.
## 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.
* 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.
* 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.
* Catch can test itself.
* 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.
* Internal and friendly macros are isolated so name clashes can be managed
* Support for Matchers (early stages)
## 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)
* Matchers
## Who else is using Catch?
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)
# define CATCH_IMPL
# define CATCH_CONFIG_EXTERNAL_INTERFACES
#endif
#ifdef CATCH_IMPL
@@ -28,19 +29,21 @@
# endif
#endif
#include "internal/catch_notimplemented_exception.h"
#include "internal/catch_context.h"
#include "internal/catch_tag_alias_autoregistrar.h"
#include "internal/catch_test_registry.hpp"
#include "internal/catch_capture.hpp"
#include "internal/catch_section.h"
#include "internal/catch_generators.hpp"
#include "internal/catch_benchmark.h"
#include "internal/catch_interfaces_exception.h"
#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_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
// in the conditionally compiled sections
#include "internal/catch_test_case_info.h"
@@ -50,30 +53,11 @@
#include "internal/catch_objc.hpp"
#endif
#ifdef CATCH_IMPL
// !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 {};
#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
#include "internal/catch_external_interfaces.h"
#endif
LeakDetector leakDetector;
#ifdef CATCH_IMPL
#include "internal/catch_impl.hpp"
#endif
@@ -87,133 +71,103 @@ LeakDetector leakDetector;
#endif
//////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL
#if defined(CATCH_CONFIG_FAST_COMPILE)
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
#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( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#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_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "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 )
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, 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_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#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_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "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 )
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, 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 )
#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 )
#endif
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#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_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", 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) )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_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_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_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_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_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
// "BDD-style" convenience wrappers
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#else
#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
#endif
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + 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, "" )
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + 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
#else
#if defined(CATCH_CONFIG_FAST_COMPILE)
#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr )
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#else
#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( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#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_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, 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_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#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_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, 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 )
#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 )
#endif
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", 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::toString(msg) )
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
@@ -222,40 +176,21 @@ LeakDetector leakDetector;
#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 SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#else
#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 )
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
#endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
// "BDD-style" convenience wrappers
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define SCENARIO( ... ) TEST_CASE( "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 SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
#endif
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
#define WHEN( desc ) SECTION( std::string(" When: ") + 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, "" )
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
#define WHEN( desc ) SECTION( std::string(" When: ") + 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;

View File

@@ -9,58 +9,57 @@
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
#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_test_spec.hpp"
#include "internal/catch_version.h"
#include "internal/catch_interfaces_reporter.h"
#include "internal/catch_startup_exception_registry.h"
#include "internal/catch_text.h"
#include <fstream>
#include <stdlib.h>
#include <cstdlib>
#include <limits>
#include <iomanip>
namespace Catch {
Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
if( !reporter ) {
std::ostringstream oss;
oss << "No reporter registered with name: '" << reporterName << "'";
throw std::domain_error( oss.str() );
}
IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) {
auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config );
CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" );
return reporter;
}
Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
std::vector<std::string> reporters = config->getReporterNames();
if( reporters.empty() )
reporters.push_back( "console" );
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
Ptr<IStreamingReporter> reporter;
for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
it != itEnd;
++it )
reporter = addReporter( reporter, createReporter( *it, config ) );
IStreamingReporterPtr makeReporter( std::shared_ptr<Config> const& config ) {
auto const& reporterNames = config->getReporterNames();
if( reporterNames.empty() )
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config );
IStreamingReporterPtr reporter;
for( auto const& name : reporterNames )
addReporter( reporter, createReporter( name, config ) );
return reporter;
}
Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
it != itEnd;
++it )
reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
return reporters;
void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) {
auto const& listeners = getRegistryHub().getReporterRegistry().getListeners();
for( auto const& listener : listeners )
addReporter(reporters, listener->create( ReporterConfig( config ) ) );
}
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 );
reporter = addListeners( iconfig, reporter );
RunContext context( iconfig, reporter );
RunContext context( config, std::move( reporter ) );
Totals totals;
@@ -70,27 +69,24 @@ namespace Catch {
if( !testSpec.hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
it != itEnd;
++it ) {
if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
totals += context.runTest( *it );
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *config );
for( auto const& testCase : allTestCases ) {
if( !context.aborting() && matchTest( testCase, testSpec, *config ) )
totals += context.runTest( testCase );
else
reporter->skipTest( *it );
context.reporter().skipTest( testCase );
}
context.testGroupEnded( iconfig->name(), totals, 1, 1 );
context.testGroupEnded( config->name(), totals, 1, 1 );
return totals;
}
void applyFilenamesAsTags( IConfig const& config ) {
std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
for(std::size_t i = 0; i < tests.size(); ++i ) {
TestCase& test = const_cast<TestCase&>( tests[i] );
std::set<std::string> tags = test.tags;
auto& tests = const_cast<std::vector<TestCase>&>( getAllTestCasesSorted( config ) );
for( auto& testCase : tests ) {
auto tags = testCase.tags;
std::string filename = test.lineInfo.file;
std::string filename = testCase.lineInfo.file;
std::string::size_type lastSlash = filename.find_last_of( "\\/" );
if( lastSlash != std::string::npos )
filename = filename.substr( lastSlash+1 );
@@ -99,67 +95,80 @@ namespace Catch {
if( lastDot != std::string::npos )
filename = filename.substr( 0, lastDot );
tags.insert( '#' + filename );
setTags( test, tags );
tags.push_back( '#' + filename );
setTags( testCase, tags );
}
}
class Session : NonCopyable {
static bool alreadyInstantiated;
class Session : NonCopyable {
static const int MaxExitCode;
public:
struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
Session()
: m_cli( makeCommandLineParser() ) {
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 );
}
Session() {
static bool alreadyInstantiated = false;
if( alreadyInstantiated )
CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" );
alreadyInstantiated = true;
m_cli = makeCommandLineParser( m_configData );
}
~Session() {
~Session() override {
Catch::cleanUp();
}
void showHelp( std::string const& processName ) {
Catch::cout() << "\nCatch v" << libraryVersion() << "\n";
m_cli.usage( Catch::cout(), processName );
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
void showHelp() const {
Catch::cout()
<< "\nCatch v" << libraryVersion() << "\n"
<< m_cli << std::endl
<< "For more detailed usage please see the project docs\n" << std::endl;
}
void libIdentify() {
Catch::cout()
<< std::left << std::setw(16) << "description: " << "A Catch test executable\n"
<< std::left << std::setw(16) << "category: " << "testframework\n"
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
}
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try {
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
if( m_configData.showHelp )
showHelp( m_configData.processName );
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)();
int applyCommandLine( int argc, char* argv[] ) {
auto result = m_cli.parse( clara::Args( argc, argv ) );
if( !result ) {
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 )
showHelp();
if( m_configData.libIdentify )
libIdentify();
m_config.reset();
return 0;
}
void useConfigData( ConfigData const& _configData ) {
m_configData = _configData;
void useConfigData( ConfigData const& configData ) {
m_configData = configData;
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 );
if( returnCode == 0 )
returnCode = run();
@@ -167,7 +176,7 @@ namespace Catch {
}
#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 ];
@@ -179,9 +188,7 @@ namespace Catch {
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
}
int returnCode = applyCommandLine( argc, utf8Argv );
if( returnCode == 0 )
returnCode = run();
int returnCode = run( argc, utf8Argv );
for ( int i = 0; i < argc; ++i )
delete [] utf8Argv[ i ];
@@ -191,9 +198,36 @@ namespace Catch {
return returnCode;
}
#endif
int run() {
if( m_configData.showHelp )
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
std::getchar();
}
int exitCode = runInternal();
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
std::getchar();
}
return exitCode;
}
clara::Parser const& cli() const {
return m_cli;
}
void cli( clara::Parser const& newParser ) {
m_cli = newParser;
}
ConfigData& configData() {
return m_configData;
}
Config& config() {
if( !m_config )
m_config = std::make_shared<Config>( m_configData );
return *m_config;
}
private:
int runInternal() {
if( m_configData.showHelp || m_configData.libIdentify )
return 0;
try
@@ -209,36 +243,20 @@ namespace Catch {
if( Option<std::size_t> listed = list( config() ) )
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::cerr() << ex.what() << std::endl;
return (std::numeric_limits<int>::max)();
return MaxExitCode;
}
}
Clara::CommandLine<ConfigData> const& cli() const {
return m_cli;
}
std::vector<Clara::Parser::Token> const& unusedTokens() const {
return m_unusedTokens;
}
ConfigData& configData() {
return m_configData;
}
Config& config() {
if( !m_config )
m_config = new Config( m_configData );
return *m_config;
}
private:
Clara::CommandLine<ConfigData> m_cli;
std::vector<Clara::Parser::Token> m_unusedTokens;
clara::Parser m_cli;
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

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 <cmath>
#include <limits>
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
#include <type_traits>
#endif
namespace Catch {
namespace Detail {
double max(double lhs, double rhs);
class Approx {
public:
explicit Approx ( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_margin( 0.0 ),
m_scale( 1.0 ),
m_value( value )
{}
explicit Approx ( double value );
static Approx custom() {
return Approx( 0 );
}
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
static Approx custom();
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.epsilon( m_epsilon );
approx.margin( m_margin );
@@ -45,15 +35,15 @@ namespace Detail {
}
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>
friend bool operator == ( const T& lhs, Approx const& rhs ) {
// Thanks to Richard Harris for his help refining this formula
auto lhs_v = 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)));
auto lhs_v = static_cast<double>(lhs);
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) {
return true;
}
@@ -66,122 +56,54 @@ namespace Detail {
}
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 );
}
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 );
}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator <= ( T lhs, Approx const& rhs ) {
return double(lhs) < rhs.m_value || lhs == rhs;
friend bool operator <= ( T const& lhs, Approx const& 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>
friend bool operator <= ( Approx const& lhs, T rhs ) {
return lhs.m_value < double(rhs) || lhs == rhs;
friend bool operator <= ( Approx const& lhs, T const& 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>
friend bool operator >= ( T lhs, Approx const& rhs ) {
return double(lhs) > rhs.m_value || lhs == rhs;
friend bool operator >= ( T const& lhs, Approx const& 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>
friend bool operator >= ( Approx const& lhs, T rhs ) {
return lhs.m_value > double(rhs) || lhs == rhs;
friend bool operator >= ( Approx const& lhs, T const& 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>
Approx& epsilon( T newEpsilon ) {
m_epsilon = double(newEpsilon);
Approx& epsilon( T const& newEpsilon ) {
m_epsilon = static_cast<double>(newEpsilon);
return *this;
}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& margin( T newMargin ) {
m_margin = double(newMargin);
Approx& margin( T const& newMargin ) {
m_margin = static_cast<double>(newMargin);
return *this;
}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& scale( T newScale ) {
m_scale = double(newScale);
Approx& scale( T const& newScale ) {
m_scale = static_cast<double>(newScale);
return *this;
}
#else
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();
}
std::string toString() const;
private:
double m_epsilon;
@@ -192,9 +114,9 @@ namespace Detail {
}
template<>
inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
return value.toString();
}
struct StringMaker<Catch::Detail::Approx> {
static std::string convert(Catch::Detail::Approx const& value);
};
} // 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
#include <string>
#include "catch_assertioninfo.h"
#include "catch_result_type.h"
#include "catch_common.h"
#include "catch_stringref.h"
#include "catch_assertionhandler.h"
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
{
AssertionResultData() : decomposedExpression( CATCH_NULL )
, resultType( ResultWas::Unknown )
, negated( false )
, parenthesized( false ) {}
AssertionResultData() = delete;
void negate( bool parenthesize ) {
negated = !negated;
parenthesized = parenthesize;
if( resultType == ResultWas::Ok )
resultType = ResultWas::ExpressionFailed;
else if( resultType == ResultWas::ExpressionFailed )
resultType = ResultWas::Ok;
}
AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression )
: resultType( _resultType ),
lazyExpression( _lazyExpression )
{}
std::string const& reconstructExpression() const {
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;
ResultWas::OfType resultType = ResultWas::Unknown;
std::string message;
ResultWas::OfType resultType;
bool negated;
bool parenthesized;
LazyExpression lazyExpression;
std::string reconstructExpression() const;
mutable std::string reconstructedExpression;
};
class AssertionResult {
public:
AssertionResult();
AssertionResult() = delete;
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 succeeded() const;
@@ -116,10 +52,8 @@ namespace Catch {
std::string getMessage() const;
SourceLineInfo getSourceInfo() const;
std::string getTestMacroName() const;
void discardDecomposedExpression() const;
void expandDecomposedExpression() const;
protected:
//protected:
AssertionInfo m_info;
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,14 +8,9 @@
#ifndef 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_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_FAST_COMPILE)
@@ -23,158 +18,139 @@
// 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
// macro in each assertion
#define INTERNAL_CATCH_REACT( resultBuilder ) \
resultBuilder.react();
#define INTERNAL_CATCH_REACT( handler ) \
handler.reactWithDebugBreak();
///////////////////////////////////////////////////////////////////////////////
// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
// macros.
// This can potentially cause false negative, if the test code catches
// the exception before it propagates back up to the runner.
#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #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_CATCH_TRY( capturer ) capturer.setExceptionGuard();
#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard();
#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
__catchResult.setExceptionGuard(); \
__catchResult.captureMatch( arg, matcher, #matcher ); \
__catchResult.unsetExceptionGuard(); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
#else // CATCH_CONFIG_FAST_COMPILE
#include "catch_debugger.h"
#else
///////////////////////////////////////////////////////////////////////////////
// In the event of a failure works out if the debugger needs to be invoked
// 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
// source code rather than in Catch library code
#define INTERNAL_CATCH_REACT( resultBuilder ) \
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
resultBuilder.react();
#define INTERNAL_CATCH_REACT( handler ) \
if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
handler.reactWithoutDebugBreak();
#define INTERNAL_CATCH_TRY( capturer ) try
#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); }
#endif
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
try { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \
catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} \
catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \
} \
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
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} 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
// 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 ) \
INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
if( Catch::getResultCapture().lastAssertionPassed() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
if( !Catch::getResultCapture().lastAssertionPassed() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \
try { \
static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
} \
catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \
catchAssertionHandler.useActiveException(); \
} \
INTERNAL_CATCH_REACT( __catchResult ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
if( __catchResult.allowThrows() ) \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \
if( catchAssertionHandler.allowThrows() ) \
try { \
static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \
catch( ... ) { \
__catchResult.captureExpectedException( matcher ); \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
} \
else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( __catchResult ) \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
if( __catchResult.allowThrows() ) \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \
try { \
static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \
catch( exceptionType ) { \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
catch( exceptionType const& ) { \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
} \
catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \
catchAssertionHandler.useActiveException(); \
} \
else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( __catchResult ) \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
__catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
__catchResult.captureResult( messageType ); \
INTERNAL_CATCH_REACT( __catchResult ) \
} 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_MSG( macroName, messageType, resultDisposition, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_INFO( macroName, 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 { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
try { \
__catchResult.captureMatch( arg, matcher, #matcher ); \
} catch( ... ) { \
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
} \
INTERNAL_CATCH_REACT( __catchResult ) \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \
try { \
static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \
catch( ... ) { \
handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
#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)
#ifdef CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
#undef CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#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
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
#include "../external/clara.h"
#undef STITCH_CLARA_OPEN_NAMESPACE
#include "../external/clara.hpp"
// Restore Clara's value for console width, if present
#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
#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,210 +9,11 @@
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
#include "catch_config.hpp"
#include "catch_common.h"
#include "catch_clara.h"
#include <fstream>
#include <ctime>
namespace Catch {
inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
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 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" );
return cli;
}
clara::Parser makeCommandLineParser( ConfigData& config );
} // 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_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
#include <sstream>
#include <algorithm>
#include <iosfwd>
#include <string>
#include <cstdint>
namespace Catch {
@@ -34,79 +35,29 @@ namespace Catch {
}; };
class NonCopyable {
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
NonCopyable( NonCopyable const& ) = delete;
NonCopyable( NonCopyable && ) = delete;
NonCopyable& operator = ( NonCopyable const& ) = delete;
NonCopyable& operator = ( NonCopyable && ) = delete;
#else
NonCopyable( NonCopyable const& info );
NonCopyable& operator = ( NonCopyable const& );
#endif
protected:
NonCopyable() {}
virtual ~NonCopyable();
};
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 {
SourceLineInfo();
SourceLineInfo( char const* _file, std::size_t _line );
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
SourceLineInfo(SourceLineInfo const& other) = default;
SourceLineInfo() = delete;
SourceLineInfo( char const* _file, std::size_t _line ) noexcept;
SourceLineInfo( SourceLineInfo const& other ) = default;
SourceLineInfo( SourceLineInfo && ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo& operator = ( SourceLineInfo && ) = default;
# endif
bool empty() const;
bool operator == ( SourceLineInfo const& other ) const;
bool operator < ( SourceLineInfo const& other ) const;
bool empty() const noexcept;
bool operator == ( SourceLineInfo const& other ) const noexcept;
bool operator < ( SourceLineInfo const& other ) const noexcept;
char const* file;
std::size_t line;
@@ -115,11 +66,9 @@ namespace Catch {
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue( bool value ){ return value; }
inline bool alwaysTrue() { return true; }
inline bool alwaysFalse() { return false; }
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
bool isTrue( bool value );
bool alwaysTrue();
bool alwaysFalse();
void seedRng( IConfig const& config );
unsigned int rngSeed();
@@ -129,9 +78,7 @@ namespace Catch {
// as well as
// >> stuff +StreamEndStop
struct StreamEndStop {
std::string operator+() {
return std::string();
}
std::string operator+() const;
};
template<typename T>
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_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
#define CATCH_INTERNAL_LINEINFO \
::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
#endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED

View File

@@ -8,23 +8,9 @@
#ifndef 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:
//
// 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_WINDOWS_SEH : is Windows SEH supported?
// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
@@ -34,18 +20,13 @@
// ****************
// 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
// 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
# if __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
# endif
# if __cplusplus >= 201402L
# define CATCH_CPP14_OR_GREATER
# endif
@@ -54,15 +35,7 @@
#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 \
_Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
@@ -74,7 +47,6 @@
_Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
_Pragma( "clang diagnostic pop" )
# endif
#endif // __clang__
@@ -129,14 +101,6 @@
// GCC
#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__
@@ -146,32 +110,10 @@
#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
////////////////////////////////////////////////////////////////////////////////
// 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
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \
@@ -181,95 +123,15 @@
#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
#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
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_NOEXCEPT
#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
// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
// This does not affect compilation
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
# define CATCH_CONFIG_COUNTER
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_SHUFFLE
#endif
# if defined(CATCH_INTERNAL_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)
# define CATCH_CONFIG_WINDOWS_SEH
#endif
@@ -287,35 +149,6 @@
# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
#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

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

View File

@@ -5,17 +5,20 @@
* 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_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
#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 {
struct IColourImpl {
virtual ~IColourImpl() {}
virtual ~IColourImpl() = default;
virtual void use( Colour::Code _colourCode ) = 0;
};
@@ -57,7 +60,7 @@ namespace {
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 ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes );
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::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() {
static Win32ColourImpl s_instance;
Ptr<IConfig const> config = getCurrentContext().getConfig();
IConfigPtr config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = !isDebuggerActive()
? UseColour::Yes
: UseColour::No;
colourMode = UseColour::Yes;
return colourMode == UseColour::Yes
? &s_instance
: NoColourImpl::instance();
@@ -118,7 +119,7 @@ namespace {
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
public:
virtual void use( Colour::Code _colourCode ) {
virtual void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@@ -134,7 +135,7 @@ namespace {
case Colour::BrightGreen: return setColour( "[1;32m" );
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() {
@@ -150,12 +151,12 @@ namespace {
IColourImpl* platformColourInstance() {
ErrnoGuard guard;
Ptr<IConfig const> config = getCurrentContext().getConfig();
IConfigPtr config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
colourMode = isatty(STDOUT_FILENO)
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes
@@ -178,8 +179,17 @@ namespace Catch {
namespace Catch {
Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
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 ); }
void Colour::use( Code _colourCode ) {
@@ -187,6 +197,8 @@ namespace Catch {
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
Colour( Code _colourCode );
Colour( Colour const& other );
Colour( Colour&& other ) noexcept;
Colour& operator=( Colour&& other ) noexcept;
~Colour();
// Use static method for one-shot changes
static void use( Code _colourCode );
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

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
#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
#include "catch_interfaces_generators.h"
#include "catch_ptr.hpp"
#include <memory>
namespace Catch {
@@ -18,18 +16,17 @@ namespace Catch {
class Stream;
struct IResultCapture;
struct IRunner;
struct IGeneratorsForTest;
struct IConfig;
using IConfigPtr = std::shared_ptr<IConfig const>;
struct IContext
{
virtual ~IContext();
virtual IResultCapture* getResultCapture() = 0;
virtual IRunner* getRunner() = 0;
virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
virtual bool advanceGeneratorsForCurrentTest() = 0;
virtual Ptr<IConfig const> getConfig() const = 0;
virtual IConfigPtr getConfig() const = 0;
};
struct IMutableContext : IContext
@@ -37,14 +34,12 @@ namespace Catch {
virtual ~IMutableContext();
virtual void setResultCapture( IResultCapture* resultCapture ) = 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();
IMutableContext& getCurrentMutableContext();
void cleanUpContext();
Stream createStream( std::string const& streamName );
}
#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)
*
*/
#ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#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
@@ -49,7 +49,7 @@
// Call sysctl.
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;
return false;
}
@@ -106,7 +106,7 @@
}
#else
namespace Catch {
inline bool isDebuggerActive() { return false; }
bool isDebuggerActive() { return false; }
}
#endif // Platform
@@ -127,5 +127,3 @@
}
}
#endif // Platform
#endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED

View File

@@ -21,15 +21,7 @@ namespace Catch{
#ifdef CATCH_PLATFORM_MAC
// The following code snippet based on:
// 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
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(CATCH_PLATFORM_LINUX)
// 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[]) {
#endif
int result = Catch::Session().run( argc, argv );
return ( result < 0xff ? result : 0xff );
return Catch::Session().run( argc, argv );
}
#else // __OBJC__
@@ -37,7 +36,7 @@ int main (int argc, char * const argv[]) {
[pool drain];
#endif
return ( result < 0xff ? result : 0xff );
return result;
}
#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
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
#include <cerrno>
#ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED
#define TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED
namespace Catch {
class ErrnoGuard {
public:
ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard() { errno = m_oldErrno; }
ErrnoGuard();
~ErrnoGuard();
private:
int m_oldErrno;
};
}
#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED

View File

@@ -1,219 +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: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"
#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 "../reporters/catch_reporter_xml.hpp"
#include "../reporters/catch_reporter_junit.hpp"
#include "../reporters/catch_reporter_console.hpp"
#include "../reporters/catch_reporter_compact.hpp"
#include "internal/catch_notimplemented_exception.h"
// Temporary hack to fix separately provided reporters
#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 {
LeakDetector leakDetector;
// These are all here to avoid warnings about not having any out of line
// virtual methods
NonCopyable::~NonCopyable() {}
IShared::~IShared() {}
IStream::~IStream() CATCH_NOEXCEPT {}
FileStream::~FileStream() CATCH_NOEXCEPT {}
CoutStream::~CoutStream() CATCH_NOEXCEPT {}
DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
IStream::~IStream() noexcept {}
FileStream::~FileStream() noexcept {}
CoutStream::~CoutStream() noexcept {}
DebugOutStream::~DebugOutStream() noexcept {}
StreamBufBase::~StreamBufBase() noexcept {}
IContext::~IContext() {}
IResultCapture::~IResultCapture() {}
ITestCase::~ITestCase() {}
ITestInvoker::~ITestInvoker() {}
ITestCaseRegistry::~ITestCaseRegistry() {}
IRegistryHub::~IRegistryHub() {}
IMutableRegistryHub::~IMutableRegistryHub() {}
IExceptionTranslator::~IExceptionTranslator() {}
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() {}
IMutableContext::~IMutableContext() {}
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() {}
namespace TestCaseTracking {
ITracker::~ITracker() {}
TrackerBase::~TrackerBase() {}
SectionTracker::~SectionTracker() {}
IndexTracker::~IndexTracker() {}
}
}
#ifdef __clang__

View File

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

View File

@@ -8,19 +8,20 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
#include "catch_common.h"
#include <iosfwd>
#include <string>
#include <vector>
#include "catch_ptr.hpp"
#include <memory>
namespace Catch {
struct Verbosity { enum Level {
NoOutput = 0,
Quiet,
Normal
}; };
enum class Verbosity {
Quiet = 0,
Normal,
High
};
struct WarnAbout { enum What {
Nothing = 0x00,
@@ -42,10 +43,16 @@ namespace Catch {
Yes,
No
}; };
struct WaitForKeypress { enum When {
Never,
BeforeStart = 1,
BeforeExit = 2,
BeforeStartAndExit = BeforeStart | BeforeExit
}; };
class TestSpec;
struct IConfig : IShared {
struct IConfig : NonCopyable {
virtual ~IConfig();
@@ -61,10 +68,13 @@ namespace Catch {
virtual TestSpec const& testSpec() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual int benchmarkResolutionMultiple() const = 0;
virtual UseColour::YesOrNo useColour() 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

View File

@@ -14,11 +14,10 @@
#include "catch_interfaces_registry_hub.h"
namespace Catch {
typedef std::string(*exceptionTranslateFunction)();
using exceptionTranslateFunction = std::string(*)();
struct IExceptionTranslator;
typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
struct IExceptionTranslator {
virtual ~IExceptionTranslator();
@@ -40,7 +39,7 @@ namespace Catch {
: 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 {
if( it == itEnd )
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
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
#include "catch_ptr.hpp"
#include "catch_common.h"
#include <string>
#include <memory>
namespace Catch {
@@ -21,6 +22,9 @@ namespace Catch {
struct IReporterRegistry;
struct IReporterFactory;
struct ITagAliasRegistry;
class StartupExceptionRegistry;
using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
struct IRegistryHub {
virtual ~IRegistryHub();
@@ -30,15 +34,19 @@ namespace Catch {
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
};
struct IMutableRegistryHub {
virtual ~IMutableRegistryHub();
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
virtual void registerTest( TestCase const& testInfo ) = 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 registerStartupException() noexcept = 0;
};
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_common.h"
#include "catch_totals.hpp"
#include "catch_ptr.hpp"
#include "catch_config.hpp"
#include "catch_context.h"
#include "catch_totals.hpp"
#include "catch_test_case_info.h"
#include "catch_assertionresult.h"
#include "catch_message.h"
#include "catch_option.hpp"
#include <string>
#include <ostream>
#include <iosfwd>
#include <map>
#include <set>
#include <memory>
namespace Catch {
namespace Catch
{
struct ReporterConfig {
explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
explicit ReporterConfig( IConfigPtr const& _fullConfig );
ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );
std::ostream& stream() const { return *m_stream; }
Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
std::ostream& stream() const;
IConfigPtr fullConfig() const;
private:
std::ostream* m_stream;
Ptr<IConfig const> m_fullConfig;
IConfigPtr m_fullConfig;
};
struct ReporterPreferences {
ReporterPreferences()
: shouldRedirectStdOut( false )
{}
bool shouldRedirectStdOut;
bool shouldRedirectStdOut = false;
};
template<typename T>
struct LazyStat : Option<T> {
LazyStat() : used( false ) {}
LazyStat& operator=( T const& _value ) {
Option<T>::operator=( _value );
used = false;
@@ -59,21 +55,17 @@ namespace Catch
Option<T>::reset();
used = false;
}
bool used;
bool used = false;
};
struct TestRunInfo {
TestRunInfo( std::string const& _name ) : name( _name ) {}
TestRunInfo( std::string const& _name );
std::string name;
};
struct GroupInfo {
GroupInfo( std::string const& _name,
std::size_t _groupIndex,
std::size_t _groupsCount )
: name( _name ),
groupIndex( _groupIndex ),
groupsCounts( _groupsCount )
{}
std::size_t _groupsCount );
std::string name;
std::size_t groupIndex;
@@ -83,29 +75,13 @@ namespace Catch
struct AssertionStats {
AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages,
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();
Totals const& _totals );
infoMessages.push_back( builder.m_info );
}
}
virtual ~AssertionStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionStats( AssertionStats const& ) = default;
AssertionStats( AssertionStats && ) = default;
AssertionStats& operator = ( AssertionStats const& ) = default;
AssertionStats& operator = ( AssertionStats && ) = default;
# endif
virtual ~AssertionStats() = default;
AssertionResult assertionResult;
std::vector<MessageInfo> infoMessages;
@@ -116,19 +92,12 @@ namespace Catch
SectionStats( SectionInfo const& _sectionInfo,
Counts const& _assertions,
double _durationInSeconds,
bool _missingAssertions )
: sectionInfo( _sectionInfo ),
assertions( _assertions ),
durationInSeconds( _durationInSeconds ),
missingAssertions( _missingAssertions )
{}
virtual ~SectionStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
bool _missingAssertions );
SectionStats( SectionStats const& ) = default;
SectionStats( SectionStats && ) = default;
SectionStats& operator = ( SectionStats const& ) = default;
SectionStats& operator = ( SectionStats && ) = default;
# endif
virtual ~SectionStats() = default;
SectionInfo sectionInfo;
Counts assertions;
@@ -141,21 +110,13 @@ namespace Catch
Totals const& _totals,
std::string const& _stdOut,
std::string const& _stdErr,
bool _aborting )
: testInfo( _testInfo ),
totals( _totals ),
stdOut( _stdOut ),
stdErr( _stdErr ),
aborting( _aborting )
{}
virtual ~TestCaseStats();
bool _aborting );
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestCaseStats( TestCaseStats const& ) = default;
TestCaseStats( TestCaseStats && ) = default;
TestCaseStats& operator = ( TestCaseStats const& ) = default;
TestCaseStats& operator = ( TestCaseStats && ) = default;
# endif
virtual ~TestCaseStats() = default;
TestCaseInfo testInfo;
Totals totals;
@@ -167,23 +128,14 @@ namespace Catch
struct TestGroupStats {
TestGroupStats( GroupInfo const& _groupInfo,
Totals const& _totals,
bool _aborting )
: groupInfo( _groupInfo ),
totals( _totals ),
aborting( _aborting )
{}
TestGroupStats( GroupInfo const& _groupInfo )
: groupInfo( _groupInfo ),
aborting( false )
{}
virtual ~TestGroupStats();
bool _aborting );
TestGroupStats( GroupInfo const& _groupInfo );
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestGroupStats( TestGroupStats const& ) = default;
TestGroupStats( TestGroupStats && ) = default;
TestGroupStats& operator = ( TestGroupStats const& ) = default;
TestGroupStats& operator = ( TestGroupStats && ) = default;
# endif
virtual ~TestGroupStats() = default;
GroupInfo groupInfo;
Totals totals;
@@ -193,38 +145,35 @@ namespace Catch
struct TestRunStats {
TestRunStats( TestRunInfo const& _runInfo,
Totals const& _totals,
bool _aborting )
: runInfo( _runInfo ),
totals( _totals ),
aborting( _aborting )
{}
virtual ~TestRunStats();
bool _aborting );
# 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 && ) = default;
TestRunStats& operator = ( TestRunStats const& ) = default;
TestRunStats& operator = ( TestRunStats && ) = default;
# endif
virtual ~TestRunStats() = default;
TestRunInfo runInfo;
Totals totals;
bool aborting;
};
struct BenchmarkInfo {
std::string name;
};
struct BenchmarkStats {
BenchmarkInfo info;
size_t iterations;
uint64_t elapsedTimeInNanoseconds;
};
class MultipleReporters;
struct IStreamingReporter : IShared {
virtual ~IStreamingReporter();
struct 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::set<Verbosity> getSupportedVerbosities()
virtual ReporterPreferences getPreferences() const = 0;
@@ -236,11 +185,17 @@ namespace Catch
virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
// *** experimental ***
virtual void benchmarkStarting( BenchmarkInfo const& ) {}
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
// The return value indicates if the messages buffer should be cleared:
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
// *** experimental ***
virtual void benchmarkEnded( BenchmarkStats const& ) {}
virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
@@ -248,28 +203,29 @@ namespace Catch
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 : IShared {
virtual ~IReporterFactory();
virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
struct IReporterFactory {
virtual ~IReporterFactory() = default;
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
virtual std::string getDescription() const = 0;
};
using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
struct IReporterRegistry {
typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
typedef std::vector<Ptr<IReporterFactory> > Listeners;
using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
using Listeners = std::vector<IReporterFactoryPtr>;
virtual ~IReporterRegistry();
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
virtual ~IReporterRegistry() = default;
virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
virtual FactoryMap const& getFactories() const = 0;
virtual Listeners const& getListeners() const = 0;
};
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED

View File

@@ -8,14 +8,16 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
#include "catch_tag_alias.h"
#include "catch_option.hpp"
#include <string>
namespace Catch {
struct TagAlias;
struct 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;
static ITagAliasRegistry const& get();

View File

@@ -8,20 +8,20 @@
#ifndef TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
#include "catch_ptr.hpp"
#include <vector>
#include <memory>
namespace Catch {
class TestSpec;
struct ITestCase : IShared {
struct ITestInvoker {
virtual void invoke () const = 0;
protected:
virtual ~ITestCase();
virtual ~ITestInvoker();
};
using ITestCasePtr = std::shared_ptr<ITestInvoker>;
class TestCase;
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 <string>
#include <vector>
namespace Catch {
namespace Matchers {
namespace Impl {
@@ -20,18 +23,15 @@ namespace Matchers {
class MatcherUntypedBase {
public:
std::string toString() const {
if( m_cachedToString.empty() )
m_cachedToString = describe();
return m_cachedToString;
}
MatcherUntypedBase() = default;
MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
std::string toString() const;
protected:
virtual ~MatcherUntypedBase();
virtual ~MatcherUntypedBase() = default;
virtual std::string describe() const = 0;
mutable std::string m_cachedToString;
private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
};
template<typename ObjectT>
@@ -54,21 +54,24 @@ namespace Matchers {
template<typename ArgT>
struct MatchAllOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if (!m_matchers[i]->match(arg))
bool match( ArgT const& arg ) const override {
for( auto matcher : m_matchers ) {
if (!matcher->match(arg))
return false;
}
return true;
}
virtual std::string describe() const CATCH_OVERRIDE {
std::string describe() const override {
std::string description;
description.reserve( 4 + m_matchers.size()*32 );
description += "( ";
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if( i != 0 )
bool first = true;
for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " and ";
description += m_matchers[i]->toString();
description += matcher->toString();
}
description += " )";
return description;
@@ -84,21 +87,24 @@ namespace Matchers {
template<typename ArgT>
struct MatchAnyOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if (m_matchers[i]->match(arg))
bool match( ArgT const& arg ) const override {
for( auto matcher : m_matchers ) {
if (matcher->match(arg))
return true;
}
return false;
}
virtual std::string describe() const CATCH_OVERRIDE {
std::string describe() const override {
std::string description;
description.reserve( 4 + m_matchers.size()*32 );
description += "( ";
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if( i != 0 )
bool first = true;
for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " or ";
description += m_matchers[i]->toString();
description += matcher->toString();
}
description += " )";
return description;
@@ -117,11 +123,11 @@ namespace Matchers {
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 );
}
virtual std::string describe() const CATCH_OVERRIDE {
std::string describe() const override {
return "not " + m_underlyingMatcher.toString();
}
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)
*/
#include "catch_matchers.hpp"
#include "catch_matchers_string.h"
#include "catch_string_manip.h"
namespace Catch {
namespace Matchers {

View File

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

View File

@@ -20,12 +20,17 @@ namespace Matchers {
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
return std::find(v.begin(), v.end(), m_comparator) != v.end();
bool match(std::vector<T> const &v) const override {
for (auto const& el : v) {
if (el == m_comparator) {
return true;
}
}
return false;
}
virtual std::string describe() const CATCH_OVERRIDE {
return "Contains: " + Catch::toString( m_comparator );
std::string describe() const override {
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
}
T const& m_comparator;
@@ -36,17 +41,26 @@ namespace Matchers {
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
if (m_comparator.size() > v.size())
return false;
for (size_t i = 0; i < m_comparator.size(); ++i)
if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
for (auto const& comparator : m_comparator) {
auto present = false;
for (const auto& el : v) {
if (el == comparator) {
present = true;
break;
}
}
if (!present) {
return false;
}
}
return true;
}
virtual std::string describe() const CATCH_OVERRIDE {
return "Contains: " + Catch::toString( m_comparator );
std::string describe() const override {
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T> const& m_comparator;
@@ -57,7 +71,7 @@ namespace Matchers {
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 !=
// - 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
@@ -69,8 +83,8 @@ namespace Matchers {
return false;
return true;
}
virtual std::string describe() const CATCH_OVERRIDE {
return "Equals: " + Catch::toString( m_comparator );
std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( 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
* 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_interfaces_capture.h"
namespace Catch {
@@ -21,21 +20,34 @@ namespace Catch {
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
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 )
: m_info( builder.m_info )
{
m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info );
}
ScopedMessage::ScopedMessage( ScopedMessage const& other )
: m_info( other.m_info )
{}
ScopedMessage::~ScopedMessage() {
if ( !std::uncaught_exception() ){
@@ -45,5 +57,3 @@ namespace Catch {
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED

View File

@@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
#include <string>
#include <sstream>
#include "catch_result_type.h"
#include "catch_common.h"
@@ -25,22 +26,28 @@ namespace Catch {
std::string message;
unsigned int sequence;
bool operator == ( MessageInfo const& other ) const {
return sequence == other.sequence;
}
bool operator < ( MessageInfo const& other ) const {
return sequence < other.sequence;
}
bool operator == ( MessageInfo const& other ) const;
bool operator < ( MessageInfo const& other ) const;
private:
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,
SourceLineInfo const& lineInfo,
ResultWas::OfType type )
: m_info( macroName, lineInfo, type )
{}
ResultWas::OfType type );
template<typename T>
MessageBuilder& operator << ( T const& value ) {
@@ -49,13 +56,11 @@ namespace Catch {
}
MessageInfo m_info;
std::ostringstream m_stream;
};
class ScopedMessage {
public:
ScopedMessage( MessageBuilder const& builder );
ScopedMessage( ScopedMessage const& other );
~ScopedMessage();
MessageInfo m_info;

View File

@@ -5,26 +5,21 @@
* 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_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
#include "catch_notimplemented_exception.h"
#include <sstream>
namespace Catch {
NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
: m_lineInfo( lineInfo ) {
NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) {
std::ostringstream oss;
oss << lineInfo << ": function ";
oss << "not implemented";
m_what = oss.str();
}
const char* NotImplementedException::what() const CATCH_NOEXCEPT {
const char* NotImplementedException::what() const noexcept {
return m_what.c_str();
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED

View File

@@ -10,6 +10,8 @@
#include "catch_common.h"
#include <exception>
namespace Catch {
class NotImplementedException : public std::exception
@@ -17,13 +19,12 @@ namespace Catch {
public:
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:
std::string m_what;
SourceLineInfo m_lineInfo;
};
} // end namespace Catch

View File

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

View File

@@ -8,20 +8,18 @@
#ifndef TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
#include "catch_common.h"
namespace Catch {
// An optional type
template<typename T>
class Option {
public:
Option() : nullableValue( CATCH_NULL ) {}
Option() : nullableValue( nullptr ) {}
Option( T const& _value )
: nullableValue( new( storage ) T( _value ) )
{}
Option( Option const& _other )
: nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
: nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
{}
~Option() {
@@ -45,7 +43,7 @@ namespace Catch {
void reset() {
if( nullableValue )
nullableValue->~T();
nullableValue = CATCH_NULL;
nullableValue = nullptr;
}
T& operator*() { return *nullableValue; }
@@ -57,27 +55,17 @@ namespace Catch {
return nullableValue ? *nullableValue : defaultValue;
}
bool some() const { return nullableValue != CATCH_NULL; }
bool none() const { return nullableValue == CATCH_NULL; }
bool some() const { return nullableValue != nullptr; }
bool none() const { return nullableValue == nullptr; }
bool operator !() const { return nullableValue == CATCH_NULL; }
operator SafeBool::type() const {
return SafeBool::makeSafe( some() );
bool operator !() const { return nullableValue == nullptr; }
explicit operator bool() const {
return some();
}
private:
T *nullableValue;
union {
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
};
alignas(alignof(T)) char storage[sizeof(T)];
};
} // end namespace Catch

View File

@@ -9,20 +9,19 @@
#ifndef 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
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
# elif TARGET_OS_IPHONE == 1
# define CATCH_PLATFORM_IPHONE
# endif
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
# define CATCH_PLATFORM_WINDOWS
# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
# define CATCH_DEFINES_NOMINMAX
# endif
# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
# endif
#endif
#endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED

View File

@@ -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
* 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_test_case_registry_impl.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_startup_exception_registry.h"
namespace Catch {
namespace {
class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
RegistryHub( RegistryHub const& );
void operator=( RegistryHub const& );
class RegistryHub : public IRegistryHub, public IMutableRegistryHub,
private NonCopyable {
public: // IRegistryHub
RegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
IReporterRegistry const& getReporterRegistry() const override {
return m_reporterRegistry;
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
ITestCaseRegistry const& getTestCaseRegistry() const override {
return m_testCaseRegistry;
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override {
return m_exceptionTranslatorRegistry;
}
virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE {
ITagAliasRegistry const& getTagAliasRegistry() const override {
return m_tagAliasRegistry;
}
StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
return m_exceptionRegistry;
}
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 );
}
virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
void registerListener( IReporterFactoryPtr const& factory ) override {
m_reporterRegistry.registerListener( factory );
}
virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
void registerTest( TestCase const& testInfo ) override {
m_testCaseRegistry.registerTest( testInfo );
}
virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
void registerTranslator( const IExceptionTranslator* translator ) override {
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 );
}
void registerStartupException() noexcept override {
m_exceptionRegistry.add(std::current_exception());
}
private:
TestRegistry m_testCaseRegistry;
ReporterRegistry m_reporterRegistry;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
TagAliasRegistry m_tagAliasRegistry;
StartupExceptionRegistry m_exceptionRegistry;
};
// Single, global, instance
inline RegistryHub*& getTheRegistryHub() {
static RegistryHub* theRegistryHub = CATCH_NULL;
RegistryHub*& getTheRegistryHub() {
static RegistryHub* theRegistryHub = nullptr;
if( !theRegistryHub )
theRegistryHub = new RegistryHub();
return theRegistryHub;
@@ -82,7 +85,7 @@ namespace Catch {
}
void cleanUp() {
delete getTheRegistryHub();
getTheRegistryHub() = CATCH_NULL;
getTheRegistryHub() = nullptr;
cleanUpContext();
}
std::string translateActiveException() {
@@ -91,5 +94,3 @@ 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.
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
@@ -9,51 +10,19 @@
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
#include "catch_interfaces_registry_hub.h"
#include "catch_legacy_reporter_adapter.h"
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>
class ReporterRegistrar {
class ReporterFactory : public SharedImpl<IReporterFactory> {
class ReporterFactory : public IReporterFactory {
// *** Please Note ***:
// - If you end up here looking at a compiler error because it's trying to register
// 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 IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr<T>( new T( config ) );
}
virtual std::string getDescription() const {
virtual std::string getDescription() const override {
return T::getDescription();
}
};
@@ -61,19 +30,19 @@ namespace Catch {
public:
ReporterRegistrar( std::string const& name ) {
getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
}
};
template<typename T>
class ListenerRegistrar {
class ListenerFactory : public SharedImpl<IReporterFactory> {
class ListenerFactory : public IReporterFactory {
virtual IStreamingReporter* create( ReporterConfig const& config ) const {
return new T( config );
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr<T>( new T( config ) );
}
virtual std::string getDescription() const {
virtual std::string getDescription() const override {
return std::string();
}
};
@@ -81,21 +50,14 @@ namespace Catch {
public:
ListenerRegistrar() {
getMutableRegistryHub().registerListener( new ListenerFactory() );
getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );
}
};
}
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
#define CATCH_REGISTER_REPORTER( name, reporterType ) \
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 ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }

View File

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

View File

@@ -1,133 +0,0 @@
/*
* Created by Phil on 28/5/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_RESULT_BUILDER_H_INCLUDED
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
#include "catch_result_type.h"
#include "catch_assertionresult.h"
#include "catch_common.h"
#include "catch_matchers.hpp"
namespace Catch {
struct TestFailureException{};
template<typename T> class ExpressionLhs;
struct CopyableStream {
CopyableStream() {}
CopyableStream( CopyableStream const& other ) {
oss << other.oss.str();
}
CopyableStream& operator=( CopyableStream const& other ) {
oss.str(std::string());
oss << other.oss.str();
return *this;
}
std::ostringstream oss;
};
class ResultBuilder : public DecomposedExpression {
public:
ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
ResultDisposition::Flags resultDisposition,
char const* secondArg = "" );
~ResultBuilder();
template<typename T>
ExpressionLhs<T const&> operator <= ( T const& operand );
ExpressionLhs<bool> operator <= ( bool value );
template<typename T>
ResultBuilder& operator << ( T const& value ) {
stream().oss << value;
return *this;
}
ResultBuilder& setResultType( ResultWas::OfType result );
ResultBuilder& setResultType( bool result );
void endExpression( DecomposedExpression const& expr );
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
AssertionResult build() const;
AssertionResult build( DecomposedExpression const& expr ) const;
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
void captureResult( ResultWas::OfType resultType );
void captureExpression();
void captureExpectedException( std::string const& expectedMessage );
void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
void handleResult( AssertionResult const& result );
void react();
bool shouldDebugBreak() const;
bool allowThrows() const;
template<typename ArgT, typename MatcherT>
void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
void setExceptionGuard();
void unsetExceptionGuard();
private:
AssertionInfo m_assertionInfo;
AssertionResultData m_data;
CopyableStream &stream()
{
if(!m_usedStream)
{
m_usedStream = true;
m_stream().oss.str("");
}
return m_stream();
}
static CopyableStream &m_stream()
{
static CopyableStream s;
return s;
}
bool m_shouldDebugBreak;
bool m_shouldThrow;
bool m_guardException;
bool m_usedStream;
};
} // namespace Catch
// Include after due to circular dependency:
#include "catch_expression_lhs.hpp"
namespace Catch {
template<typename T>
ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
return ExpressionLhs<T const&>( *this, operand );
}
inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
return ExpressionLhs<bool>( *this, value );
}
template<typename ArgT, typename MatcherT>
void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
char const* matcherString ) {
MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
setResultType( matcher.match( arg ) );
endExpression( expr );
}
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED

View File

@@ -1,173 +0,0 @@
/*
* Created by Phil on 28/5/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_RESULT_BUILDER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
#include "catch_result_builder.h"
#include "catch_context.h"
#include "catch_interfaces_config.h"
#include "catch_interfaces_runner.h"
#include "catch_interfaces_capture.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_wildcard_pattern.hpp"
namespace Catch {
ResultBuilder::ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
ResultDisposition::Flags resultDisposition,
char const* secondArg )
: m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ),
m_shouldDebugBreak( false ),
m_shouldThrow( false ),
m_guardException( false ),
m_usedStream( false )
{}
ResultBuilder::~ResultBuilder() {
#if defined(CATCH_CONFIG_FAST_COMPILE)
if ( m_guardException ) {
stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
captureResult( ResultWas::ThrewException );
getCurrentContext().getResultCapture()->exceptionEarlyReported();
}
#endif
}
ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
m_data.resultType = result;
return *this;
}
ResultBuilder& ResultBuilder::setResultType( bool result ) {
m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
return *this;
}
void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
// Flip bool results if FalseTest flag is set
if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
m_data.negate( expr.isBinaryExpression() );
}
getResultCapture().assertionRun();
if(getCurrentContext().getConfig()->includeSuccessfulResults() || m_data.resultType != ResultWas::Ok)
{
AssertionResult result = build( expr );
handleResult( result );
}
else
getResultCapture().assertionPassed();
}
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
m_assertionInfo.resultDisposition = resultDisposition;
stream().oss << Catch::translateActiveException();
captureResult( ResultWas::ThrewException );
}
void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
setResultType( resultType );
captureExpression();
}
void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
if( expectedMessage.empty() )
captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
else
captureExpectedException( Matchers::Equals( expectedMessage ) );
}
void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
AssertionResultData data = m_data;
data.resultType = ResultWas::Ok;
data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg);
std::string actualMessage = Catch::translateActiveException();
if( !matcher.match( actualMessage ) ) {
data.resultType = ResultWas::ExpressionFailed;
data.reconstructedExpression = actualMessage;
}
AssertionResult result( m_assertionInfo, data );
handleResult( result );
}
void ResultBuilder::captureExpression() {
AssertionResult result = build();
handleResult( result );
}
void ResultBuilder::handleResult( AssertionResult const& result )
{
getResultCapture().assertionEnded( result );
if( !result.isOk() ) {
if( getCurrentContext().getConfig()->shouldDebugBreak() )
m_shouldDebugBreak = true;
if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
m_shouldThrow = true;
}
}
void ResultBuilder::react() {
#if defined(CATCH_CONFIG_FAST_COMPILE)
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 throw statement
///////////////////////////////////////////////////////////////////
CATCH_BREAK_INTO_DEBUGGER();
}
#endif
if( m_shouldThrow )
throw Catch::TestFailureException();
}
bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
AssertionResult ResultBuilder::build() const
{
return build( *this );
}
// CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
// a temporary DecomposedExpression, which in turn holds references to
// operands, possibly temporary as well.
// It should immediately be passed to handleResult; if the expression
// needs to be reported, its string expansion must be composed before
// the temporaries are destroyed.
AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
{
assert( m_data.resultType != ResultWas::Unknown );
AssertionResultData data = m_data;
if(m_usedStream)
data.message = m_stream().oss.str();
data.decomposedExpression = &expr; // for lazy reconstruction
return AssertionResult( m_assertionInfo, data );
}
void ResultBuilder::reconstructExpression( std::string& dest ) const {
dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg);
}
void ResultBuilder::setExceptionGuard() {
m_guardException = true;
}
void ResultBuilder::unsetExceptionGuard() {
m_guardException = false;
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED

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