Compare commits

..

180 Commits

Author SHA1 Message Date
Martin Hořeňovský
15cf3caace v2.3.0 2018-07-23 10:12:15 +02:00
Martin Hořeňovský
12a8dfa2f2 Fix Listening reporter use of ReporterPreferences 2018-07-22 22:58:18 +02:00
Martin Hořeňovský
797d3b04df Reinstate CATCH_BUILD_TESTING CMake option 2018-07-22 18:01:42 +02:00
Martin Hořeňovský
82b8744b8c Direct construct empty StringRef in test macros 2018-07-22 14:13:34 +02:00
Martin Hořeňovský
ce80358306 Document Approx's UDL support 2018-07-15 17:38:57 +02:00
Henry Schreiner
283e2e6d41 Add float/int literal for Approx 2018-07-15 17:03:12 +02:00
Martin Hořeňovský
d6c7392b24 Add a new reporter customization point: reporting all assertions
By opting the JUnit and XML reporters into it, we no longer run
into problem where they underreport the results without `-s` flag.

Related to #1264, #1267, #1310
2018-07-14 20:51:02 +02:00
Martin Hořeňovský
9ee4c1db52 Allow disabling the implementation of the new output capture
As it turns out, some platforms do not provide things like `dup`,
or `std::tmpfile`, but they do provide streams...

Closes #1335
Related to #1311
2018-07-13 20:27:00 +02:00
Guillaume Egles
76790604f5 Properly unset tags variable. 2018-07-10 12:48:14 +02:00
Unknown
e21c6aa94d Fix the second Multiple-file example file link
Previously it pointed to the first file as well.
2018-07-09 15:47:03 +02:00
Martin Hořeňovský
7a59d5027f Link the example from CATCH_CONFIG_NOSTDOUT documentation 2018-07-08 13:58:44 +02:00
Martin Hořeňovský
c8941cccb5 Add an example on providing streams with CATCH_CONFIG_NOSTDOUT
Related to #1037
Closes #1290
2018-07-08 13:38:42 +02:00
Martin Hořeňovský
5eeb6aa361 Update Approx documentation
Fixes #1328
2018-07-05 17:28:00 +02:00
Martin Hořeňovský
1c1b447ede Properly guard CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER definition 2018-07-03 09:29:26 +02:00
Martin Hořeňovský
e1d81174db Add -Wmissing-declarations to the SelfTest project
This required some clean-up in our test files
2018-07-02 17:36:13 +02:00
Martin Hořeňovský
4846ad59e1 Remove obsolete test
`REQUIRE`, `CHECK` and many other macros already support expressions
with multiple template parameters without parenthesizing.
2018-07-02 17:32:47 +02:00
Martin Hořeňovský
ff2b3c85a7 Add comment explaining why we leak -Wparentheses under g++ 2018-07-02 17:28:45 +02:00
Martin Hořeňovský
b55424d3b2 Stop -Wunused-variable suppression leaking out of Catch's header
Previously it was leaking to suppress warnings on `SECTION`s,
but Clang's support for `_Pragma` is solid, so we can suppress
those locally.

Fixes #1317
2018-07-02 17:28:29 +02:00
Martin Hořeňovský
e69c7ce297 Add Discord badge to README 2018-07-01 20:48:21 +02:00
Martin Hořeňovský
7be8ba36c1 Install contrib when installing Catch using conan
Closes #1322
2018-07-01 19:04:50 +02:00
Stephen McDowell
ad120965cf fix link to single header version catch.hpp 2018-07-01 12:37:13 +02:00
Martin Hořeňovský
f460a7d8f9 Fix documentation of CATCH_CONFIG_FAST_COMPILE
Related to issue #1279
2018-06-30 12:31:46 +02:00
Martin Hořeňovský
ebf89000f1 Update thread safety documentation
Closes #1302
2018-06-28 22:35:42 +02:00
Martin Hořeňovský
7d00cb83f1 Remove unused benchmark project 2018-06-28 10:53:25 +02:00
Martin Hořeňovský
e69afb6252 Remove removed macros from documentation 2018-06-28 09:43:10 +02:00
Phil Nash
9fb38fcc14 Restored description field in SectionInfo for now - but marked it deprecated 2018-06-25 20:18:41 +01:00
Phil Nash
0f49a600b0 Added DYNAMIC_SECTION to CATCH_CONFIG_DISABLE builds 2018-06-25 19:22:57 +01:00
Phil Nash
5c0efa1cfc Added DYNAMIC_SECTION and implemented GIVEN/ WHEN/ THEN in terms of it 2018-06-25 19:19:21 +01:00
Phil Nash
1579744ddd Deprecated description in SECTION (still accepts it, for now, but doesn't use it anywhere) 2018-06-25 19:04:29 +01:00
Phil Nash
9b0e740e31 Changed approval tests path to match changes in CMakeLists.txt 2018-06-25 18:38:08 +01:00
Martin Hořeňovský
1af60ef5ab Separate Catch2Config from targets
This lets us add the installed helper scripts to the cmake module
path, letting CMake users just include them after requiring Catch2
package.
2018-06-24 12:32:22 +02:00
Martin Hořeňovský
3743295ca8 Stop conan package from installing Catch's helpers 2018-06-24 12:32:22 +02:00
Martin Hořeňovský
ed582bde4d Include contrib in installation 2018-06-24 12:32:22 +02:00
Martin Hořeňovský
6c1145d922 Improve pkg-config integration a bit 2018-06-24 12:32:22 +02:00
Paul le Roux
b957eb4172 Improve conan integration by using cmake install 2018-06-24 12:32:22 +02:00
Paul le Roux
0eb99fb569 Add option to not install documentation 2018-06-24 12:32:22 +02:00
Martin Hořeňovský
bf221583b1 Update CMake and build documentation 2018-06-24 12:32:22 +02:00
Martin Hořeňovský
44722f9ed3 Integrate CMake with <catch2/catch.hpp> include paths
This also goes for pkg-config installed by our CMake installation.

This includes

* Updating CMake version on Travis
* Adding a `Catch2` subfolder to the `single_include/` folder to
provide this include path both _inside_ the repository, and _outside_.
* Updated examples to build with the new paths
* Other general CMake cleanup
2018-06-24 12:32:22 +02:00
Phil Nash
35a57b070f Replaced use of std::rand with std::mt19937
This uses a global instance of the RNG
2018-06-15 14:35:47 +01:00
Phil Nash
1dce91d78e Reverted removal of #ifdef for chrono converters, and fixed in OC project a different way
- seems the #ifdef was necessary after all, because of the difference in the way the cpp files are included in the full project vs the single include
- in the OC project I moved the #include of catch_tostring.cpp first. That solves the project for now, but is a brittle solution
2018-06-12 15:37:06 +01:00
Phil Nash
b8553d62a3 Moved inline functions in cpp files into anon namespaces 2018-06-12 14:09:30 +01:00
Phil Nash
504607701b Updated XCode build settings 2018-06-12 13:43:28 +01:00
Phil Nash
788f81230f Fixed errors and warnings on OC project 2018-06-12 13:42:33 +01:00
Martin Hořeňovský
c5301bf8bf Updated release process documentation to reflect vcpkg autoupdate 2018-06-11 22:44:14 +02:00
Martin Hořeňovský
d2a130f243 v2.2.3 2018-06-06 23:19:06 +02:00
Julien Nitard
7be8a41adf Fix ambiguity in stringification
Happening when using clang and templated operators, clang cannot decide
between the operator provided by ReusableStringStream and the one provided
by the value value as both are templates. This is easily solved by calling
the operator<< through the member syntax.

Fixes #1285
2018-06-06 22:33:03 +02:00
Lyashenko Arsenii Maksimovich
021fcee636 Finish fixing invalid compilation using MinGW 2018-06-04 23:49:40 +02:00
Martin Hořeňovský
3a47b8b072 Add missing catch_platform include to compiler capabilities
This was removed in 64be2ad, to fix OS X approval tests. At the time
I couldn't investigate because I didn't have access to OS X, but this
fixed it (and since we don't have MinGW in CI, the breakage went
unnoticed).

As it turns out, piece-wise compilation of the Compact
reporter had broken OS X detection for a long time, and fixing it
was what broke the approvals. After the approval scripts were
changed to compensate, this change passes approval tests and fixes
2018-06-04 23:19:55 +02:00
Martin Hořeňovský
2771a8ee9a Normalize OS X specific pass/fail strings in approvals 2018-06-04 23:19:55 +02:00
Cristian Morales Vega
7abd7db2c8 Fix minor typo in the documentation 2018-06-01 22:24:49 +02:00
BiCapitalization
88d7b8da25 Ensure stack size for POSIX signal handling is sufficient
Until now, the stack size for POSIX signal handling was determined by
the implementation defined limit `STKSZ`, which in some cases turned out
to be insufficient, leading to stack overflow inside the signal handler.
The new size, which was determined experimentally, is the larger of 32kb
or `MINSTKSZ`.

Fixes #1225
2018-05-29 22:29:04 +02:00
Martin Hořeňovský
df0b0e64e1 Make FALLBACK_STRINGIFIER documentation more explicit
Related to #1024
2018-05-14 21:03:07 +02:00
Martin Hořeňovský
4c7b7d04fe Move FALLBACK_STRINGIFIER to before the enum and range fallbacks
This should align more closely with the intended semantics, where
types without `StringMaker` specialization or `operator<<` overload
are passed down to the user defined fallback stringifier.

Related to #1024
2018-05-14 20:38:05 +02:00
Rupert Steel
90988f578c Enable console colour in the approval tests on windows. 2018-05-14 09:41:18 +02:00
Martin Hořeňovský
e5fe3e877a Ensure platform-independent output from SpecialException::what 2018-05-12 20:37:13 +02:00
Martin Hořeňovský
6c5c4c43a0 Add stringification support to std::exception and deriving classes
This support is based on overriden `std::exception::what` method, so
if an exception does not do so meaningfully, the message is still
pointless.

This is only used as a fallback, both `StringMaker` specialization and
`operator<<` overload have priority..
2018-05-12 17:46:25 +02:00
Martin Hořeňovský
c323658483 Fix broken YAML in a way that codecov understands
Theoretically the previous was not a valid YAML at all, but it is
fairly common for parsers to accept it, just in a wrong way. This
results in a configuration where only the last value for duplicate
keys is taken, instead of a hard error.
2018-05-10 14:49:40 +02:00
Martin Hořeňovský
db570b7e24 Split list of examples into "done" and "planned".
Closes #1282
2018-05-09 22:49:04 +02:00
Martin Hořeňovský
0074926e5c Provide a polyfill over std::to_string
Android apparently does not support `std::to_string`, so we add a
small polyfill over it. Right now only the ULP matcher uses it,
but we have had plans to use it in `StringMaker<int>` and friends,
as it performs a lot better than `std::stringstream` based
stringification on MSVC.

See #1280 for more details
2018-05-09 21:47:42 +02:00
Markus Reitboeck
6496c51c95 do not strip spaces from cmake discovered test names
this fixes #1265
2018-05-09 18:00:05 +02:00
Markus Reitboeck
3dd523bdf5 Add gdbinit and lldbinit files with commands to skip stepping into Catch code during debugging
The commands provided have to be executed in the current gdb/lldb session or copied
into the users ~/.gdbinit ~/.lldbinit files to permanently skip debugging Catch code.

Fixes #904
2018-05-09 17:46:31 +02:00
Christopher Di Bella
8d5d49299b Added GCC 8 to Travis. Updated test so that it warning isn't triggered. 2018-05-06 12:06:39 +02:00
Christopher Di Bella
d0287e3b56 Updated Travis for LLVM 6.0 2018-05-06 11:50:03 +02:00
Palotás Boldizsár
dd99a66cf4 Add documentation for --use-colour
The documentation added is based on output from `-?` (help),
and comments to #590.
2018-05-06 11:37:00 +02:00
Martin Hořeňovský
ae590fe216 Only use tmpfile workaround for MSVC and not MinGW and friends
Fixes #1270
2018-04-30 23:19:39 +02:00
Christian Berger
7f791fa08f Suggestion for adding libcluon that is also using Catch2 for testing 2018-04-30 16:02:41 +02:00
Martin Hořeňovský
0510d4755f Fix missing include and wrong comment format
While the comment format was valid C++, it breaks our tooling badly.
I opened up a github issue for our tooling, because unexpected
formatting of a block comment should not silently generate invalid
single header file, see #1269.
2018-04-30 15:15:59 +02:00
Martin Hořeňovský
e92b9c07c3 Add an experimental new way of capturing stdout/stderr
Unlike the relatively non-invasive old way of capturing stdout/stderr,
this new way is also able to capture output from C's stdlib functions
such as `printf`. This is done by redirecting stdout and stderr file
descriptors to a file, and then reading this file back.

This approach has two sizeable drawbacks:
1) Performance, obviously. Previously an installed capture made the
program run faster (as long as it was then discarded), because a call
to `std::cout` did not result in text output to the console. This new
capture method in fact forces disk IO. While it is likely that any
modern OS will keep this file in memory-cache and might never actually
issue the IO to the backing storage, it is still a possibility and
calls to the file system are not free.

2) Nonportability. While POSIX is usually assumed portable, and this
implementation relies only on a very common parts of it, it is no
longer standard C++ (or just plain C) and thus might not be available
on some obscure platforms. Different C libs might also implement the
relevant functions in a less-than-useful ways (e.g. MS's `tmpfile`
generates a temp file inside system folder, so it will not work
without elevated privileges and thus is useless).

These two drawbacks mean that, at least for now, the new capture is
opt-in. To opt-in, `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` needs to be
defined in the implementation file.

Closes #1243
2018-04-29 22:25:49 +02:00
Ian Hattendorf
88a6ff0b65 Cast to unsigned char when using std::isalnum
std::isalnum expects an int in the range of unsigned char or -1 (EOF),
otherwise it exhibits undefined behavior. Casting from char to unsigned
char avoids this.

MSVC warns about this when compiling with /analyze.
2018-04-29 20:28:35 +02:00
Marcus Näslund
9e7c281e6e Minor fixes to python scripts by pycodestyle 2018-04-27 18:57:18 +02:00
Martin Hořeňovský
64be2ad96c Remove superfluous include and fix comment 2018-04-26 21:44:07 +02:00
Martin Hořeňovský
c651f239f0 Detect MinGW as Windows platform w/o SEH
Fixes #1257
2018-04-22 18:46:54 +02:00
Marcus Näslund
43769a19f7 Changed to c++ style includes 2018-04-21 15:58:05 +02:00
Barry
200d3ad824 Support for parenthesizing types with commas. 2018-04-20 15:11:09 +02:00
Martin Hořeňovský
aa7b0c9104 Fix generating single header using Python3 2018-04-19 22:03:25 +02:00
Martin Hořeňovský
375f2052bd Use io.open in approvalTests.py regardless of Python version
Both Python 2.7 and 3.x support full-featured io.open, so we
can avoid using a polyfill over this.
2018-04-19 22:02:31 +02:00
Tom Hughes
dc6b83bec9 Support Python3 in approval tests 2018-04-16 21:19:13 +02:00
Martin Hořeňovský
f00257e374 Call listeners before calling reporters
Catch2's documentation promises that listeners are called _before_
reporters, but because of the previous implementation, they were
called _after_ reporters. This commit fixes that.

Closes #1234
2018-04-07 12:25:03 +02:00
Martin Hořeňovský
414dcae34a Allow only 1 reporter at a time 2018-04-07 12:05:29 +02:00
Martin Hořeňovský
d2d8455b57 v2.2.2 2018-04-06 12:11:22 +02:00
Martin Hořeňovský
ab30621138 Fix stringifying static array of unsigned chars
The fix leaves an open question: should we keep treating refs
to static array of chars as strings, or should we instead
use `strnlen` to check if it is null-terminated within the buffer

Fixes #1238
2018-04-06 11:43:12 +02:00
Martin Hořeňovský
1ca8f43b01 Add PredicateMatcher that takes an arbitrary predicate functions
Also adds `Predicate` helper function to create `PredicateMatcher`.
Because of limitations in type inference it needs to be explicitly
typed, like so
`Predicate<std::string>([](std::string const& str) { ... })`.
It also takes an optional second argument for description of the
predicate.

It is possible to infer the argument with sufficient TMP, see
https://stackoverflow.com/questions/43560492/how-to-extract-lambdas-return-type-and-variadic-parameters-pack-back-from-gener/43561563#43561563
but I don't think that the magic is worth introducing ATM.

Closes #1236
2018-04-04 11:14:19 +02:00
David Aue
dfb83f20e9 Add stringification methods for CLR objects 2018-04-03 19:06:16 +02:00
Alexis Jeandet
319bddd5b8 Small fix to generate pc with include path
In CMake module both include and include/catch are added includes
lookup path. Examples are built with #include "catch.hpp" not
#include "catch/catch.hpp". This should be the same with pkg-config.

Signed-off-by: Alexis Jeandet <alexis.jeandet@member.fsf.org>
2018-04-02 21:38:17 +02:00
Martin Hořeňovský
931441251e Add an early bailout out of benchmark timer calibration
Specific platforms (e.g. TDM-GCC) can have terrible timer resolution,
and our checking code will then loop for an inordinate amount of time.
This change will make it so that the calibration gives up after 3
seconds and just uses the already measured values.

This leaves one open question, how to signal that the resolution
is terrible and benchmarking should not happen?

Fixes #1237
2018-04-01 22:50:39 +02:00
Martin Hořeňovský
ea1f326261 Fix potential for false negative CI results on coverage collection 2018-04-01 14:36:55 +02:00
Mike
3641706923 Leak less GCC warnings suppressions out of Catch 2018-04-01 13:57:05 +02:00
Martin Hořeňovský
3b801c4fda Modify XML encoder to hex-encode invalid UTF-8 sequences
There are still some holes, e.g. we leave surrogate pairs be
even though they are not a part of valid UTF-8, but this might
be for the better -- WTF-8 does support surrogate pairs inside
text.

Closes #1207
2018-03-27 16:49:14 +02:00
Martin Hořeňovský
e11508b48a Disable PIP's version check on AppVeyor 2018-03-22 15:19:09 +01:00
Zsolt Parragi
886d799b79 Fix clang-tidy 6 diagnostic about virtual call in destructor 2018-03-21 17:05:15 +01:00
jsc
8b78087412 Fix bug in WithinAbs::match() and add tests for it 2018-03-21 13:47:12 +01:00
Martin Hořeňovský
6c99b04c87 Allow VS 2017 failures
VS 2017 has an annoying bug, where the result of `__FILE__`
substitution is always lower-cased. This breaks approval tests
and I am not quite convinced that we should fully normalized paths
to accomodate this bug.

We need to remember to undo this in the future though.
2018-03-21 13:41:20 +01:00
Martin Hořeňovský
0a34cc201e v2.2.1 2018-03-11 12:04:28 +01:00
Martin Hořeňovský
11c89a5f7d Bring in Clara v1.1.4
This fixes #1214
2018-03-09 10:37:56 +01:00
Martin Hořeňovský
dc3e7f9cf7 Fix incorrectly clamped return value
Fixes #1215
2018-03-09 10:00:55 +01:00
Martin Hořeňovský
d14b7563c2 v2.2.0 2018-03-07 11:06:15 +01:00
Martin Hořeňovský
a3d3a633b2 Don't build dev-appveyor* branches on TravisCI 2018-03-07 10:53:09 +01:00
Martin Hořeňovský
8d4796309f Merge pull request #1206 from zemasoft/master
Introduce support for DJGPP cross compiler
2018-03-07 10:47:18 +01:00
Martin Hořeňovský
552589f25b Merge branch 'master' into master 2018-03-07 10:37:50 +01:00
Tomas Zeman
95c849f613 Introduce support for DJGPP cross compiler
DJGPP cross compiler is targeting DOS which does not support POSIX
signals. Probably for the same reason (targeting DOS) this compiler
does not support wide characters.
2018-03-07 10:35:32 +01:00
Tomas Zeman
352853ed7e Introduce conditional wchar_t (and std::wstring) support
The support is turned on by default but the user might need to be able
to turn it off which is now possible by defining CATCH_CONFIG_NO_WCHAR.
2018-03-07 10:35:31 +01:00
Josh Soref
b11175548a Fixup various spelling errors (#1208) 2018-03-07 10:08:35 +01:00
Bastian Dörig
d38f782995 Ensure Catch2ConfigVersion.cmake is installed properly
The old version would lead to error when Catch was installed
as a subproject. The file would be written to the subproject's
build directory and then would not be installed properly.
2018-03-07 09:42:58 +01:00
Martin Hořeňovský
dc8a8e6371 Speed up AppVeyor build times
* Examples are no longer built for all images
* Coverage is no longer collected from every build
* The number of configurations is reduced
2018-03-06 22:46:49 +01:00
Martin Hořeňovský
9d1858b195 Simplify internal configuration of POSIX signals 2018-03-06 17:58:37 +01:00
Martin Hořeňovský
1d1f8dc992 Stop installing lcov in builds without COVERAGE=1 2018-03-06 15:38:22 +01:00
Martin Hořeňovský
1466686ade Speed up TravisCI build
* Examples are no longer built on all travis images
* Coverage is no longer collected from all travis images
* Valgrind is no longer used with all travis images

This should greatly reduce the amount of compiling, downloading
binaries and general work the common images do.
2018-03-06 15:24:12 +01:00
Martin Hořeňovský
93db01c647 Fix C++14 toggle for OSX build 2018-03-05 15:09:25 +01:00
Martin Hořeňovský
2e285b9579 Use char const * const * for Session::run
Needed to embed newer version of Clara

Closes #1178
Closes #1031
2018-03-04 17:58:27 +01:00
Martin Hořeňovský
d2ddb997a7 Cleanup for performance reasons
* Eliminated some copies
* Made makeTestCase fit into 4 arguments -- avoids spills on Win64
* Made string literals into StringRef literals
2018-03-02 16:24:35 +01:00
Tomas Zeman
865d5f59b4 Fix 'defined but not used' warning
The warning occurred when !CATCH_CONFIG_WINDOWS_SEH
&& !CATCH_CONFIG_POSIX_SIGNALS.
2018-03-01 13:37:23 +01:00
Martin Hořeňovský
05cd05743a Provide a public method to get StringRef's underlying pointer
This allows reducing the amount of friends needed for its interface
and some extra tricks later.

The bad part is that the pointer can become invalidated via
calls to other StringRef's public methods, but c'est la vie.
2018-02-28 22:49:00 +01:00
Martin Hořeňovský
950ccf4749 StringRef appends itself to std::string efficiently 2018-02-28 16:02:25 +01:00
Martin Hořeňovský
cf4b7eead9 Document CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS macro
Also fix how it can be disabled.
2018-02-25 21:22:38 +01:00
Martin Hořeňovský
7b6e49d795 Simplify logic selecting between signal handling/SEH/nothing
It was a bit of a mess previously
2018-02-23 14:56:07 +01:00
Martin Hořeňovský
0c5df42c28 Fix how windows.h is included in our files.
To prevent bugs with stitching system headers inside Catch,
the proxy header is responsible for guarding against inclusion
on Linux, rather than the includers.

Might be related to #1197
2018-02-23 12:40:12 +01:00
Martin Hořeňovský
4e57661919 StringRef will not take ownership when writing itself to stream
This also fixes some tests that were previously failing unnoticed - WTF?
2018-02-17 20:41:50 +01:00
Martin Hořeňovský
5a8f9c84dd Fix doubled line in baselines 2018-02-16 22:10:39 +01:00
Martin Hořeňovský
f988b4eb35 Covered more translation possibilities 2018-02-15 19:58:49 +01:00
Martin Hořeňovský
c8d765a575 Cleanup some tests 2018-02-15 16:06:35 +01:00
Martin Hořeňovský
da783abee9 Move fallback conversion after enum-check 2018-02-15 16:06:35 +01:00
Martin Hořeňovský
c0267e5c20 Add test for overriding the fallback stringifier 2018-02-15 16:06:35 +01:00
Phil Nash
bb84f0788a Removed unnecessary use of ostringstream from catch_enforce.h 2018-02-15 13:59:02 +00:00
Nils Deppe
e84768fff1 Add SpECTRE project to list of users. 2018-02-14 08:31:33 +01:00
Martin Hořeňovský
31673ee0ca Document CATCH_CONFIG_DEFAULT_REPORTER macro 2018-02-11 18:10:28 +01:00
Martin Hořeňovský
34d7a33574 Add a way to change fallback stringifier
This allows reuse of projects existing stringification machinery

Closes #1024
2018-02-11 16:31:12 +01:00
Martin Hořeňovský
082c3b84bc Fix typos in documentation 2018-02-10 22:16:32 +01:00
Martin Hořeňovský
ef2e112561 Disable POSIX signals for Emscripten
Related to #1114
2018-02-10 20:42:08 +01:00
Martin Hořeňovský
a90305f857 Add another known bug to limitations.md
Related to #1183
2018-02-10 13:51:33 +01:00
Martin Hořeňovský
543c9d3a67 Set patch coverage check to target 80% 2018-02-09 20:09:55 +01:00
dvirtz
ca8470fbad https://github.com/catchorg/Catch2/issues/1175 - don't list hidden tests by default 2018-02-09 19:55:40 +01:00
dvirtz
355b3f9952 Add option to warn when no tests ran
Closes #1158
2018-02-09 18:49:36 +01:00
Martin Hořeňovský
7cbd0b587a v2.1.2 2018-02-09 17:10:27 +01:00
Martin Hořeňovský
2f15ccd4d3 Passthrough error code from coverage helper 2018-02-09 16:54:10 +01:00
Martin Hořeňovský
8f3fc15b73 Update version of Clara
Fixes #1165
2018-02-09 16:50:19 +01:00
Martin Hořeňovský
e13d9cab02 Keep .py files with LF endings so they can be executed from bash 2018-02-09 16:49:35 +01:00
Martin Hořeňovský
414e2fa946 Make embedClara.py executable 2018-02-09 16:49:21 +01:00
Martin Hořeňovský
b5ef68b044 Force MSVC to use utf-8 2018-02-08 15:44:33 +01:00
Martin Hořeňovský
681f5daa13 Update approval tests 2018-02-08 15:00:56 +01:00
Martin Hořeňovský
3b6fda3c1b Add tests for StringRef::numberOfCharacters 2018-02-08 13:10:12 +01:00
Martin Hořeňovský
1b2fa601c6 Remove superfluous comment 2018-02-08 13:09:02 +01:00
Daniel J. Rollins
39bfc6e82b Export Catch as a CMake package and 'linkable' target
Create a namespaced Catch2::Catch target that is 'linkable' through
`target_link_libraries()` and export it so it is findable through
`find_package()`.

`find_package()` will find versions with the same major number and with
minor number >= requested.

This makes catch a lot easier to use in CMake-based projects. Whether it
is found using `find_package` or included in the client project as a
subdirectory, the client can include the catch headers per-target with
`target_include_directories(target PRIVATE Catch2::Catch).

Example usage:

    cmake_minimum_required(VERSION 3.1)

    # include Catch2 as subdirectory or installed package
    # add_subdirectory(Catch2)
    find_package(Catch2 VERSION 2.1.0 REQUIRED)

    add_executable(tests tests/catch_main.cpp)
    target_link_libraries(tests PRIVATE Catch2::Catch)
2018-02-08 12:18:42 +01:00
Martin Hořeňovský
ba6d33fb8c Enable -Wpedantic, fix unconditional use of C++14 extension 2018-02-05 10:04:59 +01:00
Zachary Michaels
4be81d3588 Remove unnecessary semicolons 2018-02-05 10:03:51 +01:00
Josh Lospinoso
5201e92564 Redirect std::uncaught_exception to Catch::uncaught_exception
This means that only one place needs to work with warnings from
the deprecation of `std::uncaught_exception()` in C++17.

Closes #1162.
2018-02-02 15:36:15 +01:00
Martin Hořeňovský
5e484862f2 Add Catch::is_range to documentation 2018-02-01 20:29:49 +01:00
philsquared
5713381d06 Fixes for cygwin 2018-02-01 16:14:20 +00:00
Martin Hořeňovský
1ab6be30a2 Add a BrightYellow colour, also use it for reconstructed exprs
Closes #979
2018-02-01 14:58:33 +00:00
Martin Hořeňovský
126850e76b Prefer operator<< to range-based stringification
Fixes #1172
2018-02-01 14:07:23 +01:00
George Fotopoulos
5e8df1c384 Update opensource-users.md 2018-01-28 21:05:24 +01:00
Martin Hořeňovský
44dbda9f01 Add CATCH_VERSION_* defines for external use
I wonder how much use they will actually see, but their cost is
fairly minor.

Closes #1131
2018-01-26 20:56:14 +01:00
Phil Nash
ca2455e6e6 Fixed NoAssertions warning 2018-01-26 16:52:28 +00:00
Martin Hořeňovský
42213d4c31 Keep LICENCE.txt with LF as line endings for easy hashing 2018-01-26 16:45:32 +01:00
Martin Hořeňovský
62dae592c3 v2.1.1 2018-01-26 16:06:07 +01:00
Martin Hořeňovský
9a5705411a Add % to codecov coverage decrease threshold
Maybe now it will work?
2018-01-26 15:45:31 +01:00
Martin Hořeňovský
a1aefce6e4 Guard against CLR exceptions when translating exceptions
Partially fixes #1138, need to decide what to do about structured
exceptions.
2018-01-24 12:11:29 +01:00
Phil Nash
d5959907f5 Added Catch::clara namespace to doc for adding Opt
- Thanks to sakamoto-poteko in #1159 for point out its ommission
2018-01-23 07:44:09 +00:00
Phil Nash
31e6499e64 Embed Clara v1.1.1 2018-01-22 15:08:28 +00:00
David Seifert
b0f4f16ee0 Namespace Catch CMake options 2018-01-18 23:20:26 +01:00
David Seifert
1e3ddbb496 Specify VERSION in modern CMake 2018-01-18 23:20:26 +01:00
Martin Hořeňovský
15ad95c8db Make generateSingleHeader compatible with Python 2.7 2018-01-18 16:28:19 +01:00
Martin Hořeňovský
00a10d5a5e Return fixed codecov settings 2018-01-18 13:51:32 +01:00
David Seifert
0d687a15d3 Change CMake project name to 'Catch2' 2018-01-18 13:13:39 +01:00
David Seifert
bdf431c400 Install documentation 2018-01-18 13:13:39 +01:00
David Seifert
a0359980f0 Use CTest to control test suite via BUILD_TESTING 2018-01-18 13:13:39 +01:00
David Seifert
8d4074aad9 Use GNUInstallDirs module
* `GNUInstallDirs` is a standardised way to
  change paths, which makes systems integration
  easier and allows for a more consistent user
  experience.
2018-01-18 13:13:39 +01:00
Martin Hořeňovský
f0f40a0dbf Ensure that the single header is kept with LFs 2018-01-18 12:44:59 +01:00
Martin Hořeňovský
fa4fd7f296 Modify codecov.yml again 2018-01-15 13:59:48 +01:00
Martin Hořeňovský
07c84adfba Allow disabling -Werror in CMake
Related to #1152
2018-01-14 18:14:11 +01:00
Martin Hořeňovský
8d854c689b Provide useful and unambigous stringification for static arrays 2018-01-14 18:06:43 +01:00
Martin Hořeňovský
f0909dfe02 Add yet another expansion of INF macro
Closes #1151
2018-01-14 17:04:36 +01:00
Martin Hořeňovský
de36b2ada6 Fix compilation for types where relops don't return bool
Closes #1147
2018-01-12 15:49:56 +01:00
Martin Hořeňovský
9700ee4fc0 Update CTest autodiscovery documentation 2018-01-12 12:28:14 +01:00
Martin Hořeňovský
bbda8cd77c Update reporter docs with their new location 2018-01-12 12:20:52 +01:00
Martin Hořeňovský
4575594bbf Comment why the return code is clamped 2018-01-12 11:49:48 +01:00
Martin Hořeňovský
c053dca26e Update path to vcpkg's portfile 2018-01-12 11:09:46 +01:00
garethsb-sony
3d7104c124 Catch `catch_discover_tests`
Copied from [Dynamic Catch test discovery in CMake](https://gist.github.com/garethsb/a01ed0dbd4977d439c16200640549935), which was inspired by [Dynamic Google Test Discovery in CMake 3.10](https://blog.kitware.com/dynamic-google-test-discovery-in-cmake-3-10/).

Original source code:

- Adapted by [Gareth Sylvester-Bradley](https://github.com/garethsb) from [GoogleTest ``gtest_discover_tests``](https://gitlab.kitware.com/cmake/cmake/merge_requests/1056).
- BSD 3-clause "New" or "Revised" License.
- Copyright 2000-2017 Kitware, Inc. and Contributors. All rights reserved.
2018-01-11 21:17:12 +01:00
Martin Hořeňovský
6441c20a2c Modify codecov behaviour 2018-01-11 21:13:52 +01:00
Martin Hořeňovský
5774c4f9c2 Update release process with the need to release reporters 2018-01-11 21:06:35 +01:00
Martin Hořeňovský
2bc33dd04d Fix script responsible for updating release link in the readme 2018-01-10 14:02:15 +01:00
178 changed files with 7446 additions and 2592 deletions

13
.gitattributes vendored
View File

@@ -8,4 +8,15 @@
*.hpp text
# Windows specific files should retain windows line-endings
*.sln text eol=crlf
*.sln text eol=crlf
# Keep executable scripts with LFs so they can be run after being
# checked out on Windows
*.py text eol=lf
# Keep the single include header with LFs to make sure it is uploaded,
# hashed etc with LF
single_include/*.hpp eol=lf
# Also keep the LICENCE file with LFs for the same reason
LICENCE.txt eol=lf

View File

@@ -1,12 +1,17 @@
language: cpp
sudo: false
branches:
except:
- /dev-appveyor.*/
common_sources: &all_sources
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
- llvm-toolchain-trusty-3.9
- llvm-toolchain-trusty-4.0
- llvm-toolchain-trusty-5.0
- llvm-toolchain-trusty-6.0
matrix:
include:
@@ -17,145 +22,169 @@ matrix:
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'clang-3.5']
env: COMPILER='clang++-3.5' VALGRIND=1
packages: ['clang-3.5']
env: COMPILER='clang++-3.5'
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'clang-3.6']
env: COMPILER='clang++-3.6' VALGRIND=1
packages: ['clang-3.6']
env: COMPILER='clang++-3.6'
# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
# - os: linux
# compiler: clang
# addons:
# apt:
# sources: *all_sources
# packages: ['valgrind', 'clang-3.7']
# env: COMPILER='clang++-3.7' VALGRIND=1
# Clang 3.7 is intentionally skipped as we cannot get it easily on
# TravisCI container
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'clang-3.8']
env: COMPILER='clang++-3.8' VALGRIND=1
packages: ['lcov', 'clang-3.8']
env: COMPILER='clang++-3.8'
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-3.9', 'valgrind', 'lcov']
env: COMPILER='clang++-3.9' VALGRIND=1
packages: ['clang-3.9']
env: COMPILER='clang++-3.9'
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-4.0', 'valgrind', 'lcov']
env: COMPILER='clang++-4.0' VALGRIND=1
packages: ['clang-4.0']
env: COMPILER='clang++-4.0'
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-5.0', 'valgrind', 'lcov']
env: COMPILER='clang++-5.0' VALGRIND=1
packages: ['clang-5.0']
env: COMPILER='clang++-5.0'
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-6.0']
env: COMPILER='clang++-6.0'
# 2/ Linux GCC Builds
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['valgrind', 'lcov', 'g++-4.8']
env: COMPILER='g++-4.8' VALGRIND=1
sources: *all_sources
packages: ['g++-4.8']
env: COMPILER='g++-4.8'
- os: linux
compiler: gcc
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'g++-4.9']
env: COMPILER='g++-4.9' VALGRIND=1
packages: ['g++-4.9']
env: COMPILER='g++-4.9'
- os: linux
compiler: gcc
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'g++-5']
env: COMPILER='g++-5' VALGRIND=1
packages: ['g++-5']
env: COMPILER='g++-5'
- os: linux
compiler: gcc
addons: &gcc6
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'g++-6']
env: COMPILER='g++-6' VALGRIND=1
packages: ['g++-6']
env: COMPILER='g++-6'
- os: linux
compiler: gcc
addons: &gcc7
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'g++-7']
env: COMPILER='g++-7' VALGRIND=1
packages: ['g++-7']
env: COMPILER='g++-7'
- os: linux
compiler: gcc
addons: &gcc8
apt:
sources: *all_sources
packages: ['g++-8']
env: COMPILER='g++-8'
# 3b/ Linux C++14 Clang builds
# Note that we need newer libstdc++ for C++14 support
- os: linux
compiler: clang
addons:
apt:
packages: ['clang-3.8', 'valgrind', 'lcov', 'libstdc++-6-dev']
packages: ['clang-3.8', 'libstdc++-6-dev']
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
env: COMPILER='clang++-3.8' CPP14=1 VALGRIND=1
env: COMPILER='clang++-3.8' CPP14=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-3.9', 'valgrind', 'lcov', 'libstdc++-6-dev']
env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1
packages: ['clang-3.9', 'libstdc++-6-dev']
env: COMPILER='clang++-3.9' CPP14=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-4.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1
packages: ['clang-4.0', 'libstdc++-6-dev']
env: COMPILER='clang++-4.0' CPP14=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-5.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1
packages: ['clang-5.0', 'libstdc++-6-dev']
env: COMPILER='clang++-5.0' CPP14=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-6.0', 'libstdc++-6-dev']
env: COMPILER='clang++-6.0' CPP14=1
# 4a/ Linux C++14 GCC builds
- os: linux
compiler: gcc
addons: *gcc6
env: COMPILER='g++-6' CPP14=1 VALGRIND=1
env: COMPILER='g++-6' CPP14=1
- os: linux
compiler: gcc
addons: *gcc7
env: COMPILER='g++-7' CPP14=1 VALGRIND=1
env: COMPILER='g++-7' CPP14=1
- os: linux
compiler: gcc
addons: *gcc8
env: COMPILER='g++-8' CPP14=1
# 5/ OSX Clang Builds
- os: osx
@@ -181,15 +210,46 @@ matrix:
- os: osx
osx_image: xcode9.1
compiler: clang
env: COMPILER='clang++' USE_CPP14=1
env: COMPILER='clang++' CPP14=1
# 6/ Special builds -- examples, coverage, valgrind, etc.
- os: linux
compiler: gcc
addons:
apt:
sources: *all_sources
packages: ['lcov', 'g++-7']
env: COMPILER='g++-7' CPP14=1 EXAMPLES=1 COVERAGE=1
- os: linux
compiler: clang
addons:
apt:
packages: ['clang-3.8', 'lcov']
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
env: COMPILER='clang++-3.8' EXAMPLES=1 COVERAGE=1
- os: linux
compiler: gcc
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'lcov', 'g++-7']
env: COMPILER='g++-7' CPP14=1 VALGRIND=1
- os: osx
osx_image: xcode9.1
compiler: clang
env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1
install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz"
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz"
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
@@ -202,25 +262,24 @@ before_script:
# Regenerate single header file, so it is tested in the examples...
- python scripts/generateSingleHeader.py
- |
# Use Debug builds for running Valgrind and building examples
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON -DENABLE_COVERAGE=ON
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE}
# Don't bother with release build for coverage build
cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
script:
- |
cd Build-Debug
make -j 2
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
- cd Build-Debug
- make -j 2
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
# Coverage collection does not work for OS X atm
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]] && [[ "${COVERAGE}" == "1" ]]; then
make gcov
make lcov
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
fi
# Go to release build
cd ../Build-Release
make -j 2
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
- # Go to release build
- cd ../Build-Release
- make -j 2
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2

View File

@@ -0,0 +1,10 @@
@PACKAGE_INIT@
# Avoid repeatedly including the targets
if(NOT TARGET Catch2::Catch2)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
include(${CMAKE_CURRENT_LIST_DIR}/Catch2Targets.cmake)
endif()

26
CMake/MiscFunctions.cmake Normal file
View File

@@ -0,0 +1,26 @@
#checks that the given hard-coded list contains all headers + sources in the given folder
function(CheckFileList LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
function(CheckFileListRec LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()

7
CMake/catch2.pc.in Normal file
View File

@@ -0,0 +1,7 @@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: Catch2
Description: A modern, C++-native, header-only, test framework for C++11
URL: https://github.com/catchorg/Catch2
Version: @Catch2_VERSION@
Cflags: -I${includedir}

View File

@@ -1,10 +1,28 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
project(CatchSelfTest)
# detect if Catch is being bundled,
# disable testsuite in that case
if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.3.0)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CTest)
option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
option(CATCH_BUILD_TESTING "Build SelfTest project" ON)
option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON)
option(USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
option(BUILD_EXAMPLES "Build documentation examples" OFF)
option(ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@@ -13,364 +31,154 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
set(HEADER_DIR ${CATCH_DIR}/include)
set(CATCH_VERSION_NUMBER 2.1.0)
if(USE_WMAIN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
endif()
#checks that the given hard-coded list contains all headers + sources in the given folder
function(CheckFileList LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
add_subdirectory(projects)
endif()
function(CheckFileListRec LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
# define the sources of the self test
# Please keep these ordered alphabetically
set(TEST_SOURCES
${SELF_TEST_DIR}/TestMain.cpp
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
${SELF_TEST_DIR}/UsageTests/Class.tests.cpp
${SELF_TEST_DIR}/UsageTests/Compilation.tests.cpp
${SELF_TEST_DIR}/UsageTests/Condition.tests.cpp
${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
${SELF_TEST_DIR}/UsageTests/Matchers.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(SURROGATE_SOURCES
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.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
)
CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
# Please keep these ordered alphabetically
set(TOP_LEVEL_HEADERS
${HEADER_DIR}/catch.hpp
${HEADER_DIR}/catch_with_main.hpp
)
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
# Please keep these ordered alphabetically
set(EXTERNAL_HEADERS
${HEADER_DIR}/external/clara.hpp
)
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
# Please keep these ordered alphabetically
set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_approx.h
${HEADER_DIR}/internal/catch_assertionhandler.h
${HEADER_DIR}/internal/catch_assertioninfo.h
${HEADER_DIR}/internal/catch_assertionresult.h
${HEADER_DIR}/internal/catch_capture.hpp
${HEADER_DIR}/internal/catch_capture_matchers.h
${HEADER_DIR}/internal/catch_clara.h
${HEADER_DIR}/internal/catch_commandline.h
${HEADER_DIR}/internal/catch_common.h
${HEADER_DIR}/internal/catch_compiler_capabilities.h
${HEADER_DIR}/internal/catch_config.hpp
${HEADER_DIR}/internal/catch_console_colour.h
${HEADER_DIR}/internal/catch_context.h
${HEADER_DIR}/internal/catch_debug_console.h
${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_decomposer.h
${HEADER_DIR}/internal/catch_default_main.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_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_leak_detector.h
${HEADER_DIR}/internal/catch_list.h
${HEADER_DIR}/internal/catch_matchers.h
${HEADER_DIR}/internal/catch_matchers_floating.h
${HEADER_DIR}/internal/catch_matchers_string.h
${HEADER_DIR}/internal/catch_matchers_vector.h
${HEADER_DIR}/internal/catch_message.h
${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_random_number_generator.h
${HEADER_DIR}/internal/catch_reenable_warnings.h
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
${HEADER_DIR}/internal/catch_reporter_registry.h
${HEADER_DIR}/internal/catch_result_type.h
${HEADER_DIR}/internal/catch_run_context.h
${HEADER_DIR}/internal/catch_benchmark.h
${HEADER_DIR}/internal/catch_section.h
${HEADER_DIR}/internal/catch_section_info.h
${HEADER_DIR}/internal/catch_session.h
${HEADER_DIR}/internal/catch_startup_exception_registry.h
${HEADER_DIR}/internal/catch_stream.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_test_case_info.h
${HEADER_DIR}/internal/catch_test_case_registry_impl.h
${HEADER_DIR}/internal/catch_test_case_tracker.h
${HEADER_DIR}/internal/catch_test_registry.h
${HEADER_DIR}/internal/catch_test_spec.h
${HEADER_DIR}/internal/catch_test_spec_parser.h
${HEADER_DIR}/internal/catch_text.h
${HEADER_DIR}/internal/catch_timer.h
${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_totals.h
${HEADER_DIR}/internal/catch_user_interfaces.h
${HEADER_DIR}/internal/catch_version.h
${HEADER_DIR}/internal/catch_wildcard_pattern.h
${HEADER_DIR}/internal/catch_windows_h_proxy.h
${HEADER_DIR}/internal/catch_xmlwriter.h
)
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_debug_console.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_interfaces_capture.cpp
${HEADER_DIR}/internal/catch_interfaces_config.cpp
${HEADER_DIR}/internal/catch_interfaces_exception.cpp
${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_runner.cpp
${HEADER_DIR}/internal/catch_interfaces_testcase.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_floating.cpp
${HEADER_DIR}/internal/catch_matchers_string.cpp
${HEADER_DIR}/internal/catch_message.cpp
${HEADER_DIR}/internal/catch_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
${HEADER_DIR}/internal/catch_random_number_generator.cpp
${HEADER_DIR}/internal/catch_reporter_registry.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_session.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.h
${HEADER_DIR}/reporters/catch_reporter_console.h
${HEADER_DIR}/reporters/catch_reporter_junit.h
${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.h
)
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
${TOP_LEVEL_HEADERS}
${EXTERNAL_HEADERS}
${INTERNAL_HEADERS}
${REPORTER_HEADERS}
)
# Provide some groupings for IDEs
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
# 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} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
target_include_directories(SelfTest PRIVATE ${HEADER_DIR})
if(USE_CPP14)
message(STATUS "Enabling C++14")
set_property(TARGET SelfTest PROPERTY CXX_STANDARD 14)
else()
message(STATUS "Enabling C++11")
set_property(TARGET SelfTest PROPERTY CXX_STANDARD 11)
endif()
set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
if (ENABLE_COVERAGE)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
find_package(codecov)
add_coverage(SelfTest)
list(APPEND LCOV_REMOVE_PATTERNS "'/usr/*'")
coverage_evaluate()
endif()
# Add desired warnings
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Werror )
endif()
# Clang specific warning go here
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
# Actually keep these
target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
target_compile_options( SelfTest PRIVATE /w44265 /WX /w44061 /w44062 )
endif()
# configure unit tests via CTest
include(CTest)
add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
add_test(NAME ListTestNamesOnly COMMAND $<TARGET_FILE:SelfTest> --list-test-names-only)
set_tests_properties(ListTestNamesOnly PROPERTIES PASS_REGULAR_EXPRESSION "Regex string matcher")
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
if (USE_VALGRIND)
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
endif()
endif() # !NO_SELFTEST
if(BUILD_EXAMPLES)
if(CATCH_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
install(DIRECTORY "single_include/" DESTINATION "include/catch")
# add catch as a 'linkable' target
add_library(Catch2 INTERFACE)
# depend on some obvious c++11 features so the dependency is transitively added dependents
target_compile_features(Catch2
INTERFACE
cxx_alignas
cxx_alignof
cxx_attributes
cxx_auto_type
cxx_constexpr
cxx_defaulted_functions
cxx_deleted_functions
cxx_final
cxx_lambdas
cxx_noexcept
cxx_override
cxx_range_for
cxx_rvalue_references
cxx_static_assert
cxx_strong_enums
cxx_trailing_return_types
cxx_unicode_literals
cxx_user_literals
cxx_variadic_macros
)
target_include_directories(Catch2
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/single_include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
add_library(Catch2::Catch2 ALIAS Catch2)
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
INSTALL_DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# create and install an export set for catch target as Catch2::Catch
install(
TARGETS
Catch2
EXPORT
Catch2Targets
DESTINATION
${CMAKE_INSTALL_LIBDIR}
)
install(
EXPORT
Catch2Targets
NAMESPACE
Catch2::
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
COMPATIBILITY
SameMajorVersion
)
install(
DIRECTORY
"single_include/"
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}"
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install documentation
if(CATCH_INSTALL_DOCS)
install(
DIRECTORY
docs/
DESTINATION
"${CMAKE_INSTALL_DOCDIR}"
)
endif()
if(CATCH_INSTALL_HELPERS)
# Install CMake scripts
install(
FILES
"contrib/ParseAndAddCatchTests.cmake"
"contrib/Catch.cmake"
"contrib/CatchAddTests.cmake"
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install debugger helpers
install(
FILES
"contrib/gdbinit"
"contrib/lldbinit"
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
)
endif()
## Provide some pkg-config integration
# Don't bother on Windows
if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
set(PKGCONFIG_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
CACHE PATH "Path where catch.pc is installed"
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/catch.pc.in ${CMAKE_CURRENT_BINARY_DIR}/catch.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR})
endif()
set(PKGCONFIG_INSTALL_DIR
"${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
CACHE PATH "Path where catch2.pc is installed"
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2.pc.in
${CMAKE_CURRENT_BINARY_DIR}/catch2.pc
@ONLY
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/catch2.pc"
DESTINATION
${PKGCONFIG_INSTALL_DIR}
)

View File

@@ -5,9 +5,11 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/nerce2MiN6sVmfCi)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/Gcuv2Xx3wmWIPNzy)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.3.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!
@@ -32,5 +34,5 @@ This documentation comprises these three parts:
## More
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
* See [who else is using Catch2](docs/opensource-users.md#top)

View File

@@ -19,18 +19,53 @@ environment:
- additional_flags: "/D_UNICODE /DUNICODE"
wmain: 1
coverage: 0
# Have a coverage dimension
- additional_flags: ""
wmain: 0
coverage: 1
# Have an examples dimension
- additional_flags: ""
wmain: 0
examples: 1
matrix:
allow_failures:
- os: Visual Studio 2017
exclude:
- os: Visual Studio 2015
additional_flags: "/permissive- /std:c++latest"
init:
- git config --global core.autocrlf input
- os: Visual Studio 2015
additional_flags: "/D_UNICODE /DUNICODE"
# Exclude unwanted coverage configurations
- coverage: 1
platform: Win32
- coverage: 1
os: Visual Studio 2015
- coverage: 1
configuration: Release
# Exclude unwanted examples configurations
- examples: 1
platform: Win32
- examples: 1
os: Visual Studio 2015
- examples: 1
configuration: Release
install:
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { python -m pip install codecov }
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { .\misc\installOpenCppCoverage.ps1 }
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
# Win32 and x64 are CMake-compatible solution platform names.
# This allows us to pass %PLATFORM% to CMake -A.
@@ -54,7 +89,7 @@ before_build:
# build with MSBuild
build:
project: Build\CatchSelfTest.sln # path to Visual Studio solution or project
project: Build\Catch2.sln # path to Visual Studio solution or project
parallel: true # enable MSBuild parallel builds
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}

View File

@@ -1,9 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
Name: Catch
Description: Testing library for C++
Requires:
Version: @CATCH_VERSION_NUMBER@
Libs:
Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@/include

View File

@@ -1,10 +1,24 @@
codecov:
branch: master
coverage:
precision: 2
round: nearest
range: "60...90"
status:
project:
default:
threshold: 2%
patch:
default:
target: 80%
ignore:
- "projects/SelfTest"
- "**/catch_reporter_tap.hpp"
- "**/catch_reporter_automake.hpp"
- "**/catch_reporter_teamcity.hpp"
- "**/external/clara.hpp"
codecov:
branch: master
comment:
layout: "diff"

View File

@@ -1,19 +1,31 @@
#!/usr/bin/env python
from conans import ConanFile
from conans import ConanFile, CMake
class CatchConan(ConanFile):
name = "Catch"
version = "2.1.0"
version = "2.3.0"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared"
generators = "cmake"
exports_sources = "single_include/*"
url = "https://github.com/philsquared/Catch"
# Only needed until conan 1.5 is released
settings = "compiler", "arch"
exports_sources = "single_include/*", "CMakeLists.txt", "CMake/catch2.pc.in", "LICENSE.txt"
url = "https://github.com/catchorg/Catch2"
license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
def build(self):
pass
def package(self):
self.copy(pattern="catch.hpp", src="single_include", dst="include")
cmake = CMake(self)
cmake.definitions["BUILD_TESTING"] = "OFF"
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
cmake.definitions["CATCH_INSTALL_HELPERS"] = "ON"
cmake.configure()
cmake.install()
self.copy(pattern="LICENSE.txt", dst="licenses")
def package_id(self):
self.info.header_only()
self.info.header_only()

175
contrib/Catch.cmake Normal file
View File

@@ -0,0 +1,175 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
Catch
-----
This module defines a function to help use the Catch test framework.
The :command:`catch_discover_tests` discovers tests by asking the compiled test
executable to enumerate its tests. This does not require CMake to be re-run
when tests change. However, it may not work in a cross-compiling environment,
and setting test properties is less convenient.
This command is intended to replace use of :command:`add_test` to register
tests, and will create a separate CTest test for each Catch test case. Note
that this is in some cases less efficient, as common set-up and tear-down logic
cannot be shared by multiple test cases executing in the same instance.
However, it provides more fine-grained pass/fail information to CTest, which is
usually considered as more beneficial. By default, the CTest test name is the
same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
.. command:: catch_discover_tests
Automatically add tests with CTest by querying the compiled test executable
for available tests::
catch_discover_tests(target
[TEST_SPEC arg1...]
[EXTRA_ARGS arg1...]
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
[PROPERTIES name1 value1...]
[TEST_LIST var]
)
``catch_discover_tests`` sets up a post-build command on the test executable
that generates the list of tests by parsing the output from running the test
with the ``--list-test-names-only`` argument. This ensures that the full
list of tests is obtained. Since test discovery occurs at build time, it is
not necessary to re-run CMake when the list of tests changes.
However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
in order to function in a cross-compiling environment.
Additionally, setting properties on tests is somewhat less convenient, since
the tests are not available at CMake time. Additional test properties may be
assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
more fine-grained test control is needed, custom content may be provided
through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
directory property. The set of discovered tests is made accessible to such a
script via the ``<target>_TESTS`` variable.
The options are:
``target``
Specifies the Catch executable, which must be a known CMake executable
target. CMake will substitute the location of the built executable when
running the test.
``TEST_SPEC arg1...``
Specifies test cases, wildcarded test cases, tags and tag expressions to
pass to the Catch executable with the ``--list-test-names-only`` argument.
``EXTRA_ARGS arg1...``
Any extra arguments to pass on the command line to each test case.
``WORKING_DIRECTORY dir``
Specifies the directory in which to run the discovered test cases. If this
option is not provided, the current binary directory is used.
``TEST_PREFIX prefix``
Specifies a ``prefix`` to be prepended to the name of each discovered test
case. This can be useful when the same test executable is being used in
multiple calls to ``catch_discover_tests()`` but with different
``TEST_SPEC`` or ``EXTRA_ARGS``.
``TEST_SUFFIX suffix``
Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
be specified.
``PROPERTIES name1 value1...``
Specifies additional properties to be set on all tests discovered by this
invocation of ``catch_discover_tests``.
``TEST_LIST var``
Make the list of tests available in the variable ``var``, rather than the
default ``<target>_TESTS``. This can be useful when the same test
executable is being used in multiple calls to ``catch_discover_tests()``.
Note that this variable is only available in CTest.
#]=======================================================================]
#------------------------------------------------------------------------------
function(catch_discover_tests TARGET)
cmake_parse_arguments(
""
""
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST"
"TEST_SPEC;EXTRA_ARGS;PROPERTIES"
${ARGN}
)
if(NOT _WORKING_DIRECTORY)
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(NOT _TEST_LIST)
set(_TEST_LIST ${TARGET}_TESTS)
endif()
## Generate a unique name based on the extra arguments
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}")
string(SUBSTRING ${args_hash} 0 7 args_hash)
# Define rule to generate test list for aforementioned test executable
set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
get_property(crosscompiling_emulator
TARGET ${TARGET}
PROPERTY CROSSCOMPILING_EMULATOR
)
add_custom_command(
TARGET ${TARGET} POST_BUILD
BYPRODUCTS "${ctest_tests_file}"
COMMAND "${CMAKE_COMMAND}"
-D "TEST_TARGET=${TARGET}"
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
-D "TEST_EXECUTOR=${crosscompiling_emulator}"
-D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
-D "TEST_SPEC=${_TEST_SPEC}"
-D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
-D "TEST_PROPERTIES=${_PROPERTIES}"
-D "TEST_PREFIX=${_TEST_PREFIX}"
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
-D "TEST_LIST=${_TEST_LIST}"
-D "CTEST_FILE=${ctest_tests_file}"
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
VERBATIM
)
file(WRITE "${ctest_include_file}"
"if(EXISTS \"${ctest_tests_file}\")\n"
" include(\"${ctest_tests_file}\")\n"
"else()\n"
" add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
"endif()\n"
)
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
# Add discovered tests to directory TEST_INCLUDE_FILES
set_property(DIRECTORY
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
)
else()
# Add discovered tests as directory TEST_INCLUDE_FILE if possible
get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
if (NOT ${test_include_file_set})
set_property(DIRECTORY
PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
)
else()
message(FATAL_ERROR
"Cannot set more than one TEST_INCLUDE_FILE"
)
endif()
endif()
endfunction()
###############################################################################
set(_CATCH_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
)

View File

@@ -0,0 +1,76 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
set(prefix "${TEST_PREFIX}")
set(suffix "${TEST_SUFFIX}")
set(spec ${TEST_SPEC})
set(extra_args ${TEST_EXTRA_ARGS})
set(properties ${TEST_PROPERTIES})
set(script)
set(suite)
set(tests)
function(add_command NAME)
set(_args "")
foreach(_arg ${ARGN})
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
else()
set(_args "${_args} ${_arg}")
endif()
endforeach()
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
endfunction()
# Run test executable to get list of available tests
if(NOT EXISTS "${TEST_EXECUTABLE}")
message(FATAL_ERROR
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
)
endif()
execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
OUTPUT_VARIABLE output
RESULT_VARIABLE result
)
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
if(${result} EQUAL 0)
message(WARNING
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
)
elseif(${result} LESS 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${result}\n"
" Output: ${output}\n"
)
endif()
string(REPLACE "\n" ";" output "${output}")
# Parse output
foreach(line ${output})
set(test ${line})
# ...and add to script
add_command(add_test
"${prefix}${test}${suffix}"
${TEST_EXECUTOR}
"${TEST_EXECUTABLE}"
"${test}"
${extra_args}
)
add_command(set_tests_properties
"${prefix}${test}${suffix}"
PROPERTIES
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
${properties}
)
list(APPEND tests "${prefix}${test}${suffix}")
endforeach()
# Create a list of all discovered tests, which users may use to e.g. set
# properties on the tests
add_command(set ${TEST_LIST} ${tests})
# Write CTest script
file(WRITE "${CTEST_FILE}" "${script}")

View File

@@ -143,6 +143,9 @@ function(ParseFile SourceFile TestTarget)
endif()
string(REPLACE "]" ";" Tags "${Tags}")
string(REPLACE "[" "" Tags "${Tags}")
else()
# unset tags variable from previous loop
unset(Tags)
endif()
list(APPEND Labels ${Tags})

16
contrib/gdbinit Normal file
View File

@@ -0,0 +1,16 @@
#
# This file provides a way to skip stepping into Catch code when debugging with gdb.
#
# With the gdb "skip" command you can tell gdb to skip files or functions during debugging.
# see https://xaizek.github.io/2016-05-26/skipping-standard-library-in-gdb/ for an example
#
# Basically the following line tells gdb to skip all functions containing the
# regexp "Catch", which matches the complete Catch namespace.
# If you want to skip just some parts of the Catch code you can modify the
# regexp accordingly.
#
# If you want to permanently skip stepping into Catch code copy the following
# line into your ~/.gdbinit file
#
skip -rfu Catch

16
contrib/lldbinit Normal file
View File

@@ -0,0 +1,16 @@
#
# This file provides a way to skip stepping into Catch code when debugging with lldb.
#
# With the setting "target.process.thread.step-avoid-regexp" you can tell lldb
# to skip functions matching the regexp
#
# Basically the following line tells lldb to skip all functions containing the
# regexp "Catch", which matches the complete Catch namespace.
# If you want to skip just some parts of the Catch code you can modify the
# regexp accordingly.
#
# If you want to permanently skip stepping into Catch code copy the following
# line into your ~/.lldbinit file
#
settings set target.process.thread.step-avoid-regexp Catch

View File

@@ -20,7 +20,10 @@ Fine tuning:
Running:
* [Command line](command-line.md#top)
* [CI and Build system integration](build-systems.md#top)
Odds and ends:
* [CMake integration](cmake-integration.md#top)
* [CI and other miscellaneous pieces](ci-and-misc.md#top)
FAQ:
* [Why are my tests slow to compile?](slow-compiles.md#top)

View File

@@ -6,10 +6,11 @@
[Exceptions](#exceptions)<br>
[Matcher expressions](#matcher-expressions)<br>
[Thread Safety](#thread-safety)<br>
[Expressions with commas](#expressions-with-commas)<br>
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxilliary macros as well. We'll describe all of these here.
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxiliary macros as well. We'll describe all of these here.
Most of these macros come in two forms:
@@ -54,33 +55,45 @@ This expression is too complex because of the `||` operator. If you want to chec
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called ```Approx```. ```Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called `Approx`. `Approx` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
```
```cpp
REQUIRE( performComputation() == Approx( 2.1 ) );
```
This way `Approx` is constructed with reasonable defaults, covering most simple cases of rounding errors. If these are insufficient, each `Approx` instance has 3 tuning knobs, that can be used to customize it for your computation.
Catch also provides a UDL for `Approx`; `_a`. It resides in
the `Catch::literals` namespace and can be used like so:
```cpp
using namespace Catch::literals;
REQUIRE( performComputation() == 2.1_a );
```
* __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`.
* __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`.
* __scale__ - scale serves to adjust the epsilon's multiplicator. By default set to `0.0`.
`Approx` is constructed with defaults that should cover most simple cases.
For the more complex cases, `Approx` provides 3 customization points:
* __epsilon__ - epsilon serves to set the percentage by which a result
can differ from `Approx`'s value before it is rejected.
_By default set to `std::numeric_limits<float>::epsilon()*100`._
* __margin__ - margin serves to set the the absolute value by which
a result can differ from `Approx`'s value before it is rejected.
_By default set to `0.0`._
* __scale__ - scale is used to change the magnitude of `Approx` for relative check.
_By default set to `0.0`._
#### epsilon example
```cpp
Approx target = Approx(100).epsilon(0.01);
100.0 == target; // Obviously true
200.0 == target; // Obviously still false
100.5 == target; // True, because we set target to allow up to 1% error
100.5 == target; // True, because we set target to allow up to 1% difference
```
#### margin example
_Margin check is used only if the relative (epsilon and scale based) check fails._
```cpp
Approx target = Approx(100).margin(5);
100.0 == target; // Obviously true
200.0 == target; // Obviously still false
104.0 == target; // True, because we set target to allow absolute error up to 5
104.0 == target; // True, because we set target to allow absolute difference of at most 5
```
#### scale
@@ -155,6 +168,34 @@ Matchers can be composed using `&&`, `||` and `!` operators.
Currently assertions in Catch are not thread safe.
For more details, along with workarounds, see the section on [the limitations page](limitations.md#thread-safe-assertions).
## Expressions with commas
Because the preprocessor parses code using different rules than the
compiler, multiple-argument assertions (e.g. `REQUIRE_THROWS_AS`) have
problems with commas inside the provided expressions. As an example
`REQUIRE_THROWS_AS(std::pair<int, int>(1, 2), std::invalid_argument);`
will fail to compile, because the preprocessor sees 3 arguments provided,
but the macro accepts only 2. There are two possible workarounds.
1) Use typedef:
```cpp
using int_pair = std::pair<int, int>;
REQUIRE_THROWS_AS(int_pair(1, 2), std::invalid_argument);
```
This solution is always applicable, but makes the meaning of the code
less clear.
2) Parenthesize the expression:
```cpp
TEST_CASE_METHOD((Fixture<int, int>), "foo", "[bar]") {
SUCCEED();
}
```
This solution is not always applicable, because it might require extra
changes on the Catch's side to work.
---
[Home](Readme.md#top)

View File

@@ -1,6 +1,7 @@
<a id="top"></a>
# CI and build system integration
# CI and other odd pieces
This page talks about how Catch integrates with Continuous Integration
Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
## Continuous Integration systems
@@ -28,9 +29,14 @@ The advantage of this format is that the JUnit Ant schema is widely understood b
The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
## Other reporters
Other reporters are not part of the single-header distribution and need to be downloaded and included separately. All reporters are stored in `include/reporters` directory in the git repository, and are named `catch_reporter_*.hpp`. For example, to use the TeamCity reporter you need to download `include/reporters/catch_reporter_teamcity.hpp` and include it after Catch itself.
Other reporters are not part of the single-header distribution and need
to be downloaded and included separately. All reporters are stored in
`single_include` directory in the git repository, and are named
`catch_reporter_*.hpp`. For example, to use the TeamCity reporter you
need to download `single_include/catch_reporter_teamcity.hpp` and include
it after Catch itself.
```
```cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "catch_reporter_teamcity.hpp"
@@ -66,90 +72,31 @@ Catch offers prototypal support for being included in precompiled headers, but b
* include "catch.hpp" again
### CMake
In general we recommend "vendoring" Catch's single-include releases inside your own repository. If you do this, the following example shows a minimal CMake project:
```CMake
cmake_minimum_required(VERSION 3.0)
project(cmake_test)
# Prepare "Catch" library for other executables
set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/catch)
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
# Make test executable
set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
add_executable(tests ${TEST_SOURCES})
target_link_libraries(tests Catch)
```
Note that it assumes that the path to the Catch's header is `catch/catch.hpp` from the `CMakeLists.txt` file.
You can also use the following CMake snippet to automatically fetch the entire Catch repository from github and configure it as an external project:
```CMake
cmake_minimum_required(VERSION 2.8.8)
project(catch_builder CXX)
include(ExternalProject)
find_package(Git REQUIRED)
ExternalProject_Add(
catch
PREFIX ${CMAKE_BINARY_DIR}/catch
GIT_REPOSITORY https://github.com/philsquared/Catch.git
TIMEOUT 10
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
# Expose required variable (CATCH_INCLUDE_DIR) to parent scope
ExternalProject_Get_Property(catch source_dir)
set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch")
```
If you put it in, e.g., `${PROJECT_SRC_DIR}/${EXT_PROJECTS_DIR}/catch/`, you can use it in your project by adding the following to your root CMake file:
```CMake
# Includes Catch in the project:
add_subdirectory(${EXT_PROJECTS_DIR}/catch)
include_directories(${CATCH_INCLUDE_DIR} ${COMMON_INCLUDES})
enable_testing(true) # Enables unit-testing.
```
The advantage of this approach is that you can always automatically update Catch to the latest release. The disadvantage is that it means bringing in lot more than you need.
### Automatic test registration
If you are also using ctest, `contrib/ParseAndAddCatchTests.cmake` is a CMake script that attempts to parse your test files and automatically register all test cases, using tags as labels. This means that these
```cpp
TEST_CASE("Test1", "[unit]") {
int a = 1;
int b = 2;
REQUIRE(a == b);
}
TEST_CASE("Test2") {
int a = 1;
int b = 2;
REQUIRE(a == b);
}
TEST_CASE("Test3", "[a][b][c]") {
int a = 1;
int b = 2;
REQUIRE(a == b);
}
```
would be registered as 3 tests, `Test1`, `Test2` and `Test3`, and 4 ctest labels would be created, `a`, `b`, `c` and `unit`.
### CodeCoverage module (GCOV, LCOV...)
If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage
### pkg-config
Catch2 provides a rudimentary pkg-config integration, by registering itself
under the name `catch2`. This means that after Catch2 is installed, you
can use `pkg-config` to get its include path: `pkg-config --cflags catch2`.
### gdb and lldb scripts
Catch2's `contrib` folder also contains two simple debugger scripts,
`gdbinit` for `gdb` and `lldbinit` for `lldb`. If loaded into their
respective debugger, these will tell it to step over Catch2's internals
when stepping through code.
## CMake
[As it has been getting kinda long, the documentation of Catch2's
integration with CMake has been moved to its own page.](cmake-integration.md#top)
---
[Home](Readme.md#top)

189
docs/cmake-integration.md Normal file
View File

@@ -0,0 +1,189 @@
<a id="top"></a>
# CMake integration
Because we use CMake to build Catch2, we also provide a couple of
integration points for our users.
1) Catch2 exports a (namespaced) CMake target
2) Catch2's repository contains CMake scripts for automatic registration
of `TEST_CASE`s in CTest
## CMake target
Catch2's CMake build exports an interface target `Catch2::Catch2`. Linking
against it will add the proper include path and all necessary capabilities
to the resulting binary.
This means that if Catch2 has been installed on the system, it should be
enough to do:
```cmake
find_package(Catch2 REQUIRED)
target_link_libraries(tests Catch2::Catch2)
```
This target is also provided when Catch2 is used as a subdirectory.
Assuming that Catch2 has been cloned to `lib/Catch2`:
```cmake
add_subdirectory(lib/Catch2)
target_link_libraries(tests Catch2::Catch2)
```
## Automatic test registration
Catch2's repository also contains two CMake scripts that help users
with automatically registering their `TEST_CASE`s with CTest. They
can be found in the `contrib` folder, and are
1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`)
2) `ParseAndAddCatchTests.cmake`
If Catch2 has been installed in system, both of these can be used after
doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them
to your CMake module path.
### `Catch.cmake` and `AddCatchTests.cmake`
`Catch.cmake` provides function `catch_discover_tests` to get tests from
a target. This function works by running the resulting executable with
`--list-test-names-only` flag, and then parsing the output to find all
existing tests.
#### Usage
```cmake
cmake_minimum_required(VERSION 3.5)
project(baz LANGUAGES CXX VERSION 0.0.1)
find_package(Catch2 REQUIRED)
add_executable(foo test.cpp)
target_link_libraries(foo Catch2::Catch2)
include(CTest)
include(Catch)
catch_discover_tests(foo)
```
#### Customization
`catch_discover_tests` can be given several extra argumets:
```cmake
catch_discover_tests(target
[TEST_SPEC arg1...]
[EXTRA_ARGS arg1...]
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
[PROPERTIES name1 value1...]
[TEST_LIST var]
)
```
* `TEST_SPEC arg1...`
Specifies test cases, wildcarded test cases, tags and tag expressions to
pass to the Catch executable alongside the `--list-test-names-only` flag.
* `EXTRA_ARGS arg1...`
Any extra arguments to pass on the command line to each test case.
* `WORKING_DIRECTORY dir`
Specifies the directory in which to run the discovered test cases. If this
option is not provided, the current binary directory is used.
* `TEST_PREFIX prefix`
Specifies a _prefix_ to be added to the name of each discovered test case.
This can be useful when the same test executable is being used in multiple
calls to `catch_discover_tests()`, with different `TEST_SPEC` or `EXTRA_ARGS`.
* `TEST_SUFFIX suffix`
Same as `TEST_PREFIX`, except it specific the _suffix_ for the test names.
Both `TEST_PREFIX` and `TEST_SUFFIX` can be specified at the same time.
* `PROPERTIES name1 value1...`
Specifies additional properties to be set on all tests discovered by this
invocation of `catch_discover_tests`.
* `TEST_LIST var`
Make the list of tests available in the variable `var`, rather than the
default `<target>_TESTS`. This can be useful when the same test
executable is being used in multiple calls to `catch_discover_tests()`.
Note that this variable is only available in CTest.
### `ParseAndAddCatchTests.cmake`
`ParseAndAddCatchTests` works by parsing all implementation files
associated with the provided target, and registering them via CTest's
`add_test`. This approach has some limitations, such as the fact that
commented-out tests will be registered anyway.
#### Usage
```cmake
cmake_minimum_required(VERSION 3.5)
project(baz LANGUAGES CXX VERSION 0.0.1)
find_package(Catch2 REQUIRED)
add_executable(foo test.cpp)
target_link_libraries(foo Catch2::Catch2)
include(CTest)
include(ParseAndAddCatchTests)
ParseAndAddCatchTests(foo)
```
#### Customization
`ParseAndAddCatchTests` provides some customization points:
* `PARSE_CATCH_TESTS_VERBOSE` -- When `ON`, the script prints debug
messages. Defaults to `OFF`.
* `PARSE_CATCH_TESTS_NO_HIDDEN_TESTS` -- When `ON`, hidden tests (tests
tagged with any of `[!hide]`, `[.]` or `[.foo]`) will not be registered.
Defaults to `OFF`.
* `PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME` -- When `ON`, adds fixture
class name to the test name in CTest. Defaults to `ON`.
* `PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME` -- When `ON`, adds target
name to the test name in CTest. Defaults to `ON`.
* `PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS` -- When `ON`, adds test
file to `CMAKE_CONFIGURE_DEPENDS`. This means that the CMake configuration
step will be re-ran when the test files change, letting new tests be
automatically discovered. Defaults to `OFF`.
## CMake project options
Catch2's CMake project also provides some options for other projects
that consume it. These are
* `CATCH_BUILD_TESTING` -- When `ON`, Catch2's SelfTest project will be
built. Defaults to `ON`. Note that Catch2 also obeys `BUILD_TESTING` CMake
variable, so _both_ of them need to be `ON` for the SelfTest to be built,
and either of them can be set to `OFF` to disable building SelfTest.
* `CATCH_BUILD_EXAMPLES` -- When `ON`, Catch2's usage examples will be
built. Defaults to `OFF`.
* `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be
included in the installation. Defaults to `ON`.
* `CATCH_INSTALL_HELPERS` -- When `ON`, Catch2's contrib folder will be
included in the installation. Defaults to `ON`.
* `BUILD_TESTING` -- When `ON` and the project is not used as a subproject,
Catch2's test binary will be built. Defaults to `ON`.
---
[Home](Readme.md#top)

View File

@@ -24,6 +24,7 @@
[Usage](#usage)<br>
[Specify the section to run](#specify-the-section-to-run)<br>
[Filenames as tags](#filenames-as-tags)<br>
[Override output colouring](#use-colour)<br>
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
@@ -57,6 +58,7 @@ Click one of the followings links to take you straight to that option - or scrol
<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 />
<a href="#use-colour"> ` --use-colour`</a><br />
</br>
@@ -78,7 +80,7 @@ Wildcards consist of the `*` character at the beginning and/or end of test case
Test specs are case insensitive.
If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precendence, however.
If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precedence, however.
Inclusions and exclusions are evaluated in left-to-right order.
Test case examples:
@@ -94,7 +96,7 @@ a* ~ab* abc Matches all tests that start with 'a', except those that
</pre>
Names within square brackets are interpreted as tags.
A series of tags form an AND expression wheras a comma-separated sequence forms an OR expression. e.g.:
A series of tags form an AND expression whereas a comma-separated sequence forms an OR expression. e.g.:
<pre>[one][two],[three]</pre>
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
@@ -122,7 +124,9 @@ The JUnit reporter is an xml format that follows the structure of the JUnit XML
## Breaking into the debugger
<pre>-b, --break</pre>
In some IDEs (currently XCode and Visual Studio) it is possible for Catch to break into the debugger on a test failure. This can be very helpful during debug sessions - especially when there is more than one path through a particular test.
Under most debuggers Catch2 is capable of automatically breaking on a test
failure. This allows the user to see the current state of the test during
failure.
<a id="showing-results-for-successful-tests"></a>
## Showing results for successful tests
@@ -192,9 +196,16 @@ This option transforms tabs and newline characters into ```\t``` and ```\n``` re
## Warnings
<pre>-w, --warn &lt;warning name></pre>
Enables reporting of warnings (only one, at time of this writing). If a warning is issued it fails the test.
Enables reporting of suspicious test states. There are currently two
available warnings
```
NoAssertions // Fail test case / leaf section if no assertions
// (e.g. `REQUIRE`) is encountered.
NoTests // Return non-zero exit code when no test cases were run
// Also calls reporter's noMatchingTestCases method
```
The ony available warning, presently, is ```NoAssertions```. This warning fails a test case, or (leaf) section if no assertions (```REQUIRE```/ ```CHECK``` etc) are encountered.
<a id="reporting-timings"></a>
## Reporting timings
@@ -262,7 +273,7 @@ either before running any tests, after running all tests - or both, depending on
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.
it can be overridden here.
<a id="usage"></a>
## Usage
@@ -322,6 +333,16 @@ filename it is found in, with any extension stripped, prefixed with the `#` char
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
<a id="use-colour"></a>
## Override output colouring
<pre>--use-colour &lt;yes|no|auto&gt;</pre>
Catch colours output for terminals, but omits colouring when it detects that
output is being sent to a pipe. This is done to avoid interfering with automated
processing of output.
`--use-colour yes` forces coloured output, `--use-colour no` disables coloured
output. The default behaviour is `--use-colour auto`.
---

View File

@@ -7,6 +7,8 @@
[Terminal colour](#terminal-colour)<br>
[Console width](#console-width)<br>
[stdout](#stdout)<br>
[Fallback stringifier](#fallback-stringifier)<br>
[Default reporter](#default-reporter)<br>
[Other toggles](#other-toggles)<br>
[Windows header clutter](#windows-header-clutter)<br>
[Enabling stringification](#enabling-stringification)<br>
@@ -24,7 +26,7 @@ Although Catch is header only it still, internally, maintains a distinction betw
# Reporter / Listener interfaces
CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in neccessary headers for Reporter/Listener implementation
CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in necessary headers for Reporter/Listener implementation
Brings in various parts of Catch that are required for user defined Reporters and Listeners. This means that new Reporters and Listeners can be defined in this file as well as in the main file.
@@ -64,15 +66,70 @@ 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```, ```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:
To support platforms that do not provide `std::cout`, `std::cerr` and
`std::clog`, Catch does not usem the directly, but rather calls
`Catch::cout`, `Catch::cerr` and `Catch::clog`. You can replace their
implementation by defining `CATCH_CONFIG_NOSTDOUT` and implementing
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 the standard iostreams, such as certain embedded systems.
[You can see an example of replacing these functions here.](
../examples/231-Cfg-OutputStreams.cpp)
## Fallback stringifier
By default, when Catch's stringification machinery has to stringify
a type that does not specialize `StringMaker`, does not overload `operator<<`,
is not an enumeration and is not a range, it uses `"{?}"`. This can be
overriden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER` to name of a
function that should perform the stringification instead.
All types that do not provide `StringMaker` specialization or `operator<<`
overload will be sent to this function (this includes enums and ranges).
The provided function must return `std::string` and must accept any type,
e.g. via overloading.
_Note that if the provided function does not handle a type and this type
requires to be stringified, the compilation will fail._
## Default reporter
Catch's default reporter can be changed by defining macro
`CATCH_CONFIG_DEFAULT_REPORTER` to string literal naming the desired
default reporter.
This means that defining `CATCH_CONFIG_DEFAULT_REPORTER` to `"console"`
is equivalent with the out-of-the-box experience.
## C++11 toggles
CATCH_CONFIG_CPP11_TO_STRING // Use `std::to_string`
Because we support platforms whose standard library does not contain
`std::to_string`, it is possible to force Catch to use a workaround
based on `std::stringstream`. On platforms other than Android,
the default is to use `std::to_string`. On Android, the default is to
use the `stringstream` workaround. As always, it is possible to override
Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
`CATCH_CONFIG_NO_CPP11_TO_STRING`.
## C++17 toggles
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception
Catch contains basic compiler/standard detection and attempts to use
some C++17 features whenever appropriate. This automatic detection
can be manually overridden in both directions, that is, a feature
can be enabled by defining the macro in the table above, and disabled
by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`.
## Other toggles
@@ -84,6 +141,8 @@ This can be useful on certain platforms that do not provide the standard iostrea
CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
CATCH_CONFIG_DISABLE // Disables assertions and test case registration
CATCH_CONFIG_WCHAR // Enables use of wchart_t
CATCH_CONFIG_EXPERIMENTAL_REDIRECT // Enables the new (experimental) way of capturing stdout/stderr
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
@@ -91,14 +150,22 @@ 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.
These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
`CATCH_CONFIG_WCHAR` is on by default, but can be disabled. Currently
it is only used in support for DJGPP cross-compiler.
With the exception of `CATCH_CONFIG_EXPERIMENTAL_REDIRECT`,
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:
* The `-b` (`--break`) flag no longer makes Catch break into debugger in the same stack frame as the failed test, but rather in a stack frame *below*.
* Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_FALSE`}, no longer use local try-cache block. This disables exception translation, but should not lead to false negatives.
This compile-time flag speeds up compilation of assertion macros by ~20%,
by disabling the generation of assertion-local try-catch blocks for
non-exception family of assertion macros ({`REQUIRE`,`CHECK`}{``,`_FALSE`, `_THAT`}).
This disables translation of exceptions thrown under these assertions, but
should not lead to false negatives.
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable.
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined,
in all translation units that are linked into single test binary.
### `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.

View File

@@ -44,7 +44,7 @@ _Note that you should not use any assertion macros within a Listener!_
## Events that can be hooked
The following are the methods that can be overriden in the Listener:
The following are the methods that can be overridden in the Listener:
```c++
// The whole test run, starting and ending

View File

@@ -21,7 +21,9 @@ TEST_CASE( "Looped section" ) {
This section outlines some missing features, what is their status and their possible workarounds.
### Thread safe assertions
Because threading support in standard C++98 is limited (well, non-existent), assertion macros in Catch are not thread safe. This does not mean that you cannot use threads inside Catch's test, but that only single thread can interact with Catch's assertions and other macros.
Catch2's assertion macros are not thread safe. This does not mean that
you cannot use threads inside Catch's test, but that only single thread
can interact with Catch's assertions and other macros.
This means that this is ok
```cpp
@@ -49,8 +51,8 @@ because only one thread passes the `REQUIRE` macro and this is not
REQUIRE(cnt == 16);
```
_This limitation is highly unlikely to be lifted before Catch 2 is released._
Because C++11 provides the necessary tools to do this, we are planning
to remove this limitation in the future.
### Process isolation in a test
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
@@ -96,6 +98,14 @@ with expansion:
""\" == ""\"
```
### Visual Studio 2015 -- Alignment compilation error (C2718)
VS 2015 has a known bug, where `declval<T>` can cause compilation error
if `T` has alignment requirements that it cannot meet.
A workaround is to explicitly specialize `Catch::is_range` for given
type (this avoids code path that uses `declval<T>` in a SFINAE context).
### Visual Studio 2015 -- Wrong line number reported in debug mode

View File

@@ -1,18 +1,25 @@
<a id="top"></a>
# List of examples
## Already available
- Test Case: [Single-file](../examples/010-TestCase.cpp)
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-1.cpp)
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-2.cpp)
- Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)
- Fixture: [Sections](../examples/100-Fix-Section.cpp)
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
## Planned
- Assertion: [REQUIRE_THAT and Matchers](../examples/040-Asn-RequireThat.cpp)
- Assertion: [REQUIRE_NO_THROW](../examples/050-Asn-RequireNoThrow.cpp)
- Assertion: [REQUIRE_THROWS](../examples/050-Asn-RequireThrows.cpp)
- Assertion: [REQUIRE_THROWS_AS](../examples/070-Asn-RequireThrowsAs.cpp)
- Assertion: [REQUIRE_THROWS_WITH](../examples/080-Asn-RequireThrowsWith.cpp)
- Assertion: [REQUIRE_THROWS_MATCHES](../examples/090-Asn-RequireThrowsMatches.cpp)
- Fixture: [Sections](../examples/100-Fix-Section.cpp)
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
- Floating point: [Approx - Comparisons](../examples/130-Fpt-Approx.cpp)
- Logging: [CAPTURE - Capture expression](../examples/140-Log-Capture.cpp)
- Logging: [INFO - Provide information with failure](../examples/150-Log-Info.cpp)
@@ -21,7 +28,6 @@
- Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
- Report: [Reporter](../examples/200-Rpt-UserDefinedReporter.cpp)
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
- Configuration: [Provide your own main()](../examples/220-Cfg-OwnMain.cpp)
- Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
- Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)

View File

@@ -72,12 +72,6 @@ This would log something like:
<pre>"theAnswer := 42"</pre>
## Deprecated macros
**SCOPED_INFO and SCOPED_CAPTURE**
These macros are now deprecated and are just aliases for INFO and CAPTURE (which were not previously scoped).
---
[Home](Readme.md#top)

View File

@@ -53,6 +53,25 @@ The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts
Do note that ULP-based checks only make sense when both compared numbers are of the same type and `WithinULP` will use type of its argument as the target type. This means that `WithinULP(1.f, 1)` will expect to compare `float`s, but `WithinULP(1., 1)` will expect to compare `double`s.
### Generic matchers
Catch also aims to provide a set of generic matchers. Currently this set
contains only a matcher that takes arbitrary callable predicate and applies
it onto the provided object.
Because of type inference limitations, the argument type of the predicate
has to be provided explicitly. Example:
```cpp
REQUIRE_THAT("Hello olleH",
Predicate<std::string>(
[] (std::string const& str) -> bool { return str.front() == str.back(); },
"First and last character should be equal")
);
```
The second argument is an optional description of the predicate, and is
used only during reporting of the result.
## Custom matchers
It's easy to provide your own matchers to extend Catch or just to work with your own types.

View File

@@ -1,18 +1,18 @@
<a id="top"></a>
# Open Source projects using Catch
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
it's easy to just drop the header into your project and start writing tests - what's not to like?
As a result Catch is now being used in many Open Source projects, including some quite well known ones.
This page is an attempt to track those projects. Obviously it can never be complete.
This effort largely relies on the maintainers of the projects themselves updating this page and submitting a PR
(or, if you prefer contact one of the maintainers of Catch directly, use the
(or, if you prefer contact one of the maintainers of Catch directly, use the
[forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)), or raise an [issue](https://github.com/philsquared/Catch/issues) to let us know).
Of course users of those projects might want to update this page too. That's fine - as long you're confident the project maintainers won't mind.
If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
just let us know via any of the previously mentioned means - although I'm sure there won't be many who feel that way.
Listing a project here does not imply endorsement and the plan is to keep these ordered alphabetically to avoid an implication of relative importance.
## Libraries & Frameworks
@@ -21,7 +21,7 @@ Listing a project here does not imply endorsement and the plan is to keep these
Boost Asio style bindings for ZeroMQ
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
The core part of the Chakra Javascript engine that powers Microsoft Edge
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
@@ -35,6 +35,9 @@ The next-generation core storage and query engine for Couchbase Lite
### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
A High-performance Cluster Computing Engine
### [forest](https://github.com/xorz57/forest)
Forest is an open-source, template library of tree data structures written in C++11.
### [Fuxedo](https://github.com/fuxedo/fuxedo)
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
@@ -44,6 +47,9 @@ A header-only template engine for modern C++.
### [JSON for Modern C++](https://github.com/nlohmann/json)
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
### [libcluon](https://github.com/chrberger/libcluon)
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
### [MNMLSTC Core](https://github.com/mnmlstc/core)
A small and easy to use C++11 library that adds a functionality set that will be available in C++14 and later, as well as some useful additions.
@@ -88,6 +94,9 @@ MAME originally stood for Multiple Arcade Machine Emulator
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
### [SpECTRE](https://github.com/sxs-collaboration/spectre)
SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
### [Standardese](https://github.com/foonathan/standardese)
Standardese aims to be a nextgen Doxygen

View File

@@ -30,7 +30,7 @@ int main( int argc, char* argv[] ) {
## Amending the config
If you still want Catch to process the command line, but you want to programatically tweak the config, you can do so in one of two ways:
If you still want Catch to process the command line, but you want to programmatically tweak the config, you can do so in one of two ways:
```c++
#define CATCH_CONFIG_RUNNER
@@ -81,6 +81,7 @@ int main( int argc, char* argv[] )
int height = 0; // Some user variable you want to be able to set
// Build a new parser on top of Catch's
using namespace Catch::clara;
auto cli
= session.cli() // Get Catch's composite command line parser
| Opt( height, "height" ) // bind variable to a new option, with a hint string
@@ -105,6 +106,20 @@ int main( int argc, char* argv[] )
See the [Clara documentation](https://github.com/philsquared/Clara/blob/master/README.md) for more details.
## Version detection
Catch provides a triplet of macros providing the header's version,
* `CATCH_VERSION_MAJOR`
* `CATCH_VERSION_MINOR`
* `CATCH_VERSION_PATCH`
these macros expand into a single number, that corresponds to the appropriate
part of the version. As an example, given single header version v2.3.4,
the macros would expand into `2`, `3`, and `4` respectively.
---
[Home](Readme.md#top)

View File

@@ -1,5 +1,167 @@
<a id="top"></a>
# 2.3.0
**This release changes the include paths provided by our CMake and
pkg-config integration. The proper include path for the single-header
when using one of the above is now `<catch2/catch.hpp>`. This change
also necessitated changes to paths inside the repository, so that the
single-header version is now at `single_include/catch2/catch.hpp`, rather
than `single_include/catch.hpp`.**
## Fixes
* Fixed Objective-C++ build
* `-Wunused-variable` suppression no longer leaks from Catch's header under Clang
* Implementation of the experimental new output capture can now be disabled (#1335)
* This allows building Catch2 on platforms that do not provide things like `dup` or `tmpfile`.
* The JUnit and XML reporters will no longer skip over successful tests when running without `-s` (#1264, #1267, #1310)
* See improvements for more details
## Improvements
* pkg-config and CMake integration has been rewritten
* If you use them, the new include path is `#include <catch2/catch.hpp>`
* CMake installation now also installs scripts from `contrib/`
* For details see the [new documentation](cmake-integration.md#top)
* Reporters now have a new customization point, `ReporterPreferences::shouldReportAllAssertions`
* When this is set to `false` and the tests are run without `-s`, passing assertions are not sent to the reporter.
* Defaults to `false`.
* Added `DYNAMIC_SECTION`, a section variant that constructs its name using stream
* This means that you can do `DYNAMIC_SECTION("For X := " << x)`.
# 2.2.3
**To fix some of the bugs, some behavior had to change in potentially breaking manner.**
**This means that even though this is a patch release, it might not be a drop-in replacement.**
## Fixes
* Listeners are now called before reporter
* This was always documented to be the case, now it actually works that way
* Catch's commandline will no longer accept multiple reporters
* This was done because multiple reporters never worked properly and broke things in non-obvious ways
* **This has potential to be a breaking change**
* MinGW is now detected as Windows platform w/o SEH support (#1257)
* This means that Catch2 no longer tries to use POSIX signal handling when compiled with MinGW
* Fixed potential UB in parsing tags using non-ASCII characters (#1266)
* Note that Catch2 still supports only ASCII test names/tags/etc
* `TEST_CASE_METHOD` can now be used on classnames containing commas (#1245)
* You have to enclose the classname in extra set of parentheses
* Fixed insufficient alt stack size for POSIX signal handling (#1225)
* Fixed compilation error on Android due to missing `std::to_string` in C++11 mode (#1280)
* Fixed the order of user-provided `FALLBACK_STRINGIFIER` in stringification machinery (#1024)
* It was intended to be replacement for built-in fallbacks, but it was used _after_ them.
* **This has potential to be a breaking change**
* Fixed compilation error when a type has an `operator<<` with templated lhs (#1285, #1306)
## Improvements
* Added a new, experimental, output capture (#1243)
* This capture can also redirect output written via C apis, e.g. `printf`
* To opt-in, define `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` in the implementation file
* Added a new fallback stringifier for classes derived from `std::exception`
* Both `StringMaker` specialization and `operator<<` overload are given priority
## Miscellaneous
* `contrib/` now contains dbg scripts that skip over Catch's internals (#904, #1283)
* `gdbinit` for gdb `lldbinit` for lldb
* `CatchAddTests.cmake` no longer strips whitespace from tests (#1265, #1281)
* Online documentation now describes `--use-colour` option (#1263)
# 2.2.2
## Fixes
* Fixed bug in `WithinAbs::match()` failing spuriously (#1228)
* Fixed clang-tidy diagnostic about virtual call in destructor (#1226)
* Reduced the number of GCC warnings suppression leaking out of the header (#1090, #1091)
* Only `-Wparentheses` should be leaking now
* Added upper bound on the time benchmark timer calibration is allowed to take (#1237)
* On platforms where `std::chrono::high_resolution_clock`'s resolution is low, the calibration would appear stuck
* Fixed compilation error when stringifying static arrays of `unsigned char`s (#1238)
## Improvements
* XML encoder now hex-encodes invalid UTF-8 sequences (#1207)
* This affects xml and junit reporters
* Some invalid UTF-8 parts are left as is, e.g. surrogate pairs. This is because certain extensions of UTF-8 allow them, such as WTF-8.
* CLR objects (`T^`) can now be stringified (#1216)
* This affects code compiled as C++/CLI
* Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236)
* See [documentation for details](https://github.com/catchorg/Catch2/blob/master/docs/matchers.md)
## Others
* Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239)
* The plans to standardize on `#include <catch2/catch.hpp>` are still in effect
# 2.2.1
## Fixes
* Fixed compilation error when compiling Catch2 with `std=c++17` against libc++ (#1214)
* Clara (Catch2's CLI parsing library) used `std::optional` without including it explicitly
* Fixed Catch2 return code always being 0 (#1215)
* In the words of STL, "We feel superbad about letting this in"
# 2.2.0
## Fixes
* Hidden tests are not listed by default when listing tests (#1175)
* This makes `catch_discover_tests` CMake script work better
* Fixed regression that meant `<windows.h>` could potentially not be included properly (#1197)
* Fixed installing `Catch2ConfigVersion.cmake` when Catch2 is a subproject.
## Improvements
* Added an option to warn (+ exit with error) when no tests were ran (#1158)
* Use as `-w NoTests`
* Added provisional support for Emscripten (#1114)
* [Added a way to override the fallback stringifier](https://github.com/catchorg/Catch2/blob/master/docs/configuration.md#fallback-stringifier) (#1024)
* This allows project's own stringification machinery to be easily reused for Catch
* `Catch::Session::run()` now accepts `char const * const *`, allowing it to accept array of string literals (#1031, #1178)
* The embedded version of Clara was bumped to v1.1.3
* Various minor performance improvements
* Added support for DJGPP DOS crosscompiler (#1206)
# 2.1.2
## Fixes
* Fixed compilation error with `-fno-rtti` (#1165)
* Fixed NoAssertion warnings
* `operator<<` is used before range-based stringification (#1172)
* Fixed `-Wpedantic` warnings (extra semicolons and binary literals) (#1173)
## Improvements
* Added `CATCH_VERSION_{MAJOR,MINOR,PATCH}` macros (#1131)
* Added `BrightYellow` colour for use in reporters (#979)
* It is also used by ConsoleReporter for reconstructed expressions
## Other changes
* Catch is now exported as a CMake package and linkable target (#1170)
# 2.1.1
## Improvements
* Static arrays are now properly stringified like ranges across MSVC/GCC/Clang
* Embedded newer version of Clara -- v1.1.1
* This should fix some warnings dragged in from Clara
* MSVC's CLR exceptions are supported
## Fixes
* Fixed compilation when comparison operators do not return bool (#1147)
* Fixed CLR exceptions blowing up the executable during translation (#1138)
## Other changes
* Many CMake changes
* `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead.
* Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes
* Other changes to simplify Catch2's packaging
# 2.1.0
## Improvements
@@ -340,8 +502,8 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
* Cygwin compatibility fixes
* Signal handling is no longer compiled by default.
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
* Improved `-Wparentheses` supression for gcc (#674)
* When compiled with gcc 4.8 or newer, the supression is localized to assertions only
* Improved `-Wparentheses` suppression for gcc (#674)
* When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
* Otherwise it is supressed for the whole TU
* Fixed test spec parser issue (with escapes in multiple names)
@@ -360,7 +522,7 @@ Xml:
* C-escape control characters instead of XML encoding them (which requires XML 1.1)
* Revert XML output to XML 1.0
* Can provide stylesheet references by extending the XML reporter
* Added description and tags attribites to XML Reporter
* Added description and tags attributes to XML Reporter
* Tags are closed and the stream flushed more eagerly to avoid stdout interpolation

View File

@@ -1,11 +1,11 @@
<a id="top"></a>
# How to release
When enough changes have accumulated, it is time to release new version of Catch. This document describes the proces in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
When enough changes have accumulated, it is time to release new version of Catch. This document describes the process in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
## Neccessary steps
## Necessary steps
These steps are neccessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
These steps are necessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
### Approval testing
@@ -21,10 +21,8 @@ Catch uses a variant of [semantic versioning](http://semver.org/), with breaking
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.
### Generate updated single-include header
After updating version number, regenerate single-include header using `generateSingleHeader.py`.
This will take care of generating the single include header, updating
version numbers everywhere and pushing the new version to Wandbox.
### Release notes
@@ -39,26 +37,17 @@ After version number is incremented, single-include header is regenerated and re
### Release on GitHub
After pushing changes to GitHub, GitHub release *needs* to be created. Tag version and release title should be same as the new version, description should contain the release notes for the current release. Single header version of `catch.hpp` *needs* to be attached as a binary, as that is where the official download link links to. Preferably it should use linux line endings.
After pushing changes to GitHub, GitHub release *needs* to be created.
Tag version and release title should be same as the new version,
description should contain the release notes for the current release.
Single header version of `catch.hpp` *needs* to be attached as a binary,
as that is where the official download link links to. Preferably
it should use linux line endings. All non-bundled reporters (Automake,
TAP, TeamCity) should also be attached as binaries, as they are dependent
on a specific version of the single-include header.
## Optional steps
The following steps are optional, and do not have to be performed when releasing new version of Catch. However, they are *should* happen, but they can happen the next day without losing anything significant.
### vcpkg update
Catch is maintaining its own port in Microsoft's package manager [vcpkg](https://github.com/Microsoft/vcpkg). This means that when new version of Catch is released, it should be posted there as well. `updateVcpkgPackage.py` can do a lot of neccessary work for you, it creates a branch and commits neccessary changes. You should review these changes, push and open a PR against vcpkg's upstream.
Note that the script assumes you have your fork of vcpkg checked out in a directory next to the directory where you have checked out Catch, like so:
```
GitHub
Catch
vcpkg
```
### Wandbox update
Recently we also included a link to wandbox with preloaded Catch on the main page. Strictly speaking it is unneccessary to update this after every release, Catch usually does not change that much between versions, but it should be kept up to date anyway.
Because Catch's [vcpkg](https://github.com/Microsoft/vcpkg) port updates
itself automagically, there are no optional steps at this time.

View File

@@ -33,6 +33,23 @@ namespace Catch {
}
```
## Catch::is_range<T> specialisation
As a fallback, Catch attempts to detect if the type can be iterated
(`begin(T)` and `end(T)` are valid) and if it can be, it is stringified
as a range. For certain types this can lead to infinite recursion, so
it can be disabled by specializing `Catch::is_range` like so:
```cpp
namespace Catch {
template<>
struct is_range<T> {
static const bool value = false;
};
}
```
## Exceptions
By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example:

View File

@@ -12,7 +12,10 @@
## Getting Catch2
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/CatchOrg/Catch2/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
Alternative ways of getting Catch2 include using your system package
manager, or installing it using its CMake package.
The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
@@ -23,6 +26,9 @@ Catch2 is header only. All you need to do is drop the file somewhere reachable f
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
_If you have installed Catch2 from system package manager, or CMake
package, you need to include the header as `#include <catch2/catch.hpp>`_
## Writing tests
Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now).

View File

@@ -6,7 +6,7 @@
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <catch2/catch.hpp>
// That's it

View File

@@ -3,7 +3,7 @@
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <catch2/catch.hpp>
int Factorial( int number ) {
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail

View File

@@ -6,7 +6,7 @@
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <catch2/catch.hpp>
TEST_CASE( "1: All test cases reside in other .cpp files (empty)", "[multi-file:1]" ) {
}

View File

@@ -2,7 +2,7 @@
// main() provided by Catch in file 020-TestCase-1.cpp.
#include "catch.hpp"
#include <catch2/catch.hpp>
int Factorial( int number ) {
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail

View File

@@ -10,7 +10,7 @@
// main() provided in 000-CatchMain.cpp
#include "catch.hpp"
#include <catch2/catch.hpp>
std::string one() {
return "1";

View File

@@ -6,7 +6,7 @@
// main() provided in 000-CatchMain.cpp
#include "catch.hpp"
#include <catch2/catch.hpp>
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {

View File

@@ -6,7 +6,7 @@
// main() provided in 000-CatchMain.cpp
#include "catch.hpp"
#include <catch2/catch.hpp>
class DBConnection
{

View File

@@ -2,7 +2,7 @@
// main() provided in 000-CatchMain.cpp
#include "catch.hpp"
#include <catch2/catch.hpp>
SCENARIO( "vectors can be sized and resized", "[vector]" ) {

View File

@@ -10,7 +10,7 @@
// Let Catch provide the required interfaces:
#define CATCH_CONFIG_EXTERNAL_INTERFACES
#include "catch.hpp"
#include <catch2/catch.hpp>
#include <iostream>
// -----------------------------------------------------------------------
@@ -187,8 +187,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- name: " << info.name << "\n"
<< ws(level+1) << "- description: '" << info.description << "'\n";
<< ws(level+1) << "- name: " << info.name << "\n";
print( os, level+1 , "- lineInfo", info.lineInfo );
}

View File

@@ -0,0 +1,49 @@
// 231-Cfg-OutputStreams.cpp
// Show how to replace the streams with a simple custom made streambuf.
// Note that this reimplementation _does not_ follow `std::cerr`
// semantic, because it buffers the output. For most uses however,
// there is no important difference between having `std::cerr` buffered
// or unbuffered.
#define CATCH_CONFIG_NOSTDOUT
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
class out_buff : public std::stringbuf {
std::FILE* m_stream;
public:
out_buff(std::FILE* stream) :m_stream(stream) {}
~out_buff() { pubsync(); }
int sync() {
int ret = 0;
for (unsigned char c : str()) {
if (putc(c, m_stream) == EOF) {
ret = -1;
break;
}
}
// Reset the buffer to avoid printing it multiple times
str("");
return ret;
}
};
namespace Catch {
std::ostream& cout() {
static std::ostream ret(new out_buff(stdout));
return ret;
}
std::ostream& clog() {
static std::ostream ret(new out_buff(stderr));
return ret;
}
std::ostream& cerr() {
return clog();
}
}
TEST_CASE("This binary uses putc to write out output", "[compilation-only]") {
SUCCEED("Nothing to test.");
}

View File

@@ -1,7 +1,7 @@
#
# Build examples.
#
# Requires BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
# Requires CATCH_BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
#
cmake_minimum_required( VERSION 3.0 )
@@ -17,6 +17,7 @@ set( HEADER_DIR ${CATCH_DIR}/single_include )
set( SOURCES_SINGLE_FILE
010-TestCase.cpp
231-Cfg-OutputStreams.cpp
)
# multiple-file modules:
@@ -68,16 +69,16 @@ set( TARGETS_ALL ${TARGETS_SINGLE_FILE} ${TARGETS_IDIOMATIC_TESTS} 0
# define program targets:
add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch.hpp )
add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch2/catch.hpp )
add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch.hpp )
add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch2/catch.hpp )
foreach( name ${TARGETS_SINGLE_FILE} )
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch.hpp )
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch2/catch.hpp )
endforeach()
foreach( name ${TARGETS_IDIOMATIC_TESTS} )
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch.hpp )
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp )
endforeach()
foreach( name ${TARGETS_ALL} )

View File

@@ -9,6 +9,9 @@
#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 3
#define CATCH_VERSION_PATCH 0
#ifdef __clang__
# pragma clang system_header
@@ -30,7 +33,9 @@
# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
# undef CATCH_CONFIG_DISABLE_MATCHERS
# endif
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
# endif
#endif
#if !defined(CATCH_CONFIG_IMPL_ONLY)
@@ -132,6 +137,7 @@
#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_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_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__ )
@@ -141,11 +147,11 @@
// "BDD-style" convenience wrappers
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#define CATCH_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 ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else
@@ -191,6 +197,7 @@
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
@@ -204,15 +211,16 @@
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#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 ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
using Catch::Detail::Approx;
#else
#else // CATCH_CONFIG_DISABLE
//////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL
@@ -257,6 +265,7 @@ using Catch::Detail::Approx;
#define CATCH_METHOD_AS_TEST_CASE( method, ... )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define CATCH_SECTION( ... )
#define CATCH_DYNAMIC_SECTION( ... )
#define CATCH_FAIL( ... ) (void)(0)
#define CATCH_FAIL_CHECK( ... ) (void)(0)
#define CATCH_SUCCEED( ... ) (void)(0)
@@ -316,6 +325,7 @@ using Catch::Detail::Approx;
#define METHOD_AS_TEST_CASE( method, ... )
#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define SECTION( ... )
#define DYNAMIC_SECTION( ... )
#define FAIL( ... ) (void)(0)
#define FAIL_CHECK( ... ) (void)(0)
#define SUCCEED( ... ) (void)(0)

View File

@@ -1,5 +1,11 @@
// v1.0-develop.2
// See https://github.com/philsquared/Clara
// 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)
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.4
#ifndef CATCH_CLARA_HPP_INCLUDED
#define CATCH_CLARA_HPP_INCLUDED
@@ -12,6 +18,16 @@
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
#endif
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#include <optional>
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
#endif
#endif
#endif
// ----------- #included from clara_textflow.hpp -----------
// TextFlowCpp
@@ -370,7 +386,7 @@ namespace detail {
template<typename ClassT, typename ReturnT, typename ArgT>
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
static const bool isValid = true;
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
using ReturnType = ReturnT;
};
@@ -383,11 +399,9 @@ namespace detail {
std::vector<std::string> m_args;
public:
Args( int argc, char *argv[] ) {
m_exeName = argv[0];
for( int i = 1; i < argc; ++i )
m_args.push_back( argv[i] );
}
Args( int argc, char const* const* argv )
: m_exeName(argv[0]),
m_args(argv + 1, argv + argc) {}
Args( std::initializer_list<std::string> args )
: m_exeName( *args.begin() ),
@@ -535,7 +549,7 @@ namespace detail {
return *this;
}
~ResultValueBase() {
~ResultValueBase() override {
if( m_type == Ok )
m_value.~T();
}
@@ -573,16 +587,14 @@ namespace detail {
auto errorMessage() const -> std::string { return m_errorMessage; }
protected:
virtual void enforceOk() const {
// !TBD: If no exceptions, std::terminate here or something
switch( m_type ) {
case ResultBase::LogicError:
throw std::logic_error( m_errorMessage );
case ResultBase::RuntimeError:
throw std::runtime_error( m_errorMessage );
case ResultBase::Ok:
break;
}
void enforceOk() const override {
// Errors shouldn't reach this point, but if they do
// the actual error message will be in m_errorMessage
assert( m_type != ResultBase::LogicError );
assert( m_type != ResultBase::RuntimeError );
if( m_type != ResultBase::Ok )
std::abort();
}
std::string m_errorMessage; // Only populated if resultType is an error
@@ -652,47 +664,43 @@ namespace detail {
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
return ParserResult::ok( ParseResultType::Matched );
}
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
template<typename T>
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
T temp;
auto result = convertInto( source, temp );
if( result )
target = std::move(temp);
return result;
}
#endif // CLARA_CONFIG_OPTIONAL_TYPE
struct BoundRefBase {
BoundRefBase() = default;
BoundRefBase( BoundRefBase const & ) = delete;
BoundRefBase( BoundRefBase && ) = delete;
BoundRefBase &operator=( BoundRefBase const & ) = delete;
BoundRefBase &operator=( BoundRefBase && ) = delete;
struct NonCopyable {
NonCopyable() = default;
NonCopyable( NonCopyable const & ) = delete;
NonCopyable( NonCopyable && ) = delete;
NonCopyable &operator=( NonCopyable const & ) = delete;
NonCopyable &operator=( NonCopyable && ) = delete;
};
virtual ~BoundRefBase() = default;
virtual auto isFlag() const -> bool = 0;
struct BoundRef : NonCopyable {
virtual ~BoundRef() = default;
virtual auto isContainer() const -> bool { return false; }
virtual auto isFlag() const -> bool { return false; }
};
struct BoundValueRefBase : BoundRef {
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
};
struct BoundFlagRefBase : BoundRef {
virtual auto setFlag( bool flag ) -> ParserResult = 0;
};
struct BoundValueRefBase : BoundRefBase {
auto isFlag() const -> bool override { return false; }
auto setFlag( bool ) -> ParserResult override {
return ParserResult::logicError( "Flags can only be set on boolean fields" );
}
};
struct BoundFlagRefBase : BoundRefBase {
auto isFlag() const -> bool override { return true; }
auto setValue( std::string const &arg ) -> ParserResult override {
bool flag;
auto result = convertInto( arg, flag );
if( result )
setFlag( flag );
return result;
}
virtual auto isFlag() const -> bool { return true; }
};
template<typename T>
struct BoundRef : BoundValueRefBase {
struct BoundValueRef : BoundValueRefBase {
T &m_ref;
explicit BoundRef( T &ref ) : m_ref( ref ) {}
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
auto setValue( std::string const &arg ) -> ParserResult override {
return convertInto( arg, m_ref );
@@ -700,10 +708,10 @@ namespace detail {
};
template<typename T>
struct BoundRef<std::vector<T>> : BoundValueRefBase {
struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
std::vector<T> &m_ref;
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
auto isContainer() const -> bool override { return true; }
@@ -748,12 +756,12 @@ namespace detail {
template<typename ArgType, typename L>
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
ArgType temp;
ArgType temp{};
auto result = convertInto( arg, temp );
return !result
? result
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
};
}
template<typename L>
@@ -803,6 +811,9 @@ namespace detail {
public:
template<typename T>
auto operator|( T const &other ) const -> Parser;
template<typename T>
auto operator+( T const &other ) const -> Parser;
};
// Common code and state for Args and Opts
@@ -810,16 +821,16 @@ namespace detail {
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
protected:
Optionality m_optionality = Optionality::Optional;
std::shared_ptr<BoundRefBase> m_ref;
std::shared_ptr<BoundRef> m_ref;
std::string m_hint;
std::string m_description;
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
public:
template<typename T>
ParserRefImpl( T &ref, std::string const &hint )
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
m_hint( hint )
{}
@@ -860,10 +871,10 @@ namespace detail {
class ExeName : public ComposableParserImpl<ExeName> {
std::shared_ptr<std::string> m_name;
std::shared_ptr<BoundRefBase> m_ref;
std::shared_ptr<BoundValueRefBase> m_ref;
template<typename LambdaT>
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
}
@@ -871,7 +882,7 @@ namespace detail {
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
explicit ExeName( std::string &ref ) : ExeName() {
m_ref = std::make_shared<BoundRef<std::string>>( ref );
m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
}
template<typename LambdaT>
@@ -914,7 +925,10 @@ namespace detail {
if( token.type != TokenType::Argument )
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
auto result = m_ref->setValue( remainingTokens->token );
assert( !m_ref->isFlag() );
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
auto result = valueRef->setValue( remainingTokens->token );
if( !result )
return InternalParseResult( result );
else
@@ -988,19 +1002,21 @@ namespace detail {
auto const &token = *remainingTokens;
if( isMatch(token.token ) ) {
if( m_ref->isFlag() ) {
auto result = m_ref->setFlag( true );
auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
auto result = flagRef->setFlag( true );
if( !result )
return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll )
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
} else {
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
++remainingTokens;
if( !remainingTokens )
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto const &argToken = *remainingTokens;
if( argToken.type != TokenType::Argument )
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto result = m_ref->setValue( argToken.token );
auto result = valueRef->setValue( argToken.token );
if( !result )
return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll )
@@ -1077,6 +1093,12 @@ namespace detail {
return Parser( *this ) |= other;
}
// Forward deprecated interface with '+' instead of '|'
template<typename T>
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
template<typename T>
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
auto getHelpColumns() const -> std::vector<HelpColumns> {
std::vector<HelpColumns> cols;
for (auto const &o : m_options) {
@@ -1116,6 +1138,8 @@ namespace detail {
for( auto const &cols : rows )
optWidth = (std::max)(optWidth, cols.left.size() + 2);
optWidth = (std::min)(optWidth, consoleWidth/2);
for( auto const &cols : rows ) {
auto row =
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +

View File

@@ -35,6 +35,13 @@ namespace Detail {
return Approx( 0 );
}
Approx Approx::operator-() const {
auto temp(*this);
temp.m_value = -temp.m_value;
return temp;
}
std::string Approx::toString() const {
ReusableStringStream rss;
rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
@@ -49,6 +56,15 @@ namespace Detail {
} // end namespace Detail
namespace literals {
Detail::Approx operator "" _a(long double val) {
return Detail::Approx(val);
}
Detail::Approx operator "" _a(unsigned long long val) {
return Detail::Approx(val);
}
} // end namespace literals
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
return value.toString();
}

View File

@@ -25,6 +25,8 @@ namespace Detail {
static Approx custom();
Approx operator-() const;
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx operator()( T const& value ) {
Approx approx( static_cast<double>(value) );
@@ -121,7 +123,12 @@ namespace Detail {
double m_scale;
double m_value;
};
}
} // end namespace Detail
namespace literals {
Detail::Approx operator "" _a(long double val);
Detail::Approx operator "" _a(unsigned long long val);
} // end namespace literals
template<>
struct StringMaker<Catch::Detail::Approx> {

View File

@@ -18,9 +18,11 @@
namespace Catch {
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
expr.streamReconstructedExpression( os );
return os;
namespace {
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
expr.streamReconstructedExpression( os );
return os;
}
}
LazyExpression::LazyExpression( bool isNegated )

View File

@@ -65,9 +65,9 @@ namespace Catch {
expr = m_info.capturedExpression;
else {
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
expr += m_info.macroName.c_str();
expr += m_info.macroName;
expr += "( ";
expr += m_info.capturedExpression.c_str();
expr += m_info.capturedExpression;
expr += " )";
}
return expr;

View File

@@ -115,7 +115,7 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( false )

View File

@@ -13,7 +13,7 @@ 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
// There is another overload, in catch_assertionhandler.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();

View File

@@ -11,6 +11,7 @@
#include "catch_capture.hpp"
#include "catch_matchers.h"
#include "catch_matchers_floating.h"
#include "catch_matchers_generic.hpp"
#include "catch_matchers_string.h"
#include "catch_matchers_vector.h"

View File

@@ -20,9 +20,19 @@ namespace Catch {
using namespace clara;
auto const setWarning = [&]( std::string const& warning ) {
if( warning != "NoAssertions" )
auto warningSet = [&]() {
if( warning == "NoAssertions" )
return WarnAbout::NoAssertions;
if ( warning == "NoTests" )
return WarnAbout::NoTests;
return WarnAbout::Nothing;
}();
if (warningSet == WarnAbout::Nothing)
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
return ParserResult::ok( ParseResultType::Matched );
};
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
@@ -120,7 +130,7 @@ namespace Catch {
| Opt( config.outputFilename, "filename" )
["-o"]["--out"]
( "output filename" )
| Opt( config.reporterNames, "name" )
| Opt( config.reporterName, "name" )
["-r"]["--reporter"]
( "reporter to use (defaults to console)" )
| Opt( config.name, "name" )

View File

@@ -24,6 +24,7 @@
// Many features, at point of detection, define an _INTERNAL_ macro, so they
// can be combined, en-mass, with the _NO_ forms later.
#include "catch_platform.h"
#ifdef __cplusplus
@@ -31,6 +32,14 @@
# define CATCH_CPP14_OR_GREATER
# endif
# if __cplusplus >= 201703L
# define CATCH_CPP17_OR_GREATER
# endif
#endif
#if defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#ifdef __clang__
@@ -48,17 +57,25 @@
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
_Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
_Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
_Pragma( "clang diagnostic pop" )
#endif // __clang__
////////////////////////////////////////////////////////////////////////////////
// Assume that non-Windows platforms support posix signals by default
#if !defined(CATCH_PLATFORM_WINDOWS)
#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
#endif
////////////////////////////////////////////////////////////////////////////////
// We know some environments not to support full POSIX signals
#if defined(__CYGWIN__) || defined(__QNX__)
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# endif
#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
#endif
#ifdef __OS400__
@@ -66,6 +83,24 @@
# define CATCH_CONFIG_COLOUR_NONE
#endif
////////////////////////////////////////////////////////////////////////////////
// Android somehow still does not support std::to_string
#if defined(__ANDROID__)
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
#endif
////////////////////////////////////////////////////////////////////////////////
// Not all Windows environments support SEH properly
#if defined(__MINGW32__)
# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
#endif
////////////////////////////////////////////////////////////////////////////////
// PS4
#if defined(__ORBIS__)
# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
#endif
////////////////////////////////////////////////////////////////////////////////
// Cygwin
#ifdef __CYGWIN__
@@ -80,6 +115,11 @@
// Visual C++
#ifdef _MSC_VER
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
// Universal Windows platform does not support SEH
// Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@@ -92,6 +132,13 @@
////////////////////////////////////////////////////////////////////////////////
// DJGPP
#ifdef __DJGPP__
# define CATCH_INTERNAL_CONFIG_NO_WCHAR
#endif // __DJGPP__
////////////////////////////////////////////////////////////////////////////////
// Use of __COUNTER__ is suppressed during code analysis in
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
// handled by it.
@@ -104,13 +151,33 @@
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
# define CATCH_CONFIG_WINDOWS_SEH
#endif
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
# define CATCH_CONFIG_POSIX_SIGNALS
#endif
// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
# define CATCH_CONFIG_WCHAR
#endif
#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
# define CATCH_CONFIG_CPP11_TO_STRING
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
#endif
#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
# define CATCH_CONFIG_NEW_CAPTURE
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -120,6 +187,10 @@
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
#endif
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED

View File

@@ -15,12 +15,16 @@ namespace Catch {
: m_data( data ),
m_stream( openStream() )
{
if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() );
TestSpecParser parser(ITagAliasRegistry::get());
if (data.testsOrTags.empty()) {
parser.parse("~[.]"); // All not hidden tests
}
else {
m_hasTestFilters = true;
for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags );
m_testSpec = parser.testSpec();
}
m_testSpec = parser.testSpec();
}
std::string const& Config::getFilename() const {
@@ -33,11 +37,13 @@ namespace Catch {
bool Config::listReporters() const { return m_data.listReporters; }
std::string Config::getProcessName() const { return m_data.processName; }
std::string const& Config::getReporterName() const { return m_data.reporterName; }
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
TestSpec const& Config::testSpec() const { return m_testSpec; }
bool Config::hasTestFilters() const { return m_hasTestFilters; }
bool Config::showHelp() const { return m_data.showHelp; }
@@ -46,7 +52,8 @@ namespace Catch {
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; }
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
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; }

View File

@@ -54,8 +54,12 @@ namespace Catch {
std::string outputFilename;
std::string name;
std::string processName;
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
#undef CATCH_CONFIG_DEFAULT_REPORTER
std::vector<std::string> reporterNames;
std::vector<std::string> testsOrTags;
std::vector<std::string> sectionsToRun;
};
@@ -76,11 +80,13 @@ namespace Catch {
bool listReporters() const;
std::string getProcessName() const;
std::string const& getReporterName() const;
std::vector<std::string> const& getReporterNames() const;
std::vector<std::string> const& getTestsOrTags() const;
std::vector<std::string> const& getSectionsToRun() const override;
virtual TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const;
@@ -90,6 +96,7 @@ namespace Catch {
std::string name() const override;
bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override;
ShowDurations::OrNot showDurations() const override;
RunTests::InWhatOrder runOrder() const override;
unsigned int rngSeed() const override;
@@ -107,6 +114,7 @@ namespace Catch {
std::unique_ptr<IStream const> m_stream;
TestSpec m_testSpec;
bool m_hasTestFilters = false;
};
} // end namespace Catch

View File

@@ -11,8 +11,8 @@
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wexit-time-destructors"
#endif
#include "catch_console_colour.h"
#include "catch_enforce.h"
#include "catch_errno_guard.h"
@@ -84,8 +84,12 @@ namespace {
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
default:
CATCH_ERROR( "Unknown colour requested" );
}
}
@@ -143,8 +147,10 @@ namespace {
case Colour::BrightRed: return setColour( "[1;31m" );
case Colour::BrightGreen: return setColour( "[1;32m" );
case Colour::BrightWhite: return setColour( "[1;37m" );
case Colour::BrightYellow: return setColour( "[1;33m" );
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
}
}
static IColourImpl* instance() {
@@ -163,7 +169,12 @@ namespace {
#ifdef CATCH_PLATFORM_MAC
!isDebuggerActive() &&
#endif
isatty(STDOUT_FILENO);
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
isatty(STDOUT_FILENO)
#else
false
#endif
;
}
IColourImpl* platformColourInstance() {
ErrnoGuard guard;
@@ -196,7 +207,7 @@ namespace Catch {
namespace Catch {
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour::Colour( Colour&& rhs ) noexcept {
Colour::Colour( Colour&& rhs ) noexcept {
m_moved = rhs.m_moved;
rhs.m_moved = true;
}
@@ -205,7 +216,7 @@ namespace Catch {
rhs.m_moved = true;
return *this;
}
Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) {

View File

@@ -30,10 +30,11 @@ namespace Catch {
BrightGreen = Bright | Green,
LightGrey = Bright | Grey,
BrightWhite = Bright | White,
BrightYellow = Bright | Yellow,
// By intention
FileName = LightGrey,
Warning = Yellow,
Warning = BrightYellow,
ResultError = BrightRed,
ResultSuccess = BrightGreen,
ResultExpectedFailure = Warning,
@@ -42,7 +43,7 @@ namespace Catch {
Success = Green,
OriginalExpression = Cyan,
ReconstructedExpression = Yellow,
ReconstructedExpression = BrightYellow,
SecondaryText = LightGrey,
Headers = White

View File

@@ -9,21 +9,23 @@
#include "catch_debug_console.h"
#include "catch_stream.h"
#include "catch_platform.h"
#include "catch_windows_h_proxy.h"
#ifdef CATCH_PLATFORM_WINDOWS
#include "catch_windows_h_proxy.h"
namespace Catch {
void writeToDebugConsole( std::string const& text ) {
::OutputDebugStringA( text.c_str() );
}
}
#else
namespace Catch {
void writeToDebugConsole( std::string const& text ) {
// !TBD: Need a version for Mac/ XCode and other IDEs
Catch::cout() << text;
}
}
#endif // Platform

View File

@@ -40,7 +40,10 @@ namespace Catch {
#ifdef CATCH_TRAP
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
#else
#define CATCH_BREAK_INTO_DEBUGGER() (void)0, 0
namespace Catch {
inline void doNothing() {}
}
#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
#endif
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED

View File

@@ -82,7 +82,7 @@ namespace Catch {
// 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 const& rhs ) -> bool { return lhs == rhs; };
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
template<typename T>
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
template<typename T>
@@ -93,7 +93,7 @@ namespace Catch {
auto compareEqual( long 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 lhs != rhs; };
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
template<typename T>
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
template<typename T>
@@ -128,19 +128,19 @@ namespace Catch {
template<typename RhsT>
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { m_lhs > rhs, m_lhs, ">", rhs };
return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
}
template<typename RhsT>
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { m_lhs < rhs, m_lhs, "<", rhs };
return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
}
template<typename RhsT>
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { m_lhs >= rhs, m_lhs, ">=", rhs };
return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
}
template<typename RhsT>
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { m_lhs <= rhs, m_lhs, "<=", rhs };
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
}
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {

View File

@@ -12,7 +12,7 @@
#ifndef __OBJC__
#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
// Standard C/C++ Win32 Unicode wmain entry point
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
#else

View File

@@ -11,10 +11,9 @@
#include "catch_stream.h"
#include <stdexcept>
#include <iosfwd>
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() )
type( ( Catch::ReusableStringStream() << 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 ) \

View File

@@ -33,6 +33,17 @@ namespace Catch {
return Catch::Detail::stringify( [exception description] );
}
#else
// Compiling a mixed mode project with MSVC means that CLR
// exceptions will be caught in (...) as well. However, these
// do not fill-in std::current_exception and thus lead to crash
// when attempting rethrow.
// /EHa switch also causes structured exceptions to be caught
// here, but they fill-in current_exception properly, so
// at worst the output should be a little weird, instead of
// causing a crash.
if (std::current_exception() == nullptr) {
return "Non C++ exception. Possibly a CLR exception.";
}
return tryTranslators();
#endif
}

View File

@@ -17,6 +17,8 @@
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
namespace {
// Report the error condition
void reportFatal( char const * const message ) {
@@ -24,15 +26,9 @@ namespace {
}
}
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
#endif // signals/SEH handling
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
void FatalConditionHandler::reset() {}
}
# else // CATCH_CONFIG_WINDOWS_SEH is defined
#if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
struct SignalDefs { DWORD id; const char* name; };
@@ -72,7 +68,6 @@ namespace Catch {
void FatalConditionHandler::reset() {
if (isSet) {
// Unregister handler and restore the old guarantee
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
SetThreadStackGuarantee(&guaranteeSize);
exceptionHandlerHandle = nullptr;
@@ -91,20 +86,7 @@ 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>
#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
namespace Catch {
@@ -112,6 +94,11 @@ namespace Catch {
int id;
const char* name;
};
// 32kb for the alternate stack seems to be sufficient. However, this value
// is experimentally determined, so that's not guaranteed.
constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
static SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" },
@@ -139,7 +126,7 @@ namespace Catch {
isSet = true;
stack_t sigStack;
sigStack.ss_sp = altStackMem;
sigStack.ss_size = SIGSTKSZ;
sigStack.ss_size = sigStackSize;
sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { };
@@ -171,14 +158,18 @@ namespace Catch {
bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
char FatalConditionHandler::altStackMem[sigStackSize] = {};
} // namespace Catch
# endif // CATCH_CONFIG_POSIX_SIGNALS
#else
#endif // not Windows
namespace Catch {
void FatalConditionHandler::reset() {}
}
#endif // signals/SEH handling
#if defined(__GNUC__)
# pragma GCC diagnostic pop

View File

@@ -9,23 +9,12 @@
#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"
#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
#if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
@@ -44,20 +33,7 @@ namespace Catch {
} // 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
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
#include <signal.h>
@@ -66,7 +42,7 @@ namespace Catch {
struct FatalConditionHandler {
static bool isSet;
static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)];
static struct sigaction oldSigActions[];
static stack_t oldSigStack;
static char altStackMem[];
@@ -79,8 +55,15 @@ namespace Catch {
} // namespace Catch
# endif // CATCH_CONFIG_POSIX_SIGNALS
#endif // not Windows
#else
namespace Catch {
struct FatalConditionHandler {
void reset();
};
}
#endif
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED

View File

@@ -25,7 +25,8 @@ namespace Catch {
struct WarnAbout { enum What {
Nothing = 0x00,
NoAssertions = 0x01
NoAssertions = 0x01,
NoTests = 0x02
}; };
struct ShowDurations { enum OrNot {
@@ -62,10 +63,12 @@ namespace Catch {
virtual bool includeSuccessfulResults() const = 0;
virtual bool shouldDebugBreak() const = 0;
virtual bool warnAboutMissingAssertions() const = 0;
virtual bool warnAboutNoTests() const = 0;
virtual int abortAfter() const = 0;
virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0;
virtual TestSpec const& testSpec() const = 0;
virtual bool hasTestFilters() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual int benchmarkResolutionMultiple() const = 0;

View File

@@ -6,7 +6,7 @@
*/
#include "catch_interfaces_reporter.h"
#include "../reporters/catch_reporter_multi.h"
#include "../reporters/catch_reporter_listening.h"
namespace Catch {
@@ -111,25 +111,4 @@ namespace Catch {
IReporterFactory::~IReporterFactory() = default;
IReporterRegistry::~IReporterRegistry() = default;
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

@@ -42,6 +42,7 @@ namespace Catch {
struct ReporterPreferences {
bool shouldRedirectStdOut = false;
bool shouldReportAllAssertions = false;
};
template<typename T>
@@ -226,8 +227,6 @@ namespace Catch {
virtual Listeners const& getListeners() const = 0;
};
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED

View File

@@ -28,11 +28,10 @@ namespace Catch {
std::size_t listTests( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() )
if( config.hasTestFilters() )
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 );
@@ -54,7 +53,7 @@ namespace Catch {
Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
}
if( !config.testSpec().hasFilters() )
if( !config.hasTestFilters() )
Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
else
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
@@ -63,8 +62,6 @@ namespace Catch {
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 ) {
@@ -94,11 +91,10 @@ namespace Catch {
std::size_t listTags( Config const& config ) {
TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() )
if( config.hasTestFilters() )
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;

View File

@@ -6,6 +6,7 @@
*/
#include "catch_matchers_floating.h"
#include "catch_to_string.hpp"
#include "catch_tostring.h"
#include <cstdlib>
@@ -88,7 +89,7 @@ namespace Floating {
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
// But without the subtraction to allow for INFINITY in comparison
bool WithinAbsMatcher::match(double const& matchee) const {
return (matchee + m_margin >= m_target) && (m_target + m_margin >= m_margin);
return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
}
std::string WithinAbsMatcher::describe() const {
@@ -115,7 +116,7 @@ namespace Floating {
}
std::string WithinUlpsMatcher::describe() const {
return "is within " + std::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
}
}// namespace Floating

View File

@@ -0,0 +1,9 @@
#include "catch_matchers_generic.hpp"
std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
if (desc.empty()) {
return "matches undescribed predicate";
} else {
return "matches predicate: \"" + desc + '"';
}
}

View File

@@ -0,0 +1,58 @@
/*
* Created by Martin Hořeňovský on 03/04/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_MATCHERS_GENERIC_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
#include "catch_common.h"
#include "catch_matchers.h"
#include <functional>
#include <string>
namespace Catch {
namespace Matchers {
namespace Generic {
namespace Detail {
std::string finalizeDescription(const std::string& desc);
}
template <typename T>
class PredicateMatcher : public MatcherBase<T> {
std::function<bool(T const&)> m_predicate;
std::string m_description;
public:
PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
:m_predicate(std::move(elem)),
m_description(Detail::finalizeDescription(descr))
{}
bool match( T const& item ) const override {
return m_predicate(item);
}
std::string describe() const override {
return m_description;
}
};
} // namespace Generic
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
// infering std::function<bool(T const&)> is hard (but possible) and
// requires a lot of TMP.
template<typename T>
Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
return Generic::PredicateMatcher<T>(predicate, description);
}
} // namespace Matchers
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED

View File

@@ -8,6 +8,7 @@
#include "catch_message.h"
#include "catch_interfaces_capture.h"
#include "catch_uncaught_exceptions.h"
namespace Catch {
@@ -49,18 +50,9 @@ namespace Catch {
getResultCapture().pushScopedMessage( m_info );
}
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
#endif
ScopedMessage::~ScopedMessage() {
if ( !std::uncaught_exception() ){
if ( !uncaught_exceptions() ){
getResultCapture().popScopedMessage(m_info);
}
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
} // end namespace Catch

View File

@@ -93,7 +93,7 @@ namespace Catch {
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
const char* className = class_getName( cls );
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) );
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
noTestMethods++;
}
}

View File

@@ -0,0 +1,139 @@
/*
* Created by Martin on 28/04/2018.
*
* 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_output_redirect.h"
#include <cstdio>
#include <cstring>
#include <fstream>
#include <sstream>
#include <stdexcept>
#if defined(CATCH_CONFIG_NEW_CAPTURE)
#if defined(_MSC_VER)
#include <io.h> //_dup and _dup2
#define dup _dup
#define dup2 _dup2
#define fileno _fileno
#else
#include <unistd.h> // dup and dup2
#endif
#endif
namespace Catch {
RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
: m_originalStream( originalStream ),
m_redirectionStream( redirectionStream ),
m_prevBuf( m_originalStream.rdbuf() )
{
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
}
RedirectedStream::~RedirectedStream() {
m_originalStream.rdbuf( m_prevBuf );
}
RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
RedirectedStdErr::RedirectedStdErr()
: m_cerr( Catch::cerr(), m_rss.get() ),
m_clog( Catch::clog(), m_rss.get() )
{}
auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
#if defined(CATCH_CONFIG_NEW_CAPTURE)
#if defined(_MSC_VER)
TempFile::TempFile() {
if (tmpnam_s(m_buffer)) {
throw std::runtime_error("Could not get a temp filename");
}
if (fopen_s(&m_file, m_buffer, "w")) {
char buffer[100];
if (strerror_s(buffer, errno)) {
throw std::runtime_error("Could not translate errno to string");
}
throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer);
}
}
#else
TempFile::TempFile() {
m_file = std::tmpfile();
if (!m_file) {
throw std::runtime_error("Could not create a temp file.");
}
}
#endif
TempFile::~TempFile() {
// TBD: What to do about errors here?
std::fclose(m_file);
// We manually create the file on Windows only, on Linux
// it will be autodeleted
#if defined(_MSC_VER)
std::remove(m_buffer);
#endif
}
FILE* TempFile::getFile() {
return m_file;
}
std::string TempFile::getContents() {
std::stringstream sstr;
char buffer[100] = {};
std::rewind(m_file);
while (std::fgets(buffer, sizeof(buffer), m_file)) {
sstr << buffer;
}
return sstr.str();
}
OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
m_originalStdout(dup(1)),
m_originalStderr(dup(2)),
m_stdoutDest(stdout_dest),
m_stderrDest(stderr_dest) {
dup2(fileno(m_stdoutFile.getFile()), 1);
dup2(fileno(m_stderrFile.getFile()), 2);
}
OutputRedirect::~OutputRedirect() {
Catch::cout() << std::flush;
fflush(stdout);
// Since we support overriding these streams, we flush cerr
// even though std::cerr is unbuffered
Catch::cerr() << std::flush;
Catch::clog() << std::flush;
fflush(stderr);
dup2(m_originalStdout, 1);
dup2(m_originalStderr, 2);
m_stdoutDest += m_stdoutFile.getContents();
m_stderrDest += m_stderrFile.getContents();
}
#endif // CATCH_CONFIG_NEW_CAPTURE
} // namespace Catch
#if defined(CATCH_CONFIG_NEW_CAPTURE)
#if defined(_MSC_VER)
#undef dup
#undef dup2
#undef fileno
#endif
#endif

View File

@@ -0,0 +1,101 @@
/*
* Created by Martin on 28/04/2018.
*
* 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_OUTPUT_REDIRECT_H
#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
#include "catch_platform.h"
#include "catch_stream.h"
#include <cstdio>
#include <iosfwd>
#include <string>
namespace Catch {
class RedirectedStream {
std::ostream& m_originalStream;
std::ostream& m_redirectionStream;
std::streambuf* m_prevBuf;
public:
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
~RedirectedStream();
};
class RedirectedStdOut {
ReusableStringStream m_rss;
RedirectedStream m_cout;
public:
RedirectedStdOut();
auto str() const -> std::string;
};
// StdErr has two constituent streams in C++, std::cerr and std::clog
// This means that we need to redirect 2 streams into 1 to keep proper
// order of writes
class RedirectedStdErr {
ReusableStringStream m_rss;
RedirectedStream m_cerr;
RedirectedStream m_clog;
public:
RedirectedStdErr();
auto str() const -> std::string;
};
#if defined(CATCH_CONFIG_NEW_CAPTURE)
// Windows's implementation of std::tmpfile is terrible (it tries
// to create a file inside system folder, thus requiring elevated
// privileges for the binary), so we have to use tmpnam(_s) and
// create the file ourselves there.
class TempFile {
public:
TempFile(TempFile const&) = delete;
TempFile& operator=(TempFile const&) = delete;
TempFile(TempFile&&) = delete;
TempFile& operator=(TempFile&&) = delete;
TempFile();
~TempFile();
std::FILE* getFile();
std::string getContents();
private:
std::FILE* m_file = nullptr;
#if defined(_MSC_VER)
char m_buffer[L_tmpnam] = { 0 };
#endif
};
class OutputRedirect {
public:
OutputRedirect(OutputRedirect const&) = delete;
OutputRedirect& operator=(OutputRedirect const&) = delete;
OutputRedirect(OutputRedirect&&) = delete;
OutputRedirect& operator=(OutputRedirect&&) = delete;
OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
~OutputRedirect();
private:
int m_originalStdout = -1;
int m_originalStderr = -1;
TempFile m_stdoutFile;
TempFile m_stderrFile;
std::string& m_stdoutDest;
std::string& m_stderrDest;
};
#endif
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H

View File

@@ -20,7 +20,7 @@
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
# define CATCH_PLATFORM_WINDOWS
#endif

View File

@@ -9,23 +9,21 @@
#include "catch_context.h"
#include "catch_interfaces_config.h"
#include <cstdlib>
namespace Catch {
void seedRng( IConfig const& config ) {
if( config.rngSeed() != 0 )
std::srand( config.rngSeed() );
std::mt19937& rng() {
static std::mt19937 s_rng;
return s_rng;
}
void seedRng( IConfig const& config ) {
if( config.rngSeed() != 0 ) {
std::srand( config.rngSeed() );
rng().seed( config.rngSeed() );
}
}
unsigned int rngSeed() {
return getCurrentContext().getConfig()->rngSeed();
}
RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const {
return std::rand() % n;
}
RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const {
return std::rand() % (max)();
}
}

View File

@@ -8,31 +8,16 @@
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
#include <algorithm>
#include <random>
namespace Catch {
struct IConfig;
std::mt19937& rng();
void seedRng( IConfig const& config );
unsigned int rngSeed();
struct RandomNumberGenerator {
using result_type = unsigned int;
static constexpr result_type (min)() { return 0; }
static constexpr result_type (max)() { return 1000000; }
result_type operator()( result_type n ) const;
result_type operator()() const;
template<typename V>
static void shuffle( V& vector ) {
RandomNumberGenerator rng;
std::shuffle( vector.begin(), vector.end(), rng );
}
};
}
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED

View File

@@ -3,6 +3,7 @@
#include "catch_enforce.h"
#include "catch_random_number_generator.h"
#include "catch_stream.h"
#include "catch_output_redirect.h"
#include <cassert>
#include <algorithm>
@@ -10,55 +11,13 @@
namespace Catch {
class RedirectedStream {
std::ostream& m_originalStream;
std::ostream& m_redirectionStream;
std::streambuf* m_prevBuf;
public:
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
: m_originalStream( originalStream ),
m_redirectionStream( redirectionStream ),
m_prevBuf( m_originalStream.rdbuf() )
{
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
}
~RedirectedStream() {
m_originalStream.rdbuf( m_prevBuf );
}
};
class RedirectedStdOut {
ReusableStringStream m_rss;
RedirectedStream m_cout;
public:
RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
auto str() const -> std::string { return m_rss.str(); }
};
// StdErr has two constituent streams in C++, std::cerr and std::clog
// This means that we need to redirect 2 streams into 1 to keep proper
// order of writes
class RedirectedStdErr {
ReusableStringStream m_rss;
RedirectedStream m_cerr;
RedirectedStream m_clog;
public:
RedirectedStdErr()
: m_cerr( Catch::cerr(), m_rss.get() ),
m_clog( Catch::clog(), m_rss.get() )
{}
auto str() const -> std::string { return m_rss.str(); }
};
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
: m_runInfo(_config->name()),
m_context(getCurrentMutableContext()),
m_config(_config),
m_reporter(std::move(reporter)),
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal },
m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
{
m_context.setRunner(this);
m_context.setConfig(m_config);
@@ -84,7 +43,7 @@ namespace Catch {
std::string redirectedCout;
std::string redirectedCerr;
TestCaseInfo testInfo = testCase.getTestCaseInfo();
auto const& testInfo = testCase.getTestCaseInfo();
m_reporter->testCaseStarting(testInfo);
@@ -249,7 +208,7 @@ namespace Catch {
// Recreate section for test case (as we will lose the one that was in scope)
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
Counts assertions;
assertions.failed = 1;
@@ -287,25 +246,31 @@ namespace Catch {
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
m_reporter->sectionStarting(testCaseSection);
Counts prevAssertions = m_totals.assertions;
double duration = 0;
m_shouldReportUnexpected = true;
m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal };
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
seedRng(*m_config);
Timer timer;
try {
if (m_reporter->getPreferences().shouldRedirectStdOut) {
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
RedirectedStdOut redirectedStdOut;
RedirectedStdErr redirectedStdErr;
timer.start();
invokeActiveTestCase();
redirectedCout += redirectedStdOut.str();
redirectedCerr += redirectedStdErr.str();
#else
OutputRedirect r(redirectedCout, redirectedCerr);
timer.start();
invokeActiveTestCase();
#endif
} else {
timer.start();
invokeActiveTestCase();
@@ -321,12 +286,13 @@ namespace Catch {
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
}
}
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions);
m_testCaseTracker->close();
handleUnfinishedSections();
m_messages.clear();
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions);
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats);
}

View File

@@ -99,7 +99,7 @@ namespace Catch {
public:
// !TBD We need to do this another way!
bool aborting() const override;
bool aborting() const final;
private:

View File

@@ -8,6 +8,7 @@
#include "catch_section.h"
#include "catch_capture.hpp"
#include "catch_uncaught_exceptions.h"
namespace Catch {
@@ -18,22 +19,15 @@ namespace Catch {
m_timer.start();
}
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
#endif
Section::~Section() {
if( m_sectionIncluded ) {
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
if( std::uncaught_exception() )
SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
if( uncaught_exceptions() )
getResultCapture().sectionEndedEarly( endInfo );
else
getResultCapture().sectionEnded( endInfo );
}
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
// This indicates whether the section should be executed or not
Section::operator bool() const {

View File

@@ -8,6 +8,7 @@
#ifndef TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
#include "catch_compiler_capabilities.h"
#include "catch_section_info.h"
#include "catch_totals.h"
#include "catch_timer.h"
@@ -35,7 +36,14 @@ namespace Catch {
} // end namespace Catch
#define INTERNAL_CATCH_SECTION( ... ) \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
#define INTERNAL_CATCH_SECTION( ... ) \
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED

View File

@@ -11,15 +11,9 @@ namespace Catch {
SectionInfo::SectionInfo
( SourceLineInfo const& _lineInfo,
std::string const& _name,
std::string const& _description )
std::string const& _name )
: name( _name ),
description( _description ),
lineInfo( _lineInfo )
{}
SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
: sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
{}
} // end namespace Catch

View File

@@ -16,19 +16,22 @@
namespace Catch {
struct SectionInfo {
SectionInfo
( SourceLineInfo const& _lineInfo,
std::string const& _name );
// Deprecated
SectionInfo
( SourceLineInfo const& _lineInfo,
std::string const& _name,
std::string const& _description = std::string() );
std::string const& ) : SectionInfo( _lineInfo, _name ) {}
std::string name;
std::string description;
std::string description; // !Deprecated: this will always be empty
SourceLineInfo lineInfo;
};
struct SectionEndInfo {
SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds );
SectionInfo sectionInfo;
Counts prevAssertions;
double durationInSeconds;

View File

@@ -18,6 +18,9 @@
#include "catch_random_number_generator.h"
#include "catch_startup_exception_registry.h"
#include "catch_text.h"
#include "catch_stream.h"
#include "catch_windows_h_proxy.h"
#include "../reporters/catch_reporter_listening.h"
#include <cstdlib>
#include <iomanip>
@@ -34,33 +37,26 @@ namespace Catch {
return reporter;
}
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
auto const& reporterNames = config->getReporterNames();
if (reporterNames.empty())
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
return createReporter(config->getReporterName(), config);
}
IStreamingReporterPtr reporter;
for (auto const& name : reporterNames)
addReporter(reporter, createReporter(name, config));
return reporter;
}
auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
#undef CATCH_CONFIG_DEFAULT_REPORTER
void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
for (auto const& listener : listeners)
addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
for (auto const& listener : listeners) {
multi->addListener(listener->create(Catch::ReporterConfig(config)));
}
multi->addReporter(createReporter(config->getReporterName(), config));
return std::move(multi);
}
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
IStreamingReporterPtr reporter = makeReporter(config);
addListeners(reporter, config);
// FixMe: Add listeners in order first, then add reporters.
auto reporter = makeReporter(config);
RunContext context(config, std::move(reporter));
@@ -69,8 +65,6 @@ namespace Catch {
context.testGroupStarting(config->name(), 1, 1);
TestSpec testSpec = config->testSpec();
if (!testSpec.hasFilters())
testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
auto const& allTestCases = getAllTestCasesSorted(*config);
for (auto const& testCase : allTestCases) {
@@ -80,6 +74,20 @@ namespace Catch {
context.reporter().skipTest(testCase);
}
if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
ReusableStringStream testConfig;
bool first = true;
for (const auto& input : config->getTestsOrTags()) {
if (!first) { testConfig << ' '; }
first = false;
testConfig << input;
}
context.reporter().noMatchingTestCases(testConfig.str());
totals.error = -1;
}
context.testGroupEnded(config->name(), totals, 1, 1);
return totals;
}
@@ -119,7 +127,7 @@ namespace Catch {
if ( !exceptions.empty() ) {
m_startupExceptions = true;
Colour colourGuard( Colour::Red );
Catch::cerr() << "Errors occured during startup!" << '\n';
Catch::cerr() << "Errors occurred during startup!" << '\n';
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
@@ -151,7 +159,7 @@ namespace Catch {
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
}
int Session::applyCommandLine( int argc, char* argv[] ) {
int Session::applyCommandLine( int argc, char const * const * argv ) {
if( m_startupExceptions )
return 1;
@@ -188,7 +196,7 @@ namespace Catch {
return returnCode;
}
#if defined(WIN32) && defined(UNICODE)
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int Session::run( int argc, wchar_t* const argv[] ) {
char **utf8Argv = new char *[ argc ];
@@ -259,7 +267,11 @@ namespace Catch {
if( Option<std::size_t> listed = list( config() ) )
return static_cast<int>( *listed );
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
auto totals = runTests( m_config );
// 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 (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;

View File

@@ -25,12 +25,12 @@ namespace Catch {
void showHelp() const;
void libIdentify();
int applyCommandLine( int argc, char* argv[] );
int applyCommandLine( int argc, char const * const * argv );
void useConfigData( ConfigData const& configData );
int run( int argc, char* argv[] );
#if defined(WIN32) && defined(UNICODE)
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int run( int argc, wchar_t* const argv[] );
#endif
int run();

View File

@@ -14,6 +14,12 @@
namespace Catch {
namespace {
char toLowerCh(char c) {
return static_cast<char>( std::tolower( c ) );
}
}
bool startsWith( std::string const& s, std::string const& prefix ) {
return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
}
@@ -29,9 +35,6 @@ namespace Catch {
bool contains( std::string const& s, std::string const& infix ) {
return s.find( infix ) != std::string::npos;
}
char toLowerCh(char c) {
return static_cast<char>( std::tolower( c ) );
}
void toLowerInPlace( std::string& s ) {
std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
}

View File

@@ -15,6 +15,13 @@
#include <ostream>
#include <cstring>
#include <cstdint>
namespace {
const uint32_t byte_2_lead = 0xC0;
const uint32_t byte_3_lead = 0xE0;
const uint32_t byte_4_lead = 0xF0;
}
namespace Catch {
StringRef::StringRef( char const* rawChars ) noexcept
@@ -36,7 +43,7 @@ namespace Catch {
const_cast<StringRef*>( this )->takeOwnership();
return m_start;
}
auto StringRef::data() const noexcept -> char const* {
auto StringRef::currentData() const noexcept -> char const* {
return m_start;
}
@@ -79,13 +86,12 @@ namespace Catch {
// Make adjustments for uft encodings
for( size_type i=0; i < m_size; ++i ) {
char c = m_start[i];
if( ( c & 0b11000000 ) == 0b11000000 ) {
if( ( c & 0b11100000 ) == 0b11000000 )
if( ( c & byte_2_lead ) == byte_2_lead ) {
noChars--;
if (( c & byte_3_lead ) == byte_3_lead )
noChars--;
if( ( c & byte_4_lead ) == byte_4_lead )
noChars--;
else if( ( c & 0b11110000 ) == 0b11100000 )
noChars-=2;
else if( ( c & 0b11111000 ) == 0b11110000 )
noChars-=3;
}
}
return noChars;
@@ -106,7 +112,12 @@ namespace Catch {
}
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
return os << str.c_str();
return os.write(str.currentData(), str.size());
}
auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
lhs.append(rhs.currentData(), rhs.size());
return lhs;
}
} // namespace Catch

View File

@@ -12,7 +12,7 @@
#include <iosfwd>
namespace Catch {
class StringData;
/// A non-owning string class (similar to the forthcoming std::string_view)
@@ -31,13 +31,13 @@ namespace Catch {
char const* m_start;
size_type m_size;
char* m_data = nullptr;
void takeOwnership();
static constexpr char const* const s_empty = "";
public: // construction/ assignment
StringRef() noexcept
: StringRef( s_empty, 0 )
@@ -83,13 +83,13 @@ namespace Catch {
operator std::string() const;
void swap( StringRef& other ) noexcept;
public: // operators
auto operator == ( StringRef const& other ) const noexcept -> bool;
auto operator != ( StringRef const& other ) const noexcept -> bool;
auto operator[] ( size_type index ) const noexcept -> char;
public: // named queries
auto empty() const noexcept -> bool {
return m_size == 0;
@@ -100,22 +100,27 @@ namespace Catch {
auto numberOfCharacters() const noexcept -> size_type;
auto c_str() const -> char const*;
public: // substrings and searches
auto substr( size_type start, size_type size ) const noexcept -> StringRef;
// Returns the current start pointer.
// Note that the pointer can change when if the StringRef is a substring
auto currentData() const noexcept -> char const*;
private: // ownership queries - may not be consistent between calls
auto isOwned() const noexcept -> bool;
auto isSubstring() const noexcept -> bool;
auto data() const noexcept -> char const*;
};
auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
return StringRef( rawChars, size );
}

View File

@@ -10,15 +10,17 @@
# pragma warning(push)
# pragma warning(disable: 161 1682)
# else // __ICC
# pragma clang diagnostic ignored "-Wunused-variable"
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wswitch-enum"
# pragma clang diagnostic ignored "-Wcovered-switch-default"
# endif
#elif defined __GNUC__
# pragma GCC diagnostic ignored "-Wunused-variable"
// GCC likes to warn on REQUIREs, and we cannot suppress them
// locally because g++'s support for _Pragma is lacking in older,
// still supported, versions
# pragma GCC diagnostic ignored "-Wparentheses"
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic ignored "-Wpadded"
#endif

View File

@@ -19,37 +19,38 @@
namespace Catch {
TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
if( startsWith( tag, '.' ) ||
tag == "!hide" )
return TestCaseInfo::IsHidden;
else if( tag == "!throws" )
return TestCaseInfo::Throws;
else if( tag == "!shouldfail" )
return TestCaseInfo::ShouldFail;
else if( tag == "!mayfail" )
return TestCaseInfo::MayFail;
else if( tag == "!nonportable" )
return TestCaseInfo::NonPortable;
else if( tag == "!benchmark" )
return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
else
return TestCaseInfo::None;
}
bool isReservedTag( std::string const& tag ) {
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
}
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"
<< _lineInfo );
namespace {
TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
if( startsWith( tag, '.' ) ||
tag == "!hide" )
return TestCaseInfo::IsHidden;
else if( tag == "!throws" )
return TestCaseInfo::Throws;
else if( tag == "!shouldfail" )
return TestCaseInfo::ShouldFail;
else if( tag == "!mayfail" )
return TestCaseInfo::MayFail;
else if( tag == "!nonportable" )
return TestCaseInfo::NonPortable;
else if( tag == "!benchmark" )
return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
else
return TestCaseInfo::None;
}
bool isReservedTag( std::string const& tag ) {
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
}
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"
<< _lineInfo );
}
}
TestCase makeTestCase( ITestInvoker* _testCase,
std::string const& _className,
std::string const& _name,
std::string const& _descOrTags,
NameAndTags const& nameAndTags,
SourceLineInfo const& _lineInfo )
{
bool isHidden = false;
@@ -58,6 +59,7 @@ namespace Catch {
std::vector<std::string> tags;
std::string desc, tag;
bool inTag = false;
std::string _descOrTags = nameAndTags.tags;
for (char c : _descOrTags) {
if( !inTag ) {
if( c == '[' )
@@ -85,8 +87,8 @@ namespace Catch {
tags.push_back( "." );
}
TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
return TestCase( _testCase, info );
TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
return TestCase( _testCase, std::move(info) );
}
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
@@ -147,7 +149,7 @@ namespace Catch {
}
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
TestCase TestCase::withName( std::string const& _newName ) const {

View File

@@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
#include "catch_common.h"
#include "catch_test_registry.h"
#include <string>
#include <vector>
@@ -61,7 +62,7 @@ namespace Catch {
class TestCase : public TestCaseInfo {
public:
TestCase( ITestInvoker* testCase, TestCaseInfo const& info );
TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
TestCase withName( std::string const& _newName ) const;
@@ -78,8 +79,7 @@ namespace Catch {
TestCase makeTestCase( ITestInvoker* testCase,
std::string const& className,
std::string const& name,
std::string const& description,
NameAndTags const& nameAndTags,
SourceLineInfo const& lineInfo );
}

View File

@@ -28,7 +28,7 @@ namespace Catch {
break;
case RunTests::InRandomOrder:
seedRng( config );
RandomNumberGenerator::shuffle( sorted );
std::shuffle( sorted.begin(), sorted.end(), rng() );
break;
case RunTests::InDeclarationOrder:
// already in declaration order
@@ -96,7 +96,7 @@ namespace Catch {
m_testAsFunction();
}
std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
std::string className = classOrQualifiedMethodName;
if( startsWith( className, '&' ) )
{

View File

@@ -22,7 +22,7 @@ namespace Catch {
class TestCase;
struct IConfig;
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
@@ -58,7 +58,7 @@ namespace Catch {
};
std::string extractClassName( std::string const& classOrQualifiedMethodName );
std::string extractClassName( StringRef const& classOrQualifiedMethodName );
///////////////////////////////////////////////////////////////////////////

View File

@@ -10,7 +10,7 @@
#include "catch_enforce.h"
#include <algorithm>
#include <assert.h>
#include <cassert>
#include <stdexcept>
#include <memory>
#include <sstream>
@@ -73,8 +73,8 @@ namespace TestCaseTracking {
TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
return
tracker->nameAndLocation().name == m_nameAndLocation.name &&
tracker->nameAndLocation().location == m_nameAndLocation.location;
tracker->nameAndLocation().location == m_nameAndLocation.location &&
tracker->nameAndLocation().name == m_nameAndLocation.name;
}
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )

View File

@@ -15,23 +15,22 @@ namespace Catch {
return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
}
NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
try {
getMutableRegistryHub()
.registerTest(
makeTestCase(
invoker,
extractClassName( classOrMethod ),
nameAndTags.name,
nameAndTags.tags,
nameAndTags,
lineInfo));
} catch (...) {
// Do not throw when constructing global objects, instead register the exception to be processed later
getMutableRegistryHub().registerStartupException();
}
}
AutoReg::~AutoReg() = default;
}

View File

@@ -35,24 +35,29 @@ auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
}
struct NameAndTags {
NameAndTags( StringRef name_ = StringRef(), StringRef tags_ = StringRef() ) noexcept;
NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
StringRef name;
StringRef tags;
};
struct AutoReg : NonCopyable {
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
~AutoReg();
};
} // end namespace Catch
#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
#if defined(CATCH_CONFIG_DISABLE)
#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
static void TestName()
#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
namespace{ \
struct TestName : ClassName { \
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
void test(); \
}; \
} \
@@ -64,7 +69,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName(); \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
static void TestName()
#define INTERNAL_CATCH_TESTCASE( ... ) \
@@ -80,7 +85,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ \
struct TestName : ClassName{ \
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
@@ -93,7 +98,7 @@ struct AutoReg : NonCopyable {
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS

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