Compare commits

..

524 Commits

Author SHA1 Message Date
Martin Hořeňovský
9e1bdca466 v2.4.1 2018-09-28 15:52:51 +02:00
Martin Hořeňovský
be49a539e4 Fix a bug in UnorderedEqualsMatcher
Previously a mismatched prefix would be skipped before the actual
comparison would be performed. Obviously, it is supposed to be
_matching_ prefix that is skipped.
2018-09-28 15:30:02 +02:00
Martin Moene
558bbe7d24 Add example for TeamCity reporter and refer to it
Prevent warnings
- gnu: -Wcomment: multi-line comment
- clang: -Wweak-vtables 'class' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit
- clang: -Winconsistent-missing-override: 'method' overrides a member function but is not marked 'override'
- MSVC: C4702: unreachable code
2018-09-27 23:20:02 +02:00
wimo7083
f4881f172a prevent cygwin to_string compiler error 2018-09-27 20:56:27 +02:00
Mike Cowan
de06340e7d Abort when total assertions failed is greater than or equal to configured value 2018-09-22 22:39:08 +02:00
Martin Hořeňovský
4dd6e81d0f Update "Known limitations" section of documentation
This fixes some wording that implies C++98 standard, updates
the recommended solution to looped SECTION macros and mentioned
the "last section failed, test needs to be rerun" problem.

Related to #1367
Related to #1384
Related to #1389
2018-09-21 21:03:14 +02:00
Martin Hořeňovský
9e6d7bbf00 Add documentation for installing Catch from the repository
This might prove helpful when the package managers either doesn't
have Catch at all, or provides it in obsolete version (Ubuntu 16.04,
I am looking at you).

Closes #1383
2018-09-21 20:48:18 +02:00
Martin Hořeňovský
dfb025cf08 Change wording of Approx documentation to be less misleading
The "percentage" suggests that the expected epsilon can be in
[0, 100], but the expected values are in [0, 1]. The new wording
uses "coefficient", to make it clearer that we are talking about
values in [0, 1].

Closes #1388
2018-09-21 20:04:56 +02:00
melak47
c638c57209 Add StringMaker for std::variant, std::monostate (#1380)
The StringMaker is off by default and can be enabled by a new macro `CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER`, to avoid increasing the footprint of stringification machinery by default.
2018-09-20 14:13:35 +02:00
melak47
a575536abe Add StringMaker for std::(w)string_view
Fixes #1375
2018-09-10 11:37:26 +02:00
Martin Hořeňovský
1eb42eed97 Add C++17 builds to Travis 2018-09-10 09:30:09 +02:00
Martin Hořeňovský
46e99e258f Fixup TOC script sluggification and documentation 2018-09-09 17:09:57 +02:00
Martin Hořeňovský
a212fb440b Merge branch 'dev-appveyor-fixup-coverage-scripts' 2018-09-09 11:37:17 +02:00
Martin Hořeňovský
1e98c820bb Simplify the Appveyor configuration batch script 2018-09-09 10:18:30 +02:00
Martin Hořeňovský
bcfa9b1775 Properly exit appveyor batch scripts on error 2018-09-09 10:18:29 +02:00
Martin Hořeňovský
a3876adba6 Fix CTest regex error
The desired behaviour was to match a literal "[.]", so the regex
has to be escaped as "\\[\\.\\]" -- double backslashes, because
it has to be escaped from CMake as well as from the regex engine.
2018-09-09 10:17:08 +02:00
Martin Hořeňovský
2a4725b40e Enable some more generator tests in standard test run 2018-09-08 18:23:38 +02:00
Martin Moene
a81c01d4f9 Updated documentation TOCs 2018-09-08 11:05:52 +02:00
Martin Hořeňovský
60b05b2041 v2.4.0 2018-09-04 11:59:15 +02:00
Martin Hořeňovský
232ea3c456 Add documentation for no-exception support
Closes #703
Closes #1358
2018-09-04 10:06:31 +02:00
Martin Hořeňovský
a5c900d077 Add ExtraTest for CATCH_CONFIG_DISABLE 2018-09-04 10:06:30 +02:00
Martin Hořeňovský
8b01883854 Add support for -fno-exceptions (or equivalent)
This means

* Adding new configuration toggle `CATCH_CONFIG_DISABLE_EXCEPTIONS`
and a best-guess configuration auto-checking for it.
* Adding new set of internal macros, `CATCH_TRY`, `CATCH_CATCH_ALL`
and `CATCH_CATCH_ANON` that can be used in place of regular `try`,
`catch(...)` and `catch(T const&)` respectively, while disappearing
when `CATCH_CONFIG_DISABLE_EXCEPTIONS` is enabled.
* Replacing all uses of `throw` with calls to `Catch::throw_exception`
customization point.
* Providing a default implementation for the above customization point
when `CATCH_CONFIG_DISABLE_EXCEPTIONS` is set.
* Letting users override this implementation with their own.
* Some minor changes and ifdefs all around to support the above
2018-09-03 21:08:27 +02:00
Martin Hořeňovský
86da2846af Replace most naked throws with macros from catch_enforce.h
This is a first step towards support a no-exceptions mode
2018-09-03 18:07:34 +02:00
Martin Hořeňovský
ef9150fe6f Directly set Approx's members in operator()
This avoids instantiating the member-setting function template
and checking the invariants in cases where we know the invariant
already holds.
2018-09-03 10:20:58 +02:00
Martin Hořeňovský
84fa76e985 Move Approx's validity checks out of line into cpp file
This avoids having to include <stdexcept> in the main include path
and speeds up the compilation if Approx is used with multiple
different types.
2018-09-03 10:15:51 +02:00
Martin Hořeňovský
fcd91c7d6b Only look for Python binary when building tests
Fixes #1374
2018-09-02 18:55:17 +02:00
Martin Hořeňovský
efbf50fc7d Add test for AND_GIVEN and update the baselines 2018-09-02 16:53:57 +02:00
Matthew Parnell
64fd5b8058 Add BDD AND_GIVEN based macros
issue #1360

It is possible to have multple  given contexts in a single BDD scenario;
if you have to type 'and' in the GIVEN description; it's very likely you
need an AND.

A generic AND  is not possible, thus a AND_GIVEN  is added to complement
the AND_WHEN and AND_THEN.

Can be used without needing to increase indent:

	SCENARIO("...") {
		GIVEN("...")
		AND_GIVEN("...") {
			WHEN("...") {
				THEN("...") {
					// ...
				}
			}
		}
	}

would correctly output, when requested/needed:

    Given: ...
And given: ...
     When: ...
     Then: ...

The padding had to be increased by a character in the output message, to
continue to be uniform.
2018-09-02 16:53:57 +02:00
Martin Hořeňovský
ee73989f9b Suppress Wunreachable-code in floating matchers and exception tests
Closes #1350
2018-09-01 22:34:29 +02:00
Martin Hořeňovský
646e1f608d Make Catch2ConfigVersion.cmake be generated as arch-independent
As it turns out, there is a fairly reasonable workaround available.

Closes #1368
2018-09-01 21:51:49 +02:00
Martin Hořeňovský
6f75acbfb5 Add tests for CATCH_CONFIG_DISABLE 2018-09-01 17:28:06 +02:00
Martin Hořeňovský
9c3cc4a076 Add test for CATCH_CONFIG_PREFIX_ALL 2018-09-01 15:01:51 +02:00
Martin Hořeňovský
f3972f0695 Add test for CATCH_CONFIG_DISABLE_STRINGIFICATION 2018-08-31 21:27:35 +02:00
Martin Hořeňovský
38e1731f69 Build ExtraTests when building Examples on AppVeyor 2018-08-31 18:32:23 +02:00
Martin Hořeňovský
0947752a44 Avoid running C++17 tests as part of approvals on VS 2017 2018-08-31 18:25:42 +02:00
Martin Hořeňovský
0646e0283c Disable installation step when Catch is used as a subproject
This is because otherwise the installations paths provided via
GNUInstallDirs become messed up and parts of the installation
package will end up in the wrong place.

Also it doesn't make much sense to force dependees to also install
our header alongside them.

Closes #1373
2018-08-31 11:43:09 +02:00
Axel Huebl
90663b2e75 Tests: Spaces & TABs
Fix TABs and none-PEP8 spaces in approval test.
Does not yet fix overlong lines for full `flake8` compliance.
2018-08-29 18:28:27 +02:00
Axel Huebl
7667a7d89c Docs: TABs to Spaces
Replace TABs with four (4) spaces in code docs.
2018-08-29 18:05:22 +02:00
Axel Huebl
9773d89ab4 Code: TABs to Spaces
Replace TABs with four (4) spaces in source files.
2018-08-29 14:59:11 +02:00
George Fotopoulos
2067c8d3bd Update opensource-users.md
Add "thor"
Update "forest" description
2018-08-29 14:51:17 +02:00
Martin Hořeňovský
1742ab76a2 No longer allow failures for VS2017 on AppVeyor 2018-08-29 13:39:24 +02:00
Martin Hořeňovský
898d111f72 Fix generateSingleHeader.py to properly copy utf-8 2018-08-29 12:52:29 +02:00
Martin Hořeňovský
5202993555 Fix VS2017 approvals on AppVeyor
Because of a change in VS toolset, missing option <UseFullPaths>
is no longer interpreted as "don't pass /FC to the compiler", but
rather as "pass /FC to the compiler". This is problematic, because
/FC not only changes how much of the path is reporter by the compiler
(e.g. in `__FILE__` macro), but it also lower cases the path.

This lower-casing of the path broke our approval tests for VS2017
about 5 months ago.

Using CMake 3.13 (not yet released) would also let us fix it, but
for now we use a vcxproj.user file that is merged with the main project
and explicitly disables `/FC`.
2018-08-28 12:58:08 +02:00
Martin Hořeňovský
f061dabbad Add ExtraTests infrastructure
This means
* a new cmake option, `CATCH_BUILD_EXTRA_TESTS`, that conditionally
includes the ExtraTests subfolder
* building and running them on some of the Travis build images
* An example configuration test

In the future these should be extended to cover most of the
configuration options in Catch2, but this is a start.
2018-08-28 12:57:20 +02:00
Martin Hořeňovský
1a501fcb48 Fix examples compilation for some combinations of Clang and libstdc++ 2018-08-28 10:12:53 +02:00
Martin Hořeňovský
94121a5f6d Add a basic documentation for generators 2018-08-24 13:34:27 +02:00
Martin Hořeňovský
92e25049cf Move all<int> to .cpp file to remove <limits> from common path 2018-08-24 13:34:03 +02:00
Martin Hořeňovský
fdcd46420e Update baselines 2018-08-24 13:31:51 +02:00
Phil Nash
7c25dae9ea First attempt at data generator support
The support is to be considered experimental, that is, the interfaces,
the first party generators and helper functions can change or be removed
at any point in time.

Related to #850
2018-08-24 13:31:51 +02:00
David Seifert
7f18282d17 Allow overriding of Python interpreter
* Calling `python` does not allow overriding
  downstream when running tests.
2018-08-20 14:52:54 +02:00
Phil Nash
1cdaa48a0b CAPTURE is now variadic 2018-08-19 22:40:20 +02:00
Phil Nash
1a63fad8d6 Seed the RNG in approval tests 2018-08-19 22:34:14 +02:00
Phil Nash
d6f2fd486c Moved ReusableStringStream impl to generic singleton 2018-08-19 11:28:46 +02:00
Phil Nash
5884ec1e28 Moved registry hub to generic singleton 2018-08-19 11:13:19 +02:00
Phil Nash
eb783fc20e Added generic singletons facility
<sigh> yes, I know - but we have them - may as well make them consistent and safer
2018-08-19 10:34:44 +02:00
Igor Murashkin
38248f3f2c Add pragma ignore for -Wnon-virtual-dtor in Catch matchers 2018-08-17 17:14:56 +02:00
Martin Hořeňovský
c9de7dd12d Optimize SourceLineInfo::operator< with short-circuiting
In case of 2 instances of SourceLineInfo constructed in the same
file, they will have the same `file` pointer (even at O0). Thus, we
can check if they are equal before calling potentially pointless
`strcmp`.
2018-07-23 20:46:42 +02:00
Martin Hořeňovský
52cbb507ab Avoid copying StringRef
In theory the copy is cheap (couple of pointers change), but tests
are usually compiled in Debug mode/with minimal optimizations, which
means that most users will still have to pay the cost for those
function calls.
2018-07-23 14:04:43 +02:00
Martin Hořeňovský
83bfae1a50 Construct StringRef from constant strings in macros directly using UDL
This avoids having to call `strlen` to get the constant string's length
and thus should improve performance.
2018-07-23 14:00:45 +02:00
Martin Hořeňovský
f7f592dfc9 Introduce "C-namespaced" UDL for StringRef 2018-07-23 14:00:45 +02:00
Martin Hořeňovský
78804ea304 Replace std::string with StringRef in MessageInfo for macro capture
Because the macro name is compile-time constant, we do not have to
worry about lifetimes and will avoid allocation in case of missing
SSO or long macro name.
2018-07-23 14:00:44 +02:00
Martin Hořeňovský
b93284716e Update gitattributes 2018-07-23 10:15:52 +02:00
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
Martin Hořeňovský
cd76f5730c v2.1.0 2018-01-10 13:53:04 +01:00
Martin Hořeňovský
f5910f38ef Copy reporters to single_include during releases 2018-01-10 13:44:08 +01:00
Phil Nash
421ab16062 Exclude string-literal arrays from automatic range serialisation
These have specialised serialisers already anyway, and were causing ambiguities in VS 2015 & 2017
2018-01-08 15:15:44 +00:00
Phil Nash
161dd4ed24 Merge commit '2c43620d9baed1fdcaa9146af1d3eb90520cbe92' 2018-01-08 11:13:29 +00:00
Aivars Kalvans
13ea4225e7 Add fuxedo.io to open source users 2018-01-06 14:02:01 +01:00
Phil Nash
2c43620d9b Exclude benchmark dir 2018-01-05 14:39:59 +00:00
Phil Nash
8be1df243e Added test for stringifying std::arrays 2018-01-04 10:52:55 +00:00
Phil Nash
32eb90b9bd Fix stringifying of unknown enums 2018-01-04 10:21:52 +00:00
Phil Nash
702cfdaf6e Added special handling for vector<bool> when stringifying 2018-01-04 10:05:02 +00:00
Phil Nash
e41e8e8384 Added tests for stringifying map and set 2018-01-04 10:03:08 +00:00
Phil Nash
af3f2499bc Added generic container detection in StringMaker.
Removed vector specialisation as this is now covered generically - as are any containers that can be called via (freestanding) begin/ end
2018-01-04 09:30:06 +00:00
philsquared
c3a1143d23 Cleanly override warning level for SelfTest in MSVC
Eliminates warning about warning level override (by removing the default /W3)
2018-01-02 10:18:35 +00:00
Martin Hořeňovský
f580591bf8 Test different way of excluding system headers 2017-12-25 19:38:51 +01:00
Phil Nash
fc88313d45 Added DtCraft to Open Source users 2017-12-12 17:22:40 +00:00
Martin Hořeňovský
3979845d5f Add coverage badge 2017-12-11 13:06:27 +01:00
Dan Nissenbaum
88d2bac624 Trivial typo fix. (#1119) 2017-12-09 21:29:39 +01:00
Pfiffikus
ed33e9787e Update MessageTests.cpp
typo corrected
2017-12-09 20:51:56 +01:00
Martin Hořeňovský
f466d9a1ed Fix a7a9ee5 2017-12-09 20:49:06 +01:00
Martin Hořeňovský
a7a9ee5552 Manual cherry-pick from #1111
This hsould merge still-valid piece of #1111 into master.
2017-12-09 20:17:47 +01:00
Martin Hořeňovský
0cf05d54a6 Force Travis badge to use status of master branch 2017-12-08 21:47:42 +01:00
Martin Hořeňovský
11887fbbab Point AppVeyor status badge at status for this repo
Previously it pointed to AppVeyor's test repo status
2017-12-08 21:36:43 +01:00
Phil Nash
347be87126 Removed debug code accidentally left in previous commit 2017-12-08 16:30:16 +00:00
Phil Nash
4da655c1b0 Increased int size for timers to avoid truncations 2017-12-08 15:59:00 +00:00
Martin Hořeňovský
c4d1aa9033 Fix std::uncaught_exception deprecation warning in ~ScopedMessage
Closes #1124
2017-12-07 19:10:28 +01:00
Martin Hořeňovský
495d2458e0 Add UnorderedEqualsMatcher for vectors
Closes #1093
2017-12-07 19:05:00 +01:00
Phil Nash
3035120dc7 Some bits of tidy up 2017-12-07 00:02:32 +00:00
Martin Hořeňovský
584e04d480 Add compact reporter baseline 2017-12-06 21:47:14 +01:00
Martin Hořeňovský
673dcc16a9 Make approval tests also check compact reporter 2017-12-06 15:48:46 +01:00
Martin Hořeňovský
0c122c135d Add constructor arg checking to WithinAbsMatcher
Also tests :-)
2017-12-06 15:42:03 +01:00
Phil Nash
d19b7292b3 xml reporter reports WARN message when not used with -s 2017-12-06 14:30:17 +00:00
Phil Nash
5e063616df Moved runner helpers into Catch namespace
not sure they weren't there to start with
2017-12-05 23:26:21 +00:00
Phil Nash
aa9d635014 Refactored StreamRedirect classes 2017-12-05 23:19:28 +00:00
Phil Nash
7c5a21fb7d Added clog test 2017-12-05 17:48:15 +00:00
Phil Nash
533cdc6bc1 Revirtualised IResultCapture methods
Didn't really impact runtime anyway, but will need to use interface for threading support.
2017-12-05 16:23:10 +00:00
Martin Hořeňovský
51e281a684 Simplify code coverage CMake toggle 2017-12-03 14:53:23 +01:00
Martin Hořeňovský
24851dff99 Add release notes from the EOL of Catch Classic 2017-12-03 14:19:02 +01:00
Martin Hořeňovský
a4fd96fbaa Remove debug prints from batch scripts 2017-12-03 14:14:58 +01:00
Martin Hořeňovský
12c57cedda No longer rename AppVeyor builds 2017-12-03 13:06:21 +01:00
Martin Hořeňovský
45a465713e Add codecov.io coverage collection from AppVeyor
Also had to add new project to redirect CTest output, add
separate batch scripts for AppVeyor because it doesn't handle
multi-line batch scripts in yaml properly, and other helper
scripts.
2017-12-03 13:03:52 +01:00
Phil Nash
dfa817ae73 Just track whether last assertion passed directly, rather than deduce it from counts 2017-12-02 18:44:23 +00:00
Phil Nash
57c346a46d Removed assertionRun() and rolled its logic into assertionPassed() and assertionEnded() 2017-12-02 18:44:23 +00:00
Martin Hořeňovský
67f734c799 Remove system headers when preprocessing coverage report 2017-12-02 14:17:42 +01:00
Phil Nash
b76e80ed3d Small clean-ups 2017-11-30 17:54:44 +03:00
Martin Hořeňovský
a3632facf3 Fix teamcity reporter compilation with single header 2017-11-30 13:48:24 +01:00
Phil Nash
7d0db6b8e9 Moved -Wparentheses suppression before the push for GCC
Because of bugs in GCC 4 & 5 that prevent _Pragma from working :-(
2017-11-29 20:19:50 +03:00
Phil Nash
8a7493cd88 Globally suppress Wunused-variable again, for now 2017-11-29 20:01:00 +03:00
Phil Nash
b5a5d9a6f8 Stop leaking some warning suppressions to user code 2017-11-29 19:14:33 +03:00
Martin Hořeňovský
8c32d0b644 Add more weird chrono::duration stringification tests 2017-11-28 21:47:06 +01:00
Martin Hořeňovský
28d1955ea8 Also test Approx template constructor 2017-11-28 21:29:34 +01:00
Martin Hořeňovský
20211a33e6 Stop using brew if not needed -- fix build on XCode9 image 2017-11-27 22:34:44 +01:00
Phil Nash
e3941a9ad2 De-virtualised isBinaryExpression() and getResult() on ITransientExpression 2017-11-27 22:49:26 +03:00
Phil Nash
da86ddc620 Fixed accidental const & formating 2017-11-27 22:28:45 +03:00
Phil Nash
4b614ee1d1 Moved all AssertionHandler logic into RunContext and de-virtualised interface
This makes the assertion handling much less "chatty". AssertionHandler is now just a thin shim over RunContext
2017-11-27 22:23:15 +03:00
Phil Nash
5461242ffe Renamed last usge specific handle method (and made the low level ones private) 2017-11-27 22:23:15 +03:00
Martin Hořeňovský
e344984a1b Add codecov.io coverage tracking
* Every Linux build tracks coverage when running Debug mode
* OS X not supported yet (Future WIP)
* Our own unit tests, non-default reporters and Clara are ignored
2017-11-27 20:13:47 +01:00
Phil Nash
db44964e27 Refactored most handle() calls to more specific/ descriptive calls 2017-11-26 21:28:43 +00:00
Phil Nash
2800adba25 Qualified handleExceptionMatchExpr in Catch::
(was picking it up by ADL before - no need to rely on that!)
2017-11-26 21:28:43 +00:00
Martin Hořeňovský
ae1547e202 Add extra tests to ctest 2017-11-26 21:33:09 +01:00
Martin Hořeňovský
73a1623eaf Re-enable 2 string tests 2017-11-25 18:38:18 +01:00
Phil Nash
c411c131cb Move crtdbg.h include outside namespace 2017-11-24 10:36:54 +00:00
Phil Nash
091595780e Clean-up re-usable string streams 2017-11-24 08:46:17 +00:00
Phil Nash
f417995afc Cache IResultCapture in AssertionHandler to avoid repeated lookups 2017-11-23 19:21:09 +00:00
Phil Nash
9329d97a43 Always debug-break non-inline 2017-11-23 19:14:26 +00:00
Phil Nash
8141a7836f Inline shouldDebugBreak() 2017-11-23 16:58:43 +00:00
Phil Nash
5323202652 Bake exception guard into assertion handler flow 2017-11-23 16:52:46 +00:00
Martin Hořeňovský
f052762c11 Reduce amount of CI output on success 2017-11-22 18:29:58 +01:00
Martin Hořeňovský
401ad7a189 Remove isTrue, alwaysTrue, alwaysFalse
isTrue and alwaysFalse were replaced by (void)0, 0 inspired by doctest
alwaysTrue was replaced by warning suppression
2017-11-22 16:03:45 +01:00
Martin Hořeňovský
63c097a077 Remove superfluous TravisCI build entry 2017-11-21 18:56:29 +01:00
Martin Hořeňovský
87c125ecb8 Enable Werror for dev builds 2017-11-21 18:55:28 +01:00
Phil Nash
3b965aa501 (re)Inlined isTrue() 2017-11-21 13:12:22 +00:00
Phil Nash
e54dcdac8b Added space in StringRef literal operator 2017-11-21 12:09:04 +00:00
Phil Nash
e4a898eaaa Removed templated StringRef ctor and added StringRef literal 2017-11-21 11:08:39 +00:00
Phil Nash
c39109dce3 Ignore all cmake-build-* folders 2017-11-21 11:08:39 +00:00
Martin Hořeňovský
a8a1c379c0 Introduce a way to intentionally expose interface for use in tests
Fixes #1076
2017-11-21 11:10:07 +01:00
Phil Nash
e08a4ed99e Added missing <cstring> include to stringref.cpp 2017-11-21 09:26:56 +00:00
Phil Nash
fcba30569c Refactored to resetAssertionInfo() 2017-11-20 16:33:06 +00:00
Phil Nash
4353614df7 Added StringRef constructor that captures string literal size at compile time 2017-11-20 16:33:05 +00:00
Martin Hořeňovský
f36817ef83 Check single-header using test examples
This means that examples build for all matrix entries
2017-11-19 22:03:24 +01:00
Martin Hořeňovský
812bf21740 Move imports close to point of usage in Python scripts
This means that you no longer need urllib2 to regenerate
single header file, etc
2017-11-19 22:02:22 +01:00
Martin Hořeňovský
baf3d2f360 Split out ratio_string::symbol bodies 2017-11-19 14:54:52 +01:00
Martin Hořeňovský
b083b04126 Fix compilation when using g++ with libc++
Fixes #1110
2017-11-19 14:47:18 +01:00
Phil Nash
505d2f8977 Merge pull request #1107 from coombez/contrib
performance improvements
2017-11-17 23:32:04 +00:00
Neal Coombes
f18366150e performance improvement - getCurrentContext
inlined getCurrentContext and getMutableContext
Further work on #1086.
Brings test from 0m37.913 to 0m25.584s
Catch2 is now faster than Catch 1.x!!
2017-11-17 14:55:30 -06:00
Neal Coombes
fe725648a7 performance improvement - StringRef::operator=
inlined and reduced data copy in half.
Further work on #1086.
Brings test from 0m44.942s to 0m37.913.
2017-11-17 14:15:26 -06:00
Phil Nash
b0c379f621 Inlined StringRef ctors/ dtor and size() and empty() 2017-11-17 18:38:54 +00:00
Phil Nash
c443afcca0 Merge pull request #1104 from coombez/contrib
Performance improvement
2017-11-17 18:38:30 +00:00
Phil Nash
502da4b38d Added files for multiply inclusions of test cases 2017-11-17 15:46:57 +00:00
Phil Nash
8da845810d Rebased due to whitespace changes 2017-11-17 15:46:57 +00:00
Phil Nash
61e838edf2 Reorganised (some) usage tests so they can be included multiple times 2017-11-17 15:46:57 +00:00
lbersch
516dbc83bc Add inja to open source users (#1106)
* Add Inja to open-source users
* Capitalize first letter in user description
* Fix url
2017-11-17 11:49:39 +01:00
Neal Coombes
b9339333df Performance improvement
Begin to address #1086
Brings test from 2m51.072s to 1m15.661s
2017-11-15 14:43:43 -06:00
Neal Coombes
61e29b5630 Fix AssertionPrinter name conflict in console and compact reporters 2017-11-15 21:26:31 +01:00
Martin Hořeňovský
54fb6f2d23 Provide WandBox link for online testing
It used to be provided for Catch Classic, it was lost during
transition of Catch2 to master.

Closes #1101
2017-11-15 20:23:05 +01:00
Martin Hořeňovský
a077ebae4c Use svg build status icon for AppVeyor
Closes #1100
2017-11-15 18:54:04 +01:00
Martin Moene
2bbba4f544 Refer to example code from the Tutorial 2017-11-15 15:37:39 +01:00
Martin Moene
29cdd6c526 Add link to event listener example to documentation 2017-11-15 15:37:39 +01:00
Martin Moene
dfb7217613 Add list of examples to documentation 2017-11-15 15:37:39 +01:00
Martin Moene
f6ae45122b Add matrix element for examples to AppVeyor 2017-11-15 15:37:39 +01:00
Martin Moene
d5d2bee4c5 Add matrix element for examples to Travis configuration 2017-11-15 15:37:39 +01:00
Martin Moene
85de0727d4 Add examples subdirectory to CMake build; included if BUILD_EXAMPLES is true 2017-11-15 15:37:39 +01:00
Martin Moene
4ecb2e112e Add examples folder with initial examples 2017-11-15 15:37:39 +01:00
Martin Hořeňovský
97a8640cbf Update 3rd party bugs documentation
Removes bugs from no longer supported compilers
Adds a confirmed 3rd party bug in VS 2015

Closes #881
2017-11-14 22:05:30 +01:00
Martin Hořeňovský
033e078320 Fix typo in build system docs 2017-11-14 21:42:28 +01:00
Martin Hořeňovský
9796a77a37 Initial prototype of PCH support
Related to #1061
2017-11-14 21:41:36 +01:00
Martin Hořeňovský
98d4c49d1c Provide ConsoleReporter declaration with EXTERNAL_INTERFACES
Related to #991
2017-11-14 20:42:58 +01:00
Martin Hořeňovský
a096e4b3f2 Provide XmlReporter declaration with EXTERNAL_INTERFACES
Related to #991
2017-11-14 17:56:27 +01:00
Martin Hořeňovský
4b3730de8a Provide JunitReporter declaration with EXTERNAL_INTERFACES
Related to #991
2017-11-14 17:15:13 +01:00
Martin Hořeňovský
6acdacfde0 Provide CompactReporter declaration with EXTERNAL_INTERFACES
Related to #991
2017-11-14 16:13:35 +01:00
Martin Hořeňovský
a3cba7a0d5 Conditionally compile problematic tests under old libstdc++ 2017-11-13 21:23:52 +01:00
Martin Hořeňovský
9796846ad0 Workaround libstdc++-4.8 regex issue in approval tests 2017-11-13 18:19:40 +01:00
Phil Nash
74d3dfd4cc All tests files have .tests.cpp suffix. Also moved tests out of TestMain.cpp and moved up a level 2017-11-13 16:03:27 +00:00
Phil Nash
e34754e433 Split SelfTest test files into Usage and Introspective varieties
Usage: just exercises Catch. The tests are over arbitrary date/ types
Introspective: Tests parts of Catch itself.
2017-11-13 15:38:52 +00:00
Martin Hořeňovský
55b71bebf1 Add tests for case insensitive string matching 2017-11-13 15:46:33 +01:00
Martin Hořeňovský
b0857e846f Provide a regex matcher against std::string
Related to #1040
2017-11-13 15:35:31 +01:00
Martin Hořeňovský
a06b6dc3ea Remove pointless StringRef -> std::string conversions 2017-11-13 13:08:59 +01:00
Martin Hořeňovský
0adb04807a Change how non-nullness is enforce in StringRef constructor 2017-11-13 13:04:45 +01:00
Martin Hořeňovský
f80f28e09a Fix pointless type mismatch between StringRef and std::string 2017-11-13 12:49:13 +01:00
Martin Hořeňovský
484eee973c Move StringRef's impl details to anonymous namespace 2017-11-13 12:41:04 +01:00
Martin Hořeňovský
d09fe4459d Stop recounting constant string's length on each passed assertion 2017-11-13 12:27:02 +01:00
Martin Hořeňovský
e484236825 Don't invoke UB when nullptr is passed to StringRef constructor 2017-11-13 12:09:19 +01:00
Martin Hořeňovský
e7c23b73da Don't call strlen in StringRef when the length was already passed 2017-11-13 12:03:45 +01:00
Phil Nash
3537b7858f Removed vestigal ComparatorT template arg to MatcherBase 2017-11-13 10:08:48 +00:00
Martin Hořeňovský
b74d4ca96d Add compilation test for #1027 2017-11-13 10:07:06 +01:00
Martin Hořeňovský
8dbaac61ff Final set of fixes for floating matchers approvals 2017-11-12 11:49:36 +01:00
Martin Hořeňovský
a0dbc62955 Fix OS X compilation error 2017-11-10 19:56:39 +01:00
Martin Hořeňovský
cecee3459a Add another MSVC NAN macro 2017-11-10 19:52:43 +01:00
Martin Hořeňovský
030321e3e0 Add NAN test for Approx 2017-11-10 18:48:45 +01:00
Martin Hořeňovský
5f961af70e Remove leftover commented out lines 2017-11-10 18:37:58 +01:00
Martin Hořeňovský
0b1f1b1003 Add ULP and margin matcher
Closes #1074
2017-11-10 18:33:00 +01:00
Phil Nash
24e6d5fa33 Fixed release notes mention of *_THROWS_MATCHES
As reported in #1088
2017-11-09 11:09:17 +01:00
Martin Hořeňovský
13370bddf2 Revert "Move <ctime> include out of line"
This reverts commit 36f02d76d6.
2017-11-08 08:31:48 +01:00
Martin Hořeňovský
36f02d76d6 Move <ctime> include out of line 2017-11-07 21:59:52 +01:00
Phil Nash
07ac9b92e4 Updated badges (again) for Catch2 2017-11-07 18:50:55 +00:00
Phil Nash
0d3fc59f6d Added missing <memory> include 2017-11-07 18:48:57 +00:00
Phil Nash
56e1075613 Introduced ReusableStringStream and removed all uses of std::ostringstream from the main path
ReusableStringStream holds a std::ostringstream internally, but only exposes the ostream interface.
It caches a pool of ostringstreams in a vector which is currently global, but will be made thread-local.

Altogether this should enable both runtime and compile-time benefits. although more work is needed to realise the compile time opportunities.
2017-11-07 18:01:10 +00:00
Phil Nash
868e125d49 Moved a lot of stream related stuff out of the public headers and replaced more ostream dependencies with iosfwd 2017-11-07 15:55:09 +00:00
Phil Nash
c9cdb9a48f Tweaked logo 2017-11-07 11:41:49 +00:00
Phil Nash
5fd1d7174c Added link to Catch2 blog post 2017-11-07 11:27:01 +00:00
Phil Nash
3a4c765030 Refreshed artwork for Catch2 2017-11-07 11:25:13 +00:00
Martin Hořeňovský
a20b286999 Improve travis.yml
- Added new compilers and OS X images
- Option to run SelfTest under Valgrind
- Merge "Debug" and "Release" configurations into one run
-- This saves apt setup and cmake download step per compiler, 60-90s
- Fix C++14 compilation under Clang 3.8 and up
2017-11-07 11:24:18 +01:00
Daniel Doubleday
e28763ad05 Fix platform detection for iOS 2017-11-06 10:08:22 +01:00
Martin Hořeňovský
b2dd48f0c0 Cleanup travis.yml: remove duplicate compilers, remove unused flag 2017-11-05 15:58:12 +01:00
Martin Hořeňovský
7a562d39b2 Cleanup CMakelists.txt 2017-11-05 14:15:03 +01:00
Martin Moene
fa9c4207f1 Replace include_directories() with target_include_directories()
to prevent inheritance of include directories that possibly lead to a clash.

A clash occurs when a folder is included, e.g. examples, that wants to use the single-include directory instead of the normal include directory as used by the SelfTest in the next higher level.
2017-11-04 22:08:56 +01:00
Martin Hořeňovský
4f9123dc20 Remove self-include in header 2017-11-03 22:34:49 +01:00
Phil Nash
19ab2117c5 Remove spurious test following merge 2017-11-03 18:09:55 +00:00
Phil Nash
4acf112c19 Removed zombie files
These files were removed from the Catch2 branch, and crept back in when Catch2 merged with master
2017-11-03 16:56:11 +00:00
Phil Nash
53f6d3fc8e Locked release notes reference to v2.0.1 release 2017-11-03 13:31:59 +00:00
Phil Nash
cf76a795cc Added note about Catch2 to readme 2017-11-03 13:18:26 +00:00
Phil Nash
811f4d13d7 Updated links in readme 2017-11-03 13:15:22 +00:00
Phil Nash
7423a481eb Updated some Catch references to Catch2 2017-11-03 13:05:09 +00:00
Phil Nash
46c7c9d3a0 Merge branch 'catch2' 2017-11-03 12:05:38 +00:00
Phil Nash
b119ebdde1 v2.0.1 release 2017-11-03 12:01:52 +00:00
Phil Nash
1c43fb64c1 Added docs for extending command line with Clara 2017-11-02 18:01:24 +00:00
Phil Nash
8b40c26434 Removed handling of start-up exceptions from custom main docs 2017-11-02 18:01:24 +00:00
Phil Nash
fe05062f9e Print any start-up exceptions in Session's constructor, so custom main's don't need to worry about them 2017-11-02 17:58:07 +00:00
Martin Hořeňovský
31cc62e6b7 Updated release notes with Approx changes 2017-11-01 22:25:17 +01:00
Martin Hořeňovský
a49e6fdc27 Update Approx documentation 2017-11-01 13:45:21 +01:00
Pfiffikus
2d91035404 Update assertions.md
scale more detailed explained; have to be adapted to PR #1068 if necessary
2017-11-01 13:32:08 +01:00
Martin Hořeňovský
accf9859b4 Add OSX specific INFINITE macro parsing in approval tests 2017-11-01 08:46:49 +01:00
Martin Hořeňovský
22ac9d2184 Approx cleanup: More tests, INFINITY handling, etc 2017-11-01 07:30:11 +01:00
Pfiffikus
00af677577 Approx rework: default scale == 0, epsilon applies to Approx::value
Also adds check to Approx::epsilon that the new epsilon has a valid
(ie one between 0 and 1)

Based on
http://realtimecollisiondetection.net/blog/?p=89
https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
https://en.wikipedia.org/wiki/Approximation_error#Formal_Definition

The given epsilon should refer to the target value, otherwise
the result would be unexpected, e.g. 101.02 == Approx(100).epsilon(0.01)
is true.
The default scale should be invisible, thus,
e.g. 101.01 == Approx(100).epsilon(0.01) gets false.
Finally even 101.000001 == Approx(100).epsilon(0.01) is false
2017-10-31 15:43:42 +01:00
Martin Hořeňovský
ae21020640 dev build 6 2017-10-31 15:17:21 +01:00
Martin Hořeňovský
11f716f28d Make Approx::margin inclusive
Fixes #952, related to #980
2017-10-31 14:49:00 +01:00
Pfiffikus
c3ddd4a7e2 Update test-cases-and-sections.md
some clarification and typo correction
2017-10-31 14:28:30 +01:00
Clare Macrae
c43ce85416 Fix very minor typo
it's -> its
2017-10-31 14:28:20 +01:00
Pfiffikus
4220f2eef2 Update build-systems.md
typo correction
2017-10-31 14:28:10 +01:00
Sebastian Grottel
c1a91caf00 adds flushes to the output stream of teamcity reporter, making the test output more responsive. 2017-10-31 14:27:47 +01:00
Sebastian Grottel
96c5de678d RandomNumberGenerator::result_type should be unsigned (#1050)
`result_type` must be unsigned:
http://en.cppreference.com/w/cpp/concept/UniformRandomBitGenerator

Using a signed type causes an infinite loop working with MS Visual Studio 2017, targetting: v140, WindowsTargetPlatformVersion 10.0.15063.0, Debug, x64
2017-10-31 14:26:36 +01:00
dvirtz
e68485e196 added PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS option 2017-10-31 14:21:20 +01:00
Martin Hořeňovský
88e912b4d1 Fix documentation crosslink in configuration.md 2017-10-31 14:19:53 +01:00
Dmitry Kozhevnikov
44244713f1 Update handling of __JETBRAINS_IDE__ macro
1. Use it to conditionally define CATCH_INTERNAL_CONFIG_COUNTER, not
   CATCH_CONFIG_COUNTER, as __JETBRAINS_IDE__ is similar to
   compiler-provided macros, not to user-provided ones.

2. Since __COUNTER__ will work starting with CLion 2017.3, use it
   when possible (and hopefully remove this check altogether
   at some point).
2017-10-31 14:15:54 +01:00
solvingj
eea9e1efd7 Minor - added header-only flag in conan
See header-only guidelines: 
http://conanio.readthedocs.io/en/latest/howtos/header_only.html?highlight=header%20only
Its borderline cosmetic, but it does have a purpose.
2017-10-31 14:09:44 +01:00
Martin Hořeňovský
2a3606f8e3 v1.11.0 2017-10-31 13:55:48 +01:00
Martin Hořeňovský
a6cf19abff Make Approx::margin inclusive
Fixes #952, related to #980
2017-10-30 21:33:29 +01:00
Martin Hořeňovský
601b2888ec Remove superfluous define from cmake project 2017-10-30 12:27:14 +01:00
Martin Hořeňovský
3049445d78 Remove benchmark binary from main cmake list
We can give it a separate CMakeLists.txt later, but there is no
point in building it every time.
2017-10-30 12:25:57 +01:00
Martin Hořeňovský
c672512979 Fix C4601 and enable C4602 warning for internal builds
Related to #1072
2017-10-30 12:14:20 +01:00
Martin Hořeňovský
57b4e0b64c Fix missing pragma warning(pop) and other warnings under MSVC
Fixes #1072
2017-10-30 09:58:13 +01:00
Pfiffikus
06586b7180 Update test-cases-and-sections.md
some clarification and typo correction
2017-10-26 13:57:18 +02:00
Clare Macrae
93b3d2cb8f Fix very minor typo
it's -> its
2017-10-24 20:00:27 +02:00
Pfiffikus
a90473df28 Update build-systems.md
typo correction
2017-10-24 19:59:59 +02:00
Phil Nash
75a77b6f8c embedded v1.0-develop.2 of Clara, which addresses / prefixed options, which should impact non-windows platforms
See #1054
2017-10-21 09:16:38 +02:00
Martin Hořeňovský
5af918eefd Fix-up pkg-config provided include path
Related to #1032
2017-10-17 17:04:37 +02:00
Sebastian Grottel
c9d9699ca8 adds flushes to the output stream of teamcity reporter, making the test output more responsive. 2017-10-17 16:42:05 +02:00
Sebastian Grottel
296955c437 RandomNumberGenerator::result_type should be unsigned (#1050)
`result_type` must be unsigned:
http://en.cppreference.com/w/cpp/concept/UniformRandomBitGenerator

Using a signed type causes an infinite loop working with MS Visual Studio 2017, targetting: v140, WindowsTargetPlatformVersion 10.0.15063.0, Debug, x64
2017-10-15 18:30:40 +02:00
dvirtz
664cbf702c added PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS option 2017-10-15 17:58:39 +02:00
Martin Hořeňovský
fb6700df54 Fix documentation crosslink in configuration.md 2017-10-14 08:36:44 +02:00
Phil Nash
05b1ca2884 Fixed expansion of _FALSE binary expression
- see #1051
2017-10-13 19:45:19 +01:00
Phil Nash
da6c2a6914 Fixed expansion of _FALSE binary expression
- see #1051
2017-10-13 19:44:20 +01:00
Phil Nash
c2b7bd15c0 Changed rhs expression capture from universal ref to const ref.
- addresses #1027
2017-10-13 14:16:14 +01:00
Phil Nash
ba6845a865 Version of Clara with (std::max) 2017-10-13 13:46:39 +01:00
Phil Nash
2eb93f47f7 enclosed more min/ max in parentheses to default MFC macros 2017-10-13 13:46:39 +01:00
Martin Hořeňovský
276393e4e5 Change ToC script to use <br> instead of trailing spaces
Also updated docs that contain ToC. Fixes #1048
2017-10-13 11:17:38 +02:00
Martin Hořeňovský
c7d9f02d5b Add pkg-config support
Closes #1032
2017-10-12 21:56:22 +02:00
Phil Nash
355ab78f4a dev build 5 2017-10-12 13:06:41 +01:00
Phil Nash
927f520a97 Moved windows proxy inclusion outside of CATCH_CONFIG_COLOUR_WINDOWS guard, so workaround early inclusion can be removed 2017-10-12 10:37:23 +01:00
philsquared
cc0b093c20 unconditional windows proxy 2017-10-11 14:58:20 +01:00
Martin Hořeňovský
17cdf20968 Mark part of std::chrono stringification tests nonportable 2017-10-09 14:56:23 +02:00
Martin Hořeňovský
4899d891d3 Fix MSVC compilation when stringifying std::chrono::time_point 2017-10-09 13:13:30 +02:00
Martin Hořeňovský
760a25e813 Fix baseline for file where std::pair stringification is not enabled 2017-10-09 13:12:50 +02:00
Martin Hořeňovský
79b405fd3f Add stringification for std::chrono::{duration,time_point}
Also hides std::chrono, std::pair and std::chrono::* behind
new configuration macros, CATCH_CONFIG_ENABLE_*_STRINGMAKER
to avoid dragging in <utility>, <tuple> and <chrono> in common
path, unless requested.
2017-10-09 13:03:29 +02:00
Martin Hořeňovský
f972732737 Workaround for stitching issue in #1020
Closes #1020
2017-10-03 18:41:49 +02:00
Martin Moene
61280e6d0a Rename to updateDocumentToC.py and adapt for use with Catch
adding missing GPL 3.0 license (thanks for noting @horenmar).
2017-10-03 15:43:18 +02:00
Martin Moene
7e9b53e40c Add original markdown_toclify.py by Sebastian Raschk (@rasbt)
- https://github.com/rasbt/markdown-toclify
2017-10-03 15:43:18 +02:00
Martin Hořeňovský
b80c5134f0 Updated release notes 2017-10-01 17:03:06 +02:00
Martin Hořeňovský
70e0d48978 Replace throw; with std::rethrow_exception(std::current_exception());
This works around a bug in libcxxrt handling of active exception count
that caused std::uncaught_exception() to return true even if there was
none.

Closes #1028
2017-09-28 12:53:09 +02:00
offa
11918b76d0 Direct link to the single header file updated to latest release (dev.4). 2017-09-27 18:20:34 +02:00
Phil Nash
5fe19f73e7 Scoped parseInfos population so i can be reused 2017-09-26 16:06:48 -07:00
Phil Nash
c1416d55cb Backed out dynamic stack array (use fixed size for now) 2017-09-26 15:55:34 -07:00
Phil Nash
2a1f8ae684 New version of Clara 2017-09-26 14:13:08 -07:00
Phil Nash
9541e89e6a Changed embed script to just do direct regex substitution 2017-09-26 14:13:08 -07:00
Martin Hořeňovský
80bbce8424 Reorganize release notes 2017-09-26 13:38:09 +02:00
Phil Nash
3d49d83128 Added benchmark support to MultiReporters
- otherwise benchmarks are not reported if multiple reporters (usually reporter + listener(s)) are used
2017-09-21 09:32:46 +01:00
Phil Nash
bd46f66754 dev build 4 2017-09-19 17:42:20 +01:00
Phil Nash
e9f0773f37 Updated release notes 2017-09-19 17:36:20 +01:00
Phil Nash
54f1ce2af2 Don't use console colour if running in XCode 2017-09-19 15:25:33 +01:00
Phil Nash
0a146e3af7 OCTest project now #includes all cpp files, so they all get __OBJC__ defined 2017-09-19 14:59:12 +01:00
Phil Nash
b9ff7ec301 Fixed issues for ObjC use (see #1011) 2017-09-19 14:38:18 +01:00
Phil Nash
a63b4a75bd Updated OCTest project 2017-09-19 14:37:35 +01:00
Phil Nash
8da0d0473b qualified a load of size_ts with std:: namespace (all those not from Clara) 2017-09-18 17:13:17 +01:00
Martin Hořeňovský
40209d1ae0 Use StringRef on fatal error path
So far the fatal error path only uses string literals, so this removes
an allocation from that context
2017-09-14 20:05:25 +02:00
Martin Hořeňovský
4e85267203 Add fatalErrorEncountered method to Reporter/Listener interface
An empty default implementation is provided to keep backward compatibility.
Called when signal or Structured Exception is encountered.

Related to #1005
2017-09-14 19:57:59 +02:00
Martin Hořeňovský
eaf850cd0c Do not use SEH and console api under UWP
Fixes #1020
2017-09-11 21:09:35 +02:00
Dmitry Kozhevnikov
9c07718b5f Update handling of __JETBRAINS_IDE__ macro
1. Use it to conditionally define CATCH_INTERNAL_CONFIG_COUNTER, not
   CATCH_CONFIG_COUNTER, as __JETBRAINS_IDE__ is similar to
   compiler-provided macros, not to user-provided ones.

2. Since __COUNTER__ will work starting with CLion 2017.3, use it
   when possible (and hopefully remove this check altogether
   at some point).
2017-09-07 18:00:04 +02:00
Martin Hořeňovský
9aa96712ae Sweep out some extra warnings
Swept:
`-Wpadded` in some places (where it caused extra size, instead of just
saying "hey, we padded struct at the end to align, just as standard says")
`-Wweak-vtables` everywhere (Clang)
`-Wexit-time-destructors` everywhere (Clang)
`-Wmissing-noreturn` everywhere (Clang)

The last three are enabled for Clang compilation going forward.

Also enabled `-Wunreachable-code` for Clang and GCC
2017-09-07 17:25:15 +02:00
Phil Nash
6105282c4f Removed function pointer comparison test from approvals as it has different serilaisation behaviour in MSVC 2017-09-07 15:04:30 +01:00
Phil Nash
ca7021ae19 Reflected file extension changes in CMakeLists.txt file 2017-09-07 12:58:44 +01:00
Phil Nash
03d41ce5b9 Suppressed meaningless function type qualifier warning in MSVC again
(this time in catch_tostring.h)
2017-09-07 11:25:10 +01:00
Phil Nash
c5608f0202 Changed all .hpp extensions to .h where there is now a corresponding .cpp 2017-09-07 11:24:33 +01:00
Phil Nash
8c39f9a725 Suppress MSVC warning about meaningless function type qualifier in generic code 2017-09-07 11:15:07 +01:00
Phil Nash
4e5a67bc44 Added back OCTest project 2017-09-06 15:44:42 +01:00
Phil Nash
2d37649377 Fixed Objective-C mode 2017-09-06 15:44:42 +01:00
Martin Hořeňovský
8d03cb4915 Use StringRef to pass comparison operator name to BinaryExpr
Some nominally C++11 platforms do not have SSO (I am looking at
you libstdc++), where this avoids meaningless allocations.
2017-09-06 15:15:48 +02:00
Martin Hořeňovský
b000411434 Stop accepting non-const comparison operators
A) non-const comparison operators should not exist and should not be
encouraged

B) The logic breaks comparing function pointers certain way

C) It was inconsistent anyway, as it only applied to `==` and `!=`

Closes #925
2017-09-06 15:01:03 +02:00
Martin Hořeňovský
aef2e4d9e7 Update baselines 2017-09-02 20:29:05 +02:00
Martin Hořeňovský
ab5d176195 Fix/disable failing approval tests 2017-09-02 10:51:19 +02:00
Martin Hořeňovský
b3a923133d Actually fix AppVeyor ctest
Note, this doesn't mean it will start passing, just that it will
run the approval tests properly

Some changes are needed before it passes, as the Windows output
somewhat differs.
2017-09-01 19:12:15 +02:00
Martin Hořeňovský
35bad89684 Fix ctest failure on windows 2017-09-01 17:55:16 +02:00
Phil Nash
792d3d0a26 Fixed alignment of getSupportedVerbosities in MultipleReporters 2017-09-01 09:41:28 +01:00
offa
be067bce37 Explicit ctor used to fix compilation failures caused by copy
initialization.
2017-09-01 09:40:11 +01:00
Phil Nash
115db71bab Incorporated Clara with TextFlow fix for assertion with consecutive newlines
fixes #1012
2017-08-31 16:14:27 +01:00
Martin Hořeňovský
3a5b951256 Make approval tests part of ctest 2017-08-31 12:00:35 +02:00
Martin Hořeňovský
4e4a13dfb4 Update approvals after removing deprecated matcher helpers 2017-08-31 11:50:34 +02:00
Martin Hořeňovský
e8ec6bd73c General cleanup for C++11
Also less allocations and less stack usage on the fatal condition path
2017-08-31 11:46:37 +02:00
Martin Hořeňovský
e871742534 Move session to internal, split apart implementation 2017-08-31 10:31:52 +02:00
Martin Hořeňovský
6388fc946f Remove last usage of NotImplementedException
TeamCity reporter now uses CATCH_ERROR instead
2017-08-30 20:03:54 +02:00
Martin Hořeňovský
a4df0b2c37 Remove obsoleted utility functions on matchers
Natural operators, &&, || and ! are preferred and do not have
limited arity.
2017-08-30 19:45:09 +02:00
Martin Hořeňovský
97edf7ce65 Fix-up compilation benchmark script 2017-08-30 18:11:52 +02:00
Martin Hořeňovský
49a1408ff2 Fix compilation of main file with CATCH_CONFIG_FAST_COMPILE 2017-08-30 18:07:29 +02:00
Martin Hořeňovský
9796c516bb Always compile matchers implementation 2017-08-30 18:06:48 +02:00
Martin Hořeňovský
255f7d7369 Minor cleanup 2017-08-30 15:53:39 +02:00
Martin Hořeňovský
46e28791ff Stitch .cpp files into single header in deterministic order 2017-08-30 15:43:44 +02:00
Martin Hořeňovský
0673b9be35 Split RNG related things into its own file
This further removes 2 function declarations from the common path
2017-08-30 15:32:44 +02:00
Martin Hořeňovský
48db47c737 Remove unused internal macro from the common path 2017-08-30 15:30:10 +02:00
Martin Hořeňovský
cde57d9365 Remove tag alias registry interface from the common path 2017-08-30 15:28:33 +02:00
Martin Hořeňovský
13213faa4e Update release notes in regards to CATCH_CONFIG_DISABLE 2017-08-30 12:43:23 +02:00
solvingj
5ca44b6872 Minor - added header-only flag in conan
See header-only guidelines: 
http://conanio.readthedocs.io/en/latest/howtos/header_only.html?highlight=header%20only
Its borderline cosmetic, but it does have a purpose.
2017-08-28 12:18:54 +02:00
Sam Bristow
a04bd6d436 Remove duplicate CLI option
The "use-colour" option was accidentally duplicated as part of commit
feaf355 (Implemented libidentify support).
2017-08-28 12:16:23 +02:00
Martin Hořeňovský
784f6dfb34 Fix updateVcpkgPackage 2017-08-27 11:43:55 +02:00
Martin Hořeňovský
7818e2666d v1.10.0 2017-08-26 15:34:18 +02:00
Martin Hořeňovský
cd30dd1a70 Workaround raw string literal bug in VS2017 2017-08-26 15:14:27 +02:00
Phil Nash
8e8c0c1675 Tweaked how failedButOk assertions are recorded
- fixes issue where sections in !shouldfail or !mayfail test cases that have failing assertions where marked as failed instead of failedButOk
2017-08-25 11:37:49 +01:00
Phil Nash
b6e7c9bd7a Specialise removeConst for nullptr 2017-08-24 23:07:44 +02:00
Phil Nash
180d9242f5 Suppress more signed/ unsigned mismatches during Evaluator calls on MSVC 2017-08-24 23:07:03 +02:00
Phil Nash
b7bd52cc98 Cherry-picked "evaluate" refactoring from dev-modernize branch
- fixed up NULL comparisons to allow for NULL being a long
- should address #981
2017-08-24 23:07:03 +02:00
Martin Hořeňovský
b07a2bdf87 Refactor release scripts, automatically update Wandbox on release 2017-08-24 21:59:06 +02:00
Martin Hořeňovský
c03e8fce92 Explicitly ignore return value of getchar
This silences MSVC warning about ignored return value
2017-08-22 22:06:37 +02:00
Phil Nash
27640a5a96 Added Clara and TextFlowCpp to open source users 2017-08-17 10:49:56 +01:00
Phil Nash
dd3867bbcd Create CODE_OF_CONDUCT.md 2017-08-17 07:45:12 +01:00
Phil Nash
387f8d254d Removed unnecessary single quotes 2017-08-15 19:41:46 +01:00
Phil Nash
c65eccd68e Added --libidentify and --wait-for-keypress to docs 2017-08-15 19:39:38 +01:00
Phil Nash
61c5675c11 Removed inadvertent use of auto merged from dev-modernise 2017-08-15 19:34:10 +01:00
Phil Nash
70e4af9d44 Implemented wait-for-keypress option 2017-08-15 14:12:11 +01:00
Monocasual
8f41bdb92d Add open-source user 2017-08-13 17:55:50 +02:00
Phil Nash
7fa5d9ca94 Removed redundant processName argument from libIdentify call 2017-08-11 22:03:09 +01:00
Phil Nash
feaf355489 Implemented libidentify support
- see https://github.com/janwilmans/LibIdentify
2017-08-11 19:55:55 +01:00
Martin Hořeňovský
2ce6c74f8f v1.9.7 2017-08-11 00:01:20 +02:00
Phil Nash
9688891868 Fix issue with fatal errors and non-failing assertions
Fixes #990
2017-08-10 21:44:54 +02:00
Martin Hořeňovský
4f21bb72ff Add tests for #961 2017-08-10 21:38:07 +02:00
Martin Hořeňovský
b435e0d7c7 Make default reporter configurable at compile time
Closes #978
2017-08-10 16:45:38 +02:00
Martin Hořeňovský
ba0a09fd9e Update documentation with changes from 7e4038d 2017-08-10 16:43:17 +02:00
317 changed files with 33524 additions and 13832 deletions

13
.gitattributes vendored
View File

@@ -8,4 +8,15 @@
*.hpp text *.hpp text
# Windows specific files should retain windows line-endings # 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

6
.gitignore vendored
View File

@@ -24,6 +24,6 @@ DerivedData
*.xccheckout *.xccheckout
Build Build
.idea .idea
cmake-build-debug .vs
cmake-build-release cmake-build-*
.vs benchmark-dir

View File

@@ -1,227 +1,312 @@
language: cpp language: cpp
sudo: false 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: matrix:
include: include:
# 1/ Linux Clang Builds # 1/ Linux Clang Builds
- os: linux - os: linux
compiler: clang compiler: clang
addons: &clang35 addons:
apt: apt:
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['clang-3.5'] packages: ['clang-3.5']
env: COMPILER='clang++-3.5' BUILD_TYPE='Release' env: COMPILER='clang++-3.5'
- os: linux - os: linux
compiler: clang compiler: clang
addons: *clang35 addons:
env: COMPILER='clang++-3.5' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang36
apt: apt:
sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['clang-3.6'] packages: ['clang-3.6']
env: COMPILER='clang++-3.6' BUILD_TYPE='Release' env: COMPILER='clang++-3.6'
# Clang 3.7 is intentionally skipped as we cannot get it easily on
# TravisCI container
- os: linux - os: linux
compiler: clang compiler: clang
addons: *clang36 addons:
env: COMPILER='clang++-3.6' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang37
apt: apt:
sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['clang-3.7'] packages: ['lcov', 'clang-3.8']
env: COMPILER='clang++-3.7' BUILD_TYPE='Release' env: COMPILER='clang++-3.8'
- os: linux - os: linux
compiler: clang compiler: clang
addons: *clang37 addons:
env: COMPILER='clang++-3.7' BUILD_TYPE='Debug' apt:
sources: *all_sources
packages: ['clang-3.9']
env: COMPILER='clang++-3.9'
- os: linux - os: linux
compiler: clang compiler: clang
addons: &clang38 addons:
apt: apt:
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['clang-3.8'] packages: ['clang-4.0']
env: COMPILER='clang++-3.8' BUILD_TYPE='Release' env: COMPILER='clang++-4.0'
- os: linux - os: linux
compiler: clang compiler: clang
addons: *clang38 addons:
env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' apt:
sources: *all_sources
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 # 2/ Linux GCC Builds
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: &gcc48 addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['g++-4.8'] packages: ['g++-4.8']
env: COMPILER='g++-4.8' BUILD_TYPE='Release' env: COMPILER='g++-4.8'
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: *gcc48 addons:
env: COMPILER='g++-4.8' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc49
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['g++-4.9'] packages: ['g++-4.9']
env: COMPILER='g++-4.9' BUILD_TYPE='Release' env: COMPILER='g++-4.9'
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: *gcc49 addons:
env: COMPILER='g++-4.9' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc5
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['g++-5'] packages: ['g++-5']
env: COMPILER='g++-5' BUILD_TYPE='Release' env: COMPILER='g++-5'
- os: linux
compiler: gcc
addons: *gcc5
env: COMPILER='g++-5' BUILD_TYPE='Debug'
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: &gcc6 addons: &gcc6
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: *all_sources
packages: ['g++-6'] packages: ['g++-6']
env: COMPILER='g++-6' BUILD_TYPE='Release' env: COMPILER='g++-6'
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: *gcc6 addons: &gcc7
env: COMPILER='g++-6' BUILD_TYPE='Debug' apt:
sources: *all_sources
# 3a/ Linux C++11 GCC builds packages: ['g++-7']
- os: linux env: COMPILER='g++-7'
compiler: gcc
addons: *gcc48
env: COMPILER='g++-4.8' BUILD_TYPE='Release' CPP11=1
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: *gcc48 addons: &gcc8
env: COMPILER='g++-4.8' BUILD_TYPE='Debug' CPP11=1 apt:
sources: *all_sources
packages: ['g++-8']
env: COMPILER='g++-8'
# 3b/ Linux C++11 Clang builds # 3b/ Linux C++14 Clang builds
# Note that we need newer libstdc++ for C++14 support
- os: linux - os: linux
compiler: clang compiler: clang
addons: *clang38 addons:
env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP11=1 apt:
packages: ['clang-3.8', 'libstdc++-6-dev']
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
env: COMPILER='clang++-3.8' CPP14=1
- os: linux - os: linux
compiler: clang compiler: clang
addons: *clang38 addons:
env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP11=1 apt:
sources: *all_sources
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', 'libstdc++-6-dev']
env: COMPILER='clang++-4.0' CPP14=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
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 # 4a/ Linux C++14 GCC builds
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: *gcc6 addons: *gcc6
env: COMPILER='g++-6' BUILD_TYPE='Release' CPP14=1 env: COMPILER='g++-6' CPP14=1
- os: linux - os: linux
compiler: gcc compiler: gcc
addons: *gcc6 addons: *gcc7
env: COMPILER='g++-6' BUILD_TYPE='Debug' CPP14=1 env: COMPILER='g++-7' CPP14=1
# # 4b/ Linux C++14 Clang builds
# - os: linux
# compiler: clang
# addons: *clang38
# env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP14=1
#
# - os: linux
# compiler: clang
# addons: *clang38
# env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP14=1
- os: linux
compiler: gcc
addons: *gcc8
env: COMPILER='g++-8' CPP14=1
# 5/ OSX Clang Builds # 5/ OSX Clang Builds
- os: osx - os: osx
osx_image: xcode7.3 osx_image: xcode7.3
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug' env: COMPILER='clang++'
- os: osx
osx_image: xcode7.3
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Release'
- os: osx - os: osx
osx_image: xcode8 osx_image: xcode8
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug' env: COMPILER='clang++'
- os: osx - os: osx
osx_image: xcode8 osx_image: xcode9
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Release' env: COMPILER='clang++'
- os: osx - os: osx
osx_image: xcode8 osx_image: xcode9.1
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug' USE_CPP11=1 env: COMPILER='clang++'
- os: osx - os: osx
osx_image: xcode8 osx_image: xcode9.1
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Release' USE_CPP11=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 EXTRAS=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 EXTRAS=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 - os: osx
osx_image: xcode8 osx_image: xcode9.1
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug' USE_CPP14=1 env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
- os: osx # 7/ C++17 builds
osx_image: xcode8 - os: linux
compiler: gcc
addons: *gcc7
env: COMPILER='g++-7' CPP17=1
- os: linux
compiler: gcc
addons: *gcc7
env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
- os: linux
compiler: clang compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Release' USE_CPP14=1 addons:
apt:
sources: *all_sources
packages: ['clang-6.0', 'libstdc++-8-dev']
env: COMPILER='clang++-6.0' CPP17=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-6.0', 'libstdc++-8-dev']
env: COMPILER='clang++-6.0' CPP17=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
install: install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
- | - |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then 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://cmake.org/files/v3.8/cmake-3.8.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 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} export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
which cmake || brew install cmake which cmake || brew install cmake;
fi fi
before_script: before_script:
- export CXX=${COMPILER} - export CXX=${COMPILER}
- cd ${TRAVIS_BUILD_DIR} - cd ${TRAVIS_BUILD_DIR}
- cmake -H. -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -Wdev -DUSE_CPP11=${CPP11} -DUSE_CPP14=${CPP14} # Regenerate single header file, so it is tested in the examples...
- cd Build - 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_CPP17=${CPP17} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE} -DCATCH_BUILD_EXTRA_TESTS=${EXTRAS}
# Don't bother with release build for coverage build
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
script: script:
- cd Build-Debug
- make -j 2 - make -j 2
- ctest -V -j 2 - CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
# Coverage collection does not work for OS X atm
- |
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

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()

157
CMake/FindGcov.cmake Normal file
View File

@@ -0,0 +1,157 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
# include required Modules
include(FindPackageHandleStandardArgs)
# Search for gcov binary.
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Gcov evaluation is dependend on the used compiler. Check gcov support for
# each compiler that is used. If gcov binary was already found for this
# compiler, do not try to find it again.
if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN)
get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH)
if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU")
# Some distributions like OSX (homebrew) ship gcov with the compiler
# version appended as gcov-x. To find this binary we'll build the
# suggested binary name with the compiler version.
string(REGEX MATCH "^[0-9]+" GCC_VERSION
"${CMAKE_${LANG}_COMPILER_VERSION}")
find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov
HINTS ${COMPILER_PATH})
elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang")
# Some distributions like Debian ship llvm-cov with the compiler
# version appended as llvm-cov-x.y. To find this binary we'll build
# the suggested binary name with the compiler version.
string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION
"${CMAKE_${LANG}_COMPILER_VERSION}")
# llvm-cov prior version 3.5 seems to be not working with coverage
# evaluation tools, but these versions are compatible with the gcc
# gcov tool.
if(LLVM_VERSION VERSION_GREATER 3.4)
find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}"
"llvm-cov" HINTS ${COMPILER_PATH})
mark_as_advanced(LLVM_COV_BIN)
if (LLVM_COV_BIN)
find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS
${CMAKE_MODULE_PATH})
if (LLVM_COV_WRAPPER)
set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "")
# set additional parameters
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV
"LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING
"Environment variables for llvm-cov-wrapper.")
mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV)
endif ()
endif ()
endif ()
if (NOT GCOV_BIN)
# Fall back to gcov binary if llvm-cov was not found or is
# incompatible. This is the default on OSX, but may crash on
# recent Linux versions.
find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH})
endif ()
endif ()
if (GCOV_BIN)
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING
"${LANG} gcov binary.")
if (NOT CMAKE_REQUIRED_QUIET)
message("-- Found gcov evaluation for "
"${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}")
endif()
unset(GCOV_BIN CACHE)
endif ()
endif ()
endforeach ()
# Add a new global target for all gcov targets. This target could be used to
# generate the gcov files for the whole project instead of calling <TARGET>-gcov
# for each target.
if (NOT TARGET gcov)
add_custom_target(gcov)
endif (NOT TARGET gcov)
# This function will add gcov evaluation for target <TNAME>. Only sources of
# this target will be evaluated and no dependencies will be added. It will call
# Gcov on any source file of <TNAME> once and store the gcov file in the same
# directory.
function (add_gcov_target TNAME)
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
set(BUFFER "")
foreach(FILE ${SOURCES})
get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH)
# call gcov
add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov
COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null
DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno
WORKING_DIRECTORY ${FILE_PATH}
)
list(APPEND BUFFER ${TDIR}/${FILE}.gcov)
endforeach()
# add target for gcov evaluation of <TNAME>
add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER})
# add evaluation target to the global gcov target.
add_dependencies(gcov ${TNAME}-gcov)
endfunction (add_gcov_target)

354
CMake/FindLcov.cmake Normal file
View File

@@ -0,0 +1,354 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
# configuration
set(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data")
set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init")
set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture")
set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html")
# Search for Gcov which is used by Lcov.
find_package(Gcov)
# This function will add lcov evaluation for target <TNAME>. Only sources of
# this target will be evaluated and no dependencies will be added. It will call
# geninfo on any source file of <TNAME> once and store the info file in the same
# directory.
#
# Note: This function is only a wrapper to define this function always, even if
# coverage is not supported by the compiler or disabled. This function must
# be defined here, because the module will be exited, if there is no coverage
# support by the compiler or it is disabled by the user.
function (add_lcov_target TNAME)
if (LCOV_FOUND)
# capture initial coverage data
lcov_capture_initial_tgt(${TNAME})
# capture coverage data after execution
lcov_capture_tgt(${TNAME})
endif ()
endfunction (add_lcov_target)
# include required Modules
include(FindPackageHandleStandardArgs)
# Search for required lcov binaries.
find_program(LCOV_BIN lcov)
find_program(GENINFO_BIN geninfo)
find_program(GENHTML_BIN genhtml)
find_package_handle_standard_args(lcov
REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN
)
# enable genhtml C++ demangeling, if c++filt is found.
set(GENHTML_CPPFILT_FLAG "")
find_program(CPPFILT_BIN c++filt)
if (NOT CPPFILT_BIN STREQUAL "")
set(GENHTML_CPPFILT_FLAG "--demangle-cpp")
endif (NOT CPPFILT_BIN STREQUAL "")
# enable no-external flag for lcov, if available.
if (GENINFO_BIN AND NOT DEFINED GENINFO_EXTERN_FLAG)
set(FLAG "")
execute_process(COMMAND ${GENINFO_BIN} --help OUTPUT_VARIABLE GENINFO_HELP)
string(REGEX MATCH "external" GENINFO_RES "${GENINFO_HELP}")
if (GENINFO_RES)
set(FLAG "--no-external")
endif ()
set(GENINFO_EXTERN_FLAG "${FLAG}"
CACHE STRING "Geninfo flag to exclude system sources.")
endif ()
# If Lcov was not found, exit module now.
if (NOT LCOV_FOUND)
return()
endif (NOT LCOV_FOUND)
# Create directories to be used.
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT})
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE})
set(LCOV_REMOVE_PATTERNS "")
# This function will merge lcov files to a single target file. Additional lcov
# flags may be set with setting LCOV_EXTRA_FLAGS before calling this function.
function (lcov_merge_files OUTFILE ...)
# Remove ${OUTFILE} from ${ARGV} and generate lcov parameters with files.
list(REMOVE_AT ARGV 0)
# Generate merged file.
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}")
add_custom_command(OUTPUT "${OUTFILE}.raw"
COMMAND cat ${ARGV} > ${OUTFILE}.raw
DEPENDS ${ARGV}
COMMENT "Generating ${FILE_REL}"
)
add_custom_command(OUTPUT "${OUTFILE}"
COMMAND ${LCOV_BIN} --quiet -a ${OUTFILE}.raw --output-file ${OUTFILE}
--base-directory ${PROJECT_SOURCE_DIR} ${LCOV_EXTRA_FLAGS}
COMMAND ${LCOV_BIN} --quiet -r ${OUTFILE} ${LCOV_REMOVE_PATTERNS}
--output-file ${OUTFILE} ${LCOV_EXTRA_FLAGS}
DEPENDS ${OUTFILE}.raw
COMMENT "Post-processing ${FILE_REL}"
)
endfunction ()
# Add a new global target to generate initial coverage reports for all targets.
# This target will be used to generate the global initial info file, which is
# used to gather even empty report data.
if (NOT TARGET lcov-capture-init)
add_custom_target(lcov-capture-init)
set(LCOV_CAPTURE_INIT_FILES "" CACHE INTERNAL "")
endif (NOT TARGET lcov-capture-init)
# This function will add initial capture of coverage data for target <TNAME>,
# which is needed to get also data for objects, which were not loaded at
# execution time. It will call geninfo for every source file of <TNAME> once and
# store the info file in the same directory.
function (lcov_capture_initial_tgt TNAME)
# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
set(GENINFO_FILES "")
foreach(FILE ${SOURCES})
# generate empty coverage files
set(OUTFILE "${TDIR}/${FILE}.info.init")
list(APPEND GENINFO_FILES ${OUTFILE})
add_custom_command(OUTPUT ${OUTFILE} COMMAND ${GCOV_ENV} ${GENINFO_BIN}
--quiet --base-directory ${PROJECT_SOURCE_DIR} --initial
--gcov-tool ${GCOV_BIN} --output-filename ${OUTFILE}
${GENINFO_EXTERN_FLAG} ${TDIR}/${FILE}.gcno
DEPENDS ${TNAME}
COMMENT "Capturing initial coverage data for ${FILE}"
)
endforeach()
# Concatenate all files generated by geninfo to a single file per target.
set(OUTFILE "${LCOV_DATA_PATH_INIT}/${TNAME}.info")
set(LCOV_EXTRA_FLAGS "--initial")
lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})
add_custom_target(${TNAME}-capture-init ALL DEPENDS ${OUTFILE})
# add geninfo file generation to global lcov-geninfo target
add_dependencies(lcov-capture-init ${TNAME}-capture-init)
set(LCOV_CAPTURE_INIT_FILES "${LCOV_CAPTURE_INIT_FILES}"
"${OUTFILE}" CACHE INTERNAL ""
)
endfunction (lcov_capture_initial_tgt)
# This function will generate the global info file for all targets. It has to be
# called after all other CMake functions in the root CMakeLists.txt file, to get
# a full list of all targets that generate coverage data.
function (lcov_capture_initial)
# Skip this function (and do not create the following targets), if there are
# no input files.
if ("${LCOV_CAPTURE_INIT_FILES}" STREQUAL "")
return()
endif ()
# Add a new target to merge the files of all targets.
set(OUTFILE "${LCOV_DATA_PATH_INIT}/all_targets.info")
lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_INIT_FILES})
add_custom_target(lcov-geninfo-init ALL DEPENDS ${OUTFILE}
lcov-capture-init
)
endfunction (lcov_capture_initial)
# Add a new global target to generate coverage reports for all targets. This
# target will be used to generate the global info file.
if (NOT TARGET lcov-capture)
add_custom_target(lcov-capture)
set(LCOV_CAPTURE_FILES "" CACHE INTERNAL "")
endif (NOT TARGET lcov-capture)
# This function will add capture of coverage data for target <TNAME>, which is
# needed to get also data for objects, which were not loaded at execution time.
# It will call geninfo for every source file of <TNAME> once and store the info
# file in the same directory.
function (lcov_capture_tgt TNAME)
# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
set(GENINFO_FILES "")
foreach(FILE ${SOURCES})
# Generate coverage files. If no .gcda file was generated during
# execution, the empty coverage file will be used instead.
set(OUTFILE "${TDIR}/${FILE}.info")
list(APPEND GENINFO_FILES ${OUTFILE})
add_custom_command(OUTPUT ${OUTFILE}
COMMAND test -f "${TDIR}/${FILE}.gcda"
&& ${GCOV_ENV} ${GENINFO_BIN} --quiet --base-directory
${PROJECT_SOURCE_DIR} --gcov-tool ${GCOV_BIN}
--output-filename ${OUTFILE} ${GENINFO_EXTERN_FLAG}
${TDIR}/${FILE}.gcda
|| cp ${OUTFILE}.init ${OUTFILE}
DEPENDS ${TNAME} ${TNAME}-capture-init
COMMENT "Capturing coverage data for ${FILE}"
)
endforeach()
# Concatenate all files generated by geninfo to a single file per target.
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info")
lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})
add_custom_target(${TNAME}-geninfo DEPENDS ${OUTFILE})
# add geninfo file generation to global lcov-capture target
add_dependencies(lcov-capture ${TNAME}-geninfo)
set(LCOV_CAPTURE_FILES "${LCOV_CAPTURE_FILES}" "${OUTFILE}" CACHE INTERNAL
""
)
# Add target for generating html output for this target only.
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/${TNAME})
add_custom_target(${TNAME}-genhtml
COMMAND ${GENHTML_BIN} --quiet --sort --prefix ${PROJECT_SOURCE_DIR}
--baseline-file ${LCOV_DATA_PATH_INIT}/${TNAME}.info
--output-directory ${LCOV_HTML_PATH}/${TNAME}
--title "${CMAKE_PROJECT_NAME} - target ${TNAME}"
${GENHTML_CPPFILT_FLAG} ${OUTFILE}
DEPENDS ${TNAME}-geninfo ${TNAME}-capture-init
)
endfunction (lcov_capture_tgt)
# This function will generate the global info file for all targets. It has to be
# called after all other CMake functions in the root CMakeLists.txt file, to get
# a full list of all targets that generate coverage data.
function (lcov_capture)
# Skip this function (and do not create the following targets), if there are
# no input files.
if ("${LCOV_CAPTURE_FILES}" STREQUAL "")
return()
endif ()
# Add a new target to merge the files of all targets.
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info")
lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_FILES})
add_custom_target(lcov-geninfo DEPENDS ${OUTFILE} lcov-capture)
# Add a new global target for all lcov targets. This target could be used to
# generate the lcov html output for the whole project instead of calling
# <TARGET>-geninfo and <TARGET>-genhtml for each target. It will also be
# used to generate a html site for all project data together instead of one
# for each target.
if (NOT TARGET lcov)
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/all_targets)
add_custom_target(lcov
COMMAND ${GENHTML_BIN} --quiet --sort
--baseline-file ${LCOV_DATA_PATH_INIT}/all_targets.info
--output-directory ${LCOV_HTML_PATH}/all_targets
--title "${CMAKE_PROJECT_NAME}" --prefix "${PROJECT_SOURCE_DIR}"
${GENHTML_CPPFILT_FLAG} ${OUTFILE}
DEPENDS lcov-geninfo-init lcov-geninfo
)
endif ()
endfunction (lcov_capture)
# Add a new global target to generate the lcov html report for the whole project
# instead of calling <TARGET>-genhtml for each target (to create an own report
# for each target). Instead of the lcov target it does not require geninfo for
# all targets, so you have to call <TARGET>-geninfo to generate the info files
# the targets you'd like to have in your report or lcov-geninfo for generating
# info files for all targets before calling lcov-genhtml.
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/selected_targets)
if (NOT TARGET lcov-genhtml)
add_custom_target(lcov-genhtml
COMMAND ${GENHTML_BIN}
--quiet
--output-directory ${LCOV_HTML_PATH}/selected_targets
--title \"${CMAKE_PROJECT_NAME} - targets `find
${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name
\"all_targets.info\" -exec basename {} .info \\\;`\"
--prefix ${PROJECT_SOURCE_DIR}
--sort
${GENHTML_CPPFILT_FLAG}
`find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name
\"all_targets.info\"`
)
endif (NOT TARGET lcov-genhtml)

258
CMake/Findcodecov.cmake Normal file
View File

@@ -0,0 +1,258 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
# Add an option to choose, if coverage should be enabled or not. If enabled
# marked targets will be build with coverage support and appropriate targets
# will be added. If disabled coverage will be ignored for *ALL* targets.
option(ENABLE_COVERAGE "Enable coverage build." OFF)
set(COVERAGE_FLAG_CANDIDATES
# gcc and clang
"-O0 -g -fprofile-arcs -ftest-coverage"
# gcc and clang fallback
"-O0 -g --coverage"
)
# Add coverage support for target ${TNAME} and register target for coverage
# evaluation. If coverage is disabled or not supported, this function will
# simply do nothing.
#
# Note: This function is only a wrapper to define this function always, even if
# coverage is not supported by the compiler or disabled. This function must
# be defined here, because the module will be exited, if there is no coverage
# support by the compiler or it is disabled by the user.
function (add_coverage TNAME)
# only add coverage for target, if coverage is support and enabled.
if (ENABLE_COVERAGE)
foreach (TNAME ${ARGV})
add_coverage_target(${TNAME})
endforeach ()
endif ()
endfunction (add_coverage)
# Add global target to gather coverage information after all targets have been
# added. Other evaluation functions could be added here, after checks for the
# specific module have been passed.
#
# Note: This function is only a wrapper to define this function always, even if
# coverage is not supported by the compiler or disabled. This function must
# be defined here, because the module will be exited, if there is no coverage
# support by the compiler or it is disabled by the user.
function (coverage_evaluate)
# add lcov evaluation
if (LCOV_FOUND)
lcov_capture_initial()
lcov_capture()
endif (LCOV_FOUND)
endfunction ()
# Exit this module, if coverage is disabled. add_coverage is defined before this
# return, so this module can be exited now safely without breaking any build-
# scripts.
if (NOT ENABLE_COVERAGE)
return()
endif ()
# Find the reuired flags foreach language.
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Coverage flags are not dependend on language, but the used compiler. So
# instead of searching flags foreach language, search flags foreach compiler
# used.
set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
if (NOT COVERAGE_${COMPILER}_FLAGS)
foreach (FLAG ${COVERAGE_FLAG_CANDIDATES})
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Try ${COMPILER} code coverage flag = [${FLAG}]")
endif()
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
unset(COVERAGE_FLAG_DETECTED CACHE)
if (${LANG} STREQUAL "C")
include(CheckCCompilerFlag)
check_c_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
elseif (${LANG} STREQUAL "CXX")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
elseif (${LANG} STREQUAL "Fortran")
# CheckFortranCompilerFlag was introduced in CMake 3.x. To be
# compatible with older Cmake versions, we will check if this
# module is present before we use it. Otherwise we will define
# Fortran coverage support as not available.
include(CheckFortranCompilerFlag OPTIONAL
RESULT_VARIABLE INCLUDED)
if (INCLUDED)
check_fortran_compiler_flag("${FLAG}"
COVERAGE_FLAG_DETECTED)
elseif (NOT CMAKE_REQUIRED_QUIET)
message("-- Performing Test COVERAGE_FLAG_DETECTED")
message("-- Performing Test COVERAGE_FLAG_DETECTED - Failed"
" (Check not supported)")
endif ()
endif()
if (COVERAGE_FLAG_DETECTED)
set(COVERAGE_${COMPILER}_FLAGS "${FLAG}"
CACHE STRING "${COMPILER} flags for code coverage.")
mark_as_advanced(COVERAGE_${COMPILER}_FLAGS)
break()
else ()
message(WARNING "Code coverage is not available for ${COMPILER}"
" compiler. Targets using this compiler will be "
"compiled without it.")
endif ()
endforeach ()
endif ()
endforeach ()
set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
# Helper function to get the language of a source file.
function (codecov_lang_of_source FILE RETURN_VAR)
get_filename_component(FILE_EXT "${FILE}" EXT)
string(TOLOWER "${FILE_EXT}" FILE_EXT)
string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
if (NOT ${TEMP} EQUAL -1)
set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
return()
endif ()
endforeach()
set(${RETURN_VAR} "" PARENT_SCOPE)
endfunction ()
# Helper function to get the relative path of the source file destination path.
# This path is needed by FindGcov and FindLcov cmake files to locate the
# captured data.
function (codecov_path_of_source FILE RETURN_VAR)
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _source ${FILE})
# If expression was found, SOURCEFILE is a generator-expression for an
# object library. Currently we found no way to call this function automatic
# for the referenced target, so it must be called in the directoryso of the
# object library definition.
if (NOT "${_source}" STREQUAL "")
set(${RETURN_VAR} "" PARENT_SCOPE)
return()
endif ()
string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" FILE "${FILE}")
if(IS_ABSOLUTE ${FILE})
file(RELATIVE_PATH FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
endif()
# get the right path for file
string(REPLACE ".." "__" PATH "${FILE}")
set(${RETURN_VAR} "${PATH}" PARENT_SCOPE)
endfunction()
# Add coverage support for target ${TNAME} and register target for coverage
# evaluation.
function(add_coverage_target TNAME)
# Check if all sources for target use the same compiler. If a target uses
# e.g. C and Fortran mixed and uses different compilers (e.g. clang and
# gfortran) this can trigger huge problems, because different compilers may
# use different implementations for code coverage.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(TARGET_COMPILER "")
set(ADDITIONAL_FILES "")
foreach (FILE ${TSOURCES})
# If expression was found, FILE is a generator-expression for an object
# library. Object libraries will be ignored.
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
if ("${_file}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (LANG)
list(APPEND TARGET_COMPILER ${CMAKE_${LANG}_COMPILER_ID})
list(APPEND ADDITIONAL_FILES "${FILE}.gcno")
list(APPEND ADDITIONAL_FILES "${FILE}.gcda")
endif ()
endif ()
endforeach ()
list(REMOVE_DUPLICATES TARGET_COMPILER)
list(LENGTH TARGET_COMPILER NUM_COMPILERS)
if (NUM_COMPILERS GREATER 1)
message(WARNING "Can't use code coverage for target ${TNAME}, because "
"it will be compiled by incompatible compilers. Target will be "
"compiled without code coverage.")
return()
elseif (NUM_COMPILERS EQUAL 0)
message(WARNING "Can't use code coverage for target ${TNAME}, because "
"it uses an unknown compiler. Target will be compiled without "
"code coverage.")
return()
elseif (NOT DEFINED "COVERAGE_${TARGET_COMPILER}_FLAGS")
# A warning has been printed before, so just return if flags for this
# compiler aren't available.
return()
endif()
# enable coverage for target
set_property(TARGET ${TNAME} APPEND_STRING
PROPERTY COMPILE_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
set_property(TARGET ${TNAME} APPEND_STRING
PROPERTY LINK_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
# Add gcov files generated by compiler to clean target.
set(CLEAN_FILES "")
foreach (FILE ${ADDITIONAL_FILES})
codecov_path_of_source(${FILE} FILE)
list(APPEND CLEAN_FILES "CMakeFiles/${TNAME}.dir/${FILE}")
endforeach()
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
"${CLEAN_FILES}")
add_gcov_target(${TNAME})
add_lcov_target(${TNAME})
endfunction(add_coverage_target)
# Include modules for parsing the collected data and output it in a readable
# format (like gcov and lcov).
find_package(Gcov)
find_package(Lcov)

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}

56
CMake/llvm-cov-wrapper Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/sh
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
if [ -z "$LLVM_COV_BIN" ]
then
echo "LLVM_COV_BIN not set!" >& 2
exit 1
fi
# Get LLVM version to find out.
LLVM_VERSION=$($LLVM_COV_BIN -version | grep -i "LLVM version" \
| sed "s/^\([A-Za-z ]*\)\([0-9]\).\([0-9]\).*$/\2.\3/g")
if [ "$1" = "-v" ]
then
echo "llvm-cov-wrapper $LLVM_VERSION"
exit 0
fi
if [ -n "$LLVM_VERSION" ]
then
MAJOR=$(echo $LLVM_VERSION | cut -d'.' -f1)
MINOR=$(echo $LLVM_VERSION | cut -d'.' -f2)
if [ $MAJOR -eq 3 ] && [ $MINOR -le 4 ]
then
if [ -f "$1" ]
then
filename=$(basename "$1")
extension="${filename##*.}"
case "$extension" in
"gcno") exec $LLVM_COV_BIN --gcno="$1" ;;
"gcda") exec $LLVM_COV_BIN --gcda="$1" ;;
esac
fi
fi
if [ $MAJOR -eq 3 ] && [ $MINOR -le 5 ]
then
exec $LLVM_COV_BIN $@
fi
fi
exec $LLVM_COV_BIN gcov $@

View File

@@ -1,6 +1,29 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.5)
# 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.4.1)
# 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_BUILD_EXTRA_TESTS "Build extra tests" 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)
project(CatchSelfTest)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@@ -10,313 +33,176 @@ set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark) set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
set(HEADER_DIR ${CATCH_DIR}/include) set(HEADER_DIR ${CATCH_DIR}/include)
if(USE_CPP14)
message(STATUS "Enabling C++14")
set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
else()
message(STATUS "Enabling C++11")
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
endif()
if(USE_WMAIN) if(USE_WMAIN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
endif() endif()
#checks that the given hard-coded list contains all headers + sources in the given folder if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
function(CheckFileList LIST_VAR FOLDER) find_package(PythonInterp)
set(MESSAGE " should be added to the variable ${LIST_VAR}") if (NOT PYTHONINTERP_FOUND)
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n") message(FATAL_ERROR "Python not found, but required for tests")
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
function(CheckFileListRec LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
# define the sources of the self test
# Please keep these ordered alphabetically
set(TEST_SOURCES
${SELF_TEST_DIR}/ApproxTests.cpp
${SELF_TEST_DIR}/BDDTests.cpp
${SELF_TEST_DIR}/Benchmark.tests.cpp
${SELF_TEST_DIR}/ClassTests.cpp
${SELF_TEST_DIR}/CmdLineTests.cpp
${SELF_TEST_DIR}/CompilationTests.cpp
${SELF_TEST_DIR}/ConditionTests.cpp
${SELF_TEST_DIR}/DecompositionTests.cpp
${SELF_TEST_DIR}/EnumToString.cpp
${SELF_TEST_DIR}/ExceptionTests.cpp
${SELF_TEST_DIR}/MessageTests.cpp
${SELF_TEST_DIR}/MiscTests.cpp
${SELF_TEST_DIR}/PartTrackerTests.cpp
${SELF_TEST_DIR}/TagAliasTests.cpp
${SELF_TEST_DIR}/TestMain.cpp
${SELF_TEST_DIR}/ToStringGeneralTests.cpp
${SELF_TEST_DIR}/ToStringPair.cpp
${SELF_TEST_DIR}/ToStringTuple.cpp
${SELF_TEST_DIR}/ToStringVector.cpp
${SELF_TEST_DIR}/ToStringWhich.cpp
${SELF_TEST_DIR}/TrickyTests.cpp
${SELF_TEST_DIR}/VariadicMacrosTests.cpp
${SELF_TEST_DIR}/MatchersTests.cpp
${SELF_TEST_DIR}/StringRef.tests.cpp
)
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
# A set of impl files that just #include a single header
# Please keep these ordered alphabetically
set(SURROGATE_SOURCES
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_registry_hub.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
)
CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
# Please keep these ordered alphabetically
set(TOP_LEVEL_HEADERS
${HEADER_DIR}/catch.hpp
${HEADER_DIR}/catch_session.hpp
${HEADER_DIR}/catch_with_main.hpp
)
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
# Please keep these ordered alphabetically
set(EXTERNAL_HEADERS
${HEADER_DIR}/external/clara.hpp
)
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
# Please keep these ordered alphabetically
set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_approx.hpp
${HEADER_DIR}/internal/catch_assertionhandler.h
${HEADER_DIR}/internal/catch_assertioninfo.h
${HEADER_DIR}/internal/catch_assertionresult.h
${HEADER_DIR}/internal/catch_capture.hpp
${HEADER_DIR}/internal/catch_capture_matchers.h
${HEADER_DIR}/internal/catch_clara.h
${HEADER_DIR}/internal/catch_commandline.hpp
${HEADER_DIR}/internal/catch_common.h
${HEADER_DIR}/internal/catch_compiler_capabilities.h
${HEADER_DIR}/internal/catch_config.hpp
${HEADER_DIR}/internal/catch_console_colour.hpp
${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.hpp
${HEADER_DIR}/internal/catch_matchers_string.h
${HEADER_DIR}/internal/catch_matchers_vector.h
${HEADER_DIR}/internal/catch_message.h
${HEADER_DIR}/internal/catch_notimplemented_exception.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_reenable_warnings.h
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
${HEADER_DIR}/internal/catch_reporter_registry.hpp
${HEADER_DIR}/internal/catch_result_type.h
${HEADER_DIR}/internal/catch_run_context.hpp
${HEADER_DIR}/internal/catch_benchmark.h
${HEADER_DIR}/internal/catch_section.h
${HEADER_DIR}/internal/catch_section_info.h
${HEADER_DIR}/internal/catch_startup_exception_registry.h
${HEADER_DIR}/internal/catch_stream.h
${HEADER_DIR}/internal/catch_streambuf.h
${HEADER_DIR}/internal/catch_stringref.h
${HEADER_DIR}/internal/catch_string_manip.h
${HEADER_DIR}/internal/catch_suppress_warnings.h
${HEADER_DIR}/internal/catch_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.hpp
${HEADER_DIR}/internal/catch_test_case_tracker.hpp
${HEADER_DIR}/internal/catch_test_registry.hpp
${HEADER_DIR}/internal/catch_test_spec.hpp
${HEADER_DIR}/internal/catch_test_spec_parser.hpp
${HEADER_DIR}/internal/catch_text.h
${HEADER_DIR}/internal/catch_timer.h
${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_totals.hpp
${HEADER_DIR}/internal/catch_version.h
${HEADER_DIR}/internal/catch_wildcard_pattern.hpp
${HEADER_DIR}/internal/catch_windows_h_proxy.h
${HEADER_DIR}/internal/catch_xmlwriter.hpp
)
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_list.cpp
${HEADER_DIR}/internal/catch_leak_detector.cpp
${HEADER_DIR}/internal/catch_matchers.cpp
${HEADER_DIR}/internal/catch_matchers_string.cpp
${HEADER_DIR}/internal/catch_message.cpp
${HEADER_DIR}/internal/catch_notimplemented_exception.cpp
${HEADER_DIR}/internal/catch_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
${HEADER_DIR}/internal/catch_result_type.cpp
${HEADER_DIR}/internal/catch_run_context.cpp
${HEADER_DIR}/internal/catch_section.cpp
${HEADER_DIR}/internal/catch_section_info.cpp
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
${HEADER_DIR}/internal/catch_stream.cpp
${HEADER_DIR}/internal/catch_stringref.cpp
${HEADER_DIR}/internal/catch_string_manip.cpp
${HEADER_DIR}/internal/catch_tag_alias.cpp
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.cpp
${HEADER_DIR}/internal/catch_tag_alias_registry.cpp
${HEADER_DIR}/internal/catch_test_case_info.cpp
${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp
${HEADER_DIR}/internal/catch_test_case_tracker.cpp
${HEADER_DIR}/internal/catch_test_registry.cpp
${HEADER_DIR}/internal/catch_test_spec.cpp
${HEADER_DIR}/internal/catch_test_spec_parser.cpp
${HEADER_DIR}/internal/catch_timer.cpp
${HEADER_DIR}/internal/catch_tostring.cpp
${HEADER_DIR}/internal/catch_totals.cpp
${HEADER_DIR}/internal/catch_version.cpp
${HEADER_DIR}/internal/catch_wildcard_pattern.cpp
${HEADER_DIR}/internal/catch_xmlwriter.cpp
)
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal)
# Please keep these ordered alphabetically
set(REPORTER_HEADERS
${HEADER_DIR}/reporters/catch_reporter_automake.hpp
${HEADER_DIR}/reporters/catch_reporter_bases.hpp
${HEADER_DIR}/reporters/catch_reporter_multi.h
${HEADER_DIR}/reporters/catch_reporter_tap.hpp
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
)
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}
)
set(BENCH_SOURCES
${BENCHMARK_DIR}/BenchMain.cpp
${BENCHMARK_DIR}/StringificationBench.cpp
)
CheckFileList(BENCH_SOURCES ${BENCHMARK_DIR})
# Provide some groupings for IDEs
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES})
# configure the executable
include_directories(${HEADER_DIR})
add_definitions( -DCATCH_CONFIG_FULL_PROJECT )
# Projects consuming Catch via ExternalProject_Add might want to use install step
# without building all of our selftests.
if (NOT NO_SELFTEST)
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${HEADERS})
# Add desired warnings
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
target_compile_options( SelfTest PRIVATE -Wall -Wextra )
target_compile_options( Benchmark PRIVATE -Wall -Wextra )
endif() endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) add_subdirectory(projects)
target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX ) endif()
target_compile_options( Benchmark PRIVATE /W4 )
if(CATCH_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if(CATCH_BUILD_EXTRA_TESTS)
add_subdirectory(projects/ExtraTests)
endif()
# 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)
# Only perform the installation steps when Catch is not being used as
# a subproject via `add_subdirectory`, or the destinations will break,
# see https://github.com/catchorg/Catch2/issues/1373
if (NOT_SUBPROJECT)
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
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}
)
# By default, FooConfigVersion is tied to architecture that it was
# generated on. Because Catch2 is header-only, it is arch-independent
# and thus Catch2ConfigVersion should not be tied to the architecture
# it was generated on.
#
# CMake does not provide a direct customization point for this in
# `write_basic_package_version_file`, but it can be accomplished
# indirectly by temporarily undefining `CMAKE_SIZEOF_VOID_P`.
set(CATCH2_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
unset(CMAKE_SIZEOF_VOID_P)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
COMPATIBILITY
SameMajorVersion
)
set(CMAKE_SIZEOF_VOID_P ${CATCH2_CMAKE_SIZEOF_VOID_P})
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() endif()
if(CATCH_INSTALL_HELPERS)
# Install CMake scripts
install(
FILES
"contrib/ParseAndAddCatchTests.cmake"
"contrib/Catch.cmake"
"contrib/CatchAddTests.cmake"
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# configure unit tests via CTest # Install debugger helpers
enable_testing() install(
add_test(NAME RunTests COMMAND SelfTest) FILES
"contrib/gdbinit"
"contrib/lldbinit"
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
)
endif()
add_test(NAME ListTests COMMAND SelfTest --list-tests) ## Provide some pkg-config integration
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases") 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}
)
add_test(NAME ListTags COMMAND SelfTest --list-tags) endif(NOT_SUBPROJECT)
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
endif() # !NO_SELFTEST
install(DIRECTORY "single_include/" DESTINATION "include/catch")

View File

@@ -1,17 +1,27 @@
<a id="top"></a> <a id="top"></a>
![catch logo](catch-logo-small.png) ![catch logo](artwork/catch2-logo-small.png)
[![Github Releases](https://img.shields.io/github/release/philsquared/catch.svg)](https://github.com/philsquared/catch/releases) [![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
[![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=catch2)](https://travis-ci.org/philsquared/Catch?branch=catch2) [![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/hrtk60hv6tw6fght/branch/catch2?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/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/E0msqwbW7U4PVbHn)
[![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/philsquared/Catch/releases/download/v2.0.0-develop.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.4.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!
If you've been using an earlier version of Catch, please see the
Breaking Changes section of [the release notes](https://github.com/catchorg/Catch2/releases/tag/v2.0.1)
before moving to Catch2. You might also like to read [this blog post](http://www.levelofindirection.com/journal/2017/11/3/catch2-released.html) for more details.
## What's the Catch? ## What's the Catch?
Catch stands for C++ Automated Test Cases in Headers and is a Catch2 stands for C++ Automated Test Cases in a Header and is a
multi-paradigm test framework for C++. which also supports Objective-C multi-paradigm test framework for C++. which also supports Objective-C
and, maybe, C. (and maybe C).
It is primarily distributed as a single header file, although certain It is primarily distributed as a single header file, although certain
extensions may require additional headers. extensions may require additional headers.
@@ -23,6 +33,6 @@ This documentation comprises these three parts:
* [Reference section](docs/Readme.md#top) - all the details * [Reference section](docs/Readme.md#top) - all the details
## More ## More
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues) * Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/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 Catch](docs/opensource-users.md#top) * See [who else is using Catch2](docs/opensource-users.md#top)

View File

@@ -1,6 +1,10 @@
# version string format -- This will be overwritten later anyway # version string format -- This will be overwritten later anyway
version: "{build}" version: "{build}"
branches:
except:
- /dev-travis.+/
os: os:
- Visual Studio 2017 - Visual Studio 2017
- Visual Studio 2015 - Visual Studio 2015
@@ -15,23 +19,51 @@ environment:
- additional_flags: "/D_UNICODE /DUNICODE" - additional_flags: "/D_UNICODE /DUNICODE"
wmain: 1 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: matrix:
exclude: exclude:
- - os: Visual Studio 2015
additional_flags: "/permissive- /std:c++latest" additional_flags: "/permissive- /std:c++latest"
os: Visual Studio 2015
-
additional_flags: "/permissive- /std:c++latest"
os: Visual Studio 2013
init: - os: Visual Studio 2015
- git config --global core.autocrlf input additional_flags: "/D_UNICODE /DUNICODE"
# Set build version to git commit-hash
- ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)"
# fetch repository as zip archive # Exclude unwanted coverage configurations
shallow_clone: true - 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" -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. # Win32 and x64 are CMake-compatible solution platform names.
# This allows us to pass %PLATFORM% to CMake -A. # This allows us to pass %PLATFORM% to CMake -A.
@@ -47,14 +79,18 @@ configuration:
#Cmake will autodetect the compiler, but we set the arch #Cmake will autodetect the compiler, but we set the arch
before_build: before_build:
- set CXXFLAGS=%additional_flags% - set CXXFLAGS=%additional_flags%
- cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% # Indirection because appveyor doesn't handle multiline batch scripts properly
# https://stackoverflow.com/questions/37627248/how-to-split-a-command-over-multiple-lines-in-appveyor-yml/37647169#37647169
# https://help.appveyor.com/discussions/questions/3888-multi-line-cmd-or-powershell-warning-ignore
- cmd: .\misc\appveyorBuildConfigurationScript.bat
# build with MSBuild # build with MSBuild
build: 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 parallel: true # enable MSBuild parallel builds
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed} verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
test_script: test_script:
- cd Build - set CTEST_OUTPUT_ON_FAILURE=1
- ctest -V -j 2 -C %CONFIGURATION% - cmd: .\misc\appveyorTestRunScript.bat

BIN
artwork/catch2-c-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

24
codecov.yml Normal file
View File

@@ -0,0 +1,24 @@
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,16 +1,31 @@
#!/usr/bin/env python #!/usr/bin/env python
from conans import ConanFile from conans import ConanFile, CMake
class CatchConan(ConanFile): class CatchConan(ConanFile):
name = "Catch" name = "Catch"
version = "2.0.0-develop.3" version = "2.4.1"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared" author = "philsquared"
generators = "cmake" generators = "cmake"
exports_sources = "single_include/*" # Only needed until conan 1.5 is released
url = "https://github.com/philsquared/Catch" 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" license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
def build(self):
pass
def package(self): 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()

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

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

@@ -1,7 +1,7 @@
<a id="top"></a> <a id="top"></a>
# Reference # Reference
To get the most out of Catch, start with the [tutorial](tutorial.md#top). To get the most out of Catch2, start with the [tutorial](tutorial.md#top).
Once you're up and running consider the following reference material. Once you're up and running consider the following reference material.
Writing tests: Writing tests:
@@ -12,6 +12,7 @@ Writing tests:
* [Test fixtures](test-fixtures.md#top) * [Test fixtures](test-fixtures.md#top)
* [Reporters](reporters.md#top) * [Reporters](reporters.md#top)
* [Event Listeners](event-listeners.md#top) * [Event Listeners](event-listeners.md#top)
* [Data Generators](generators.md#top)
Fine tuning: Fine tuning:
* [Supplying your own main()](own-main.md#top) * [Supplying your own main()](own-main.md#top)
@@ -20,7 +21,10 @@ Fine tuning:
Running: Running:
* [Command line](command-line.md#top) * [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: FAQ:
* [Why are my tests slow to compile?](slow-compiles.md#top) * [Why are my tests slow to compile?](slow-compiles.md#top)

View File

@@ -1,15 +1,16 @@
<a id="top"></a> <a id="top"></a>
# Assertion Macros # Assertion Macros
**Contents** **Contents**<br>
[Natural Expressions](#natural-expressions) [Natural Expressions](#natural-expressions)<br>
[Exceptions](#exceptions) [Exceptions](#exceptions)<br>
[Matcher expressions](#matcher-expressions) [Matcher expressions](#matcher-expressions)<br>
[Thread Safety](#thread-safety) [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). 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: Most of these macros come in two forms:
@@ -21,7 +22,7 @@ The ```CHECK``` family are equivalent but execution continues in the same test c
* **REQUIRE(** _expression_ **)** and * **REQUIRE(** _expression_ **)** and
* **CHECK(** _expression_ **)** * **CHECK(** _expression_ **)**
Evaluates the expression and records the result. If an exception is thrown it is caught, reported, and counted as a failure. These are the macros you will use most of the time Evaluates the expression and records the result. If an exception is thrown, it is caught, reported, and counted as a failure. These are the macros you will use most of the time.
Examples: Examples:
``` ```
@@ -54,37 +55,54 @@ 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. 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 ) ); 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`. `Approx` is constructed with defaults that should cover most simple cases.
* __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`. For the more complex cases, `Approx` provides 3 customization points:
* __scale__ - scale serves to adjust the base for comparison used by epsilon, can be used when By default set to `1.0`.
* __epsilon__ - epsilon serves to set the coefficient 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 #### epsilon example
```cpp ```cpp
Approx target = Approx(100).epsilon(0.01); Approx target = Approx(100).epsilon(0.01);
100.0 == target; // Obviously true 100.0 == target; // Obviously true
200.0 == target; // Obviously still false 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 example
_Margin check is used only if the relative (epsilon and scale based) check fails._
```cpp ```cpp
Approx target = Approx(100).margin(5); Approx target = Approx(100).margin(5);
100.0 == target; // Obviously true 100.0 == target; // Obviously true
200.0 == target; // Obviously still false 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 #### scale
Scale can be useful if the computation leading to the result worked on different scale, than is used by the results (and thus expected errors are on a different scale than would be expected based on the results alone). Scale can be useful if the computation leading to the result worked
on different scale than is used by the results. Since allowed difference
between Approx's value and compared value is based primarily on Approx's value
(the allowed difference is computed as
`(Approx::scale + Approx::value) * epsilon`), the resulting comparison could
need rescaling to be correct.
## Exceptions ## Exceptions
@@ -150,6 +168,34 @@ Matchers can be composed using `&&`, `||` and `!` operators.
Currently assertions in Catch are not thread safe. 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). 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) [Home](Readme.md#top)

View File

@@ -1,6 +1,13 @@
<a id="top"></a> <a id="top"></a>
# CI and build system integration # CI and other odd pieces
**Contents**<br>
[Continuous Integration systems](#continuous-integration-systems)<br>
[Other reporters](#other-reporters)<br>
[Low-level tools](#low-level-tools)<br>
[CMake](#cmake)<br>
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. 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 ## Continuous Integration systems
@@ -16,7 +23,7 @@ The XML Reporter writes in an XML format that is specific to Catch.
The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing. The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course. The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course.
### JUnit Reporter ### JUnit Reporter
```-r junit``` ```-r junit```
@@ -28,9 +35,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. 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
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 #define CATCH_CONFIG_MAIN
#include "catch.hpp" #include "catch.hpp"
#include "catch_reporter_teamcity.hpp" #include "catch_reporter_teamcity.hpp"
@@ -55,90 +67,42 @@ Because of the incremental nature of Catch's test suites and ability to run spec
## Low-level tools ## Low-level tools
### CMake ### Precompiled headers (PCHs)
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: Catch offers prototypal support for being included in precompiled headers, but because of its single-header nature it does need some actions by the user:
```CMake * The precompiled header needs to define `CATCH_CONFIG_ALL_PARTS`
cmake_minimum_required(VERSION 3.0) * The implementation file needs to
* undefine `TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED`
* define `CATCH_CONFIG_IMPL_ONLY`
* define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`
* include "catch.hpp" again
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 ctest 4 labels would be created, `a`, `b`, `c` and `unit`.
### CodeCoverage module (GCOV, LCOV...) ### 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 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) [Home](Readme.md#top)

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

@@ -0,0 +1,216 @@
<a id="top"></a>
# CMake integration
**Contents**<br>
[CMake target](#cmake-target)<br>
[Automatic test registration](#automatic-test-registration)<br>
[CMake project options](#cmake-project-options)<br>
[Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br>
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`.
## Installing Catch2 from git repository
If you cannot install Catch2 from a package manager (e.g. Ubuntu 16.04
provides catch only in version 1.2.0) you might want to install it from
the repository instead. Assuming you have enough rights, you can just
install it to the default location, like so:
```
$ git clone https://github.com/catchorg/Catch2.git
$ cd Catch2
$ cmake -Bbuild -H. -DBUILD_TESTING=OFF
$ sudo cmake --build build/ --target install
```
If you do not have superuser rights, you will also need to specify
[CMAKE_INSTALL_PREFIX](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html)
when configuring the build, and then modify your calls to
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html)
accordingly.
---
[Home](Readme.md#top)

View File

@@ -1,29 +1,30 @@
<a id="top"></a> <a id="top"></a>
# Command line # Command line
**Contents** **Contents**<br>
[Specifying which tests to run](#specifying-which-tests-to-run) [Specifying which tests to run](#specifying-which-tests-to-run)<br>
[Choosing a reporter to use](#choosing-a-reporter-to-use) [Choosing a reporter to use](#choosing-a-reporter-to-use)<br>
[Breaking into the debugger](#breaking-into-the-debugger) [Breaking into the debugger](#breaking-into-the-debugger)<br>
[Showing results for successful tests](#showing-results-for-successful-tests) [Showing results for successful tests](#showing-results-for-successful-tests)<br>
[Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures) [Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures)<br>
[Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters) [Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters)<br>
[Sending output to a file](#sending-output-to-a-file) [Sending output to a file](#sending-output-to-a-file)<br>
[Naming a test run](#naming-a-test-run) [Naming a test run](#naming-a-test-run)<br>
[Eliding assertions expected to throw](#eliding-assertions-expected-to-throw) [Eliding assertions expected to throw](#eliding-assertions-expected-to-throw)<br>
[Make whitespace visible](#make-whitespace-visible) [Make whitespace visible](#make-whitespace-visible)<br>
[Warnings](#warnings) [Warnings](#warnings)<br>
[Reporting timings](#reporting-timings) [Reporting timings](#reporting-timings)<br>
[Load test names to run from a file](#load-test-names-to-run-from-a-file) [Load test names to run from a file](#load-test-names-to-run-from-a-file)<br>
[Just test names](#just-test-names) [Just test names](#just-test-names)<br>
[Specify the order test cases are run](#specify-the-order-test-cases-are-run) [Specify the order test cases are run](#specify-the-order-test-cases-are-run)<br>
[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator) [Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator)<br>
[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard) [Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard)<br>
[Wait for key before continuing](#wait-for-key-before-continuing) [Wait for key before continuing](#wait-for-key-before-continuing)<br>
[Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for) [Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for)<br>
[Usage](#usage) [Usage](#usage)<br>
[Specify the section to run](#specify-the-section-to-run) [Specify the section to run](#specify-the-section-to-run)<br>
[Filenames as tags](#filenames-as-tags) [Filenames as tags](#filenames-as-tags)<br>
[Override output colouring](#override-output-colouring)<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. 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. 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="#libidentify"> ` --libidentify`</a><br />
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br /> <a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br /> <a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
<a href="#use-colour"> ` --use-colour`</a><br />
</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. 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. Inclusions and exclusions are evaluated in left-to-right order.
Test case examples: Test case examples:
@@ -94,7 +96,7 @@ a* ~ab* abc Matches all tests that start with 'a', except those that
</pre> </pre>
Names within square brackets are interpreted as tags. 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> <pre>[one][two],[three]</pre>
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]` 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 ## Breaking into the debugger
<pre>-b, --break</pre> <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> <a id="showing-results-for-successful-tests"></a>
## Showing results for successful tests ## Showing results for successful tests
@@ -192,9 +196,16 @@ This option transforms tabs and newline characters into ```\t``` and ```\n``` re
## Warnings ## Warnings
<pre>-w, --warn &lt;warning name></pre> <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> <a id="reporting-timings"></a>
## Reporting timings ## 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 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 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> <a id="usage"></a>
## Usage ## 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]`. 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

@@ -1,14 +1,21 @@
<a id="top"></a> <a id="top"></a>
# Compile-time configuration # Compile-time configuration
**Contents** **Contents**<br>
[main()/ implementation](#main-implementation) [main()/ implementation](#main-implementation)<br>
[Prefixing Catch macros](#prefixing-catch-macros) [Reporter / Listener interfaces](#reporter--listener-interfaces)<br>
[Terminal colour](#terminal-colour) [Prefixing Catch macros](#prefixing-catch-macros)<br>
[Console width](#console-width) [Terminal colour](#terminal-colour)<br>
[stdout](#stdout) [Console width](#console-width)<br>
[Other toggles](#other-toggles) [stdout](#stdout)<br>
[Windows header clutter](#windows-header-clutter) [Fallback stringifier](#fallback-stringifier)<br>
[Default reporter](#default-reporter)<br>
[C++11 toggles](#c11-toggles)<br>
[C++17 toggles](#c17-toggles)<br>
[Other toggles](#other-toggles)<br>
[Windows header clutter](#windows-header-clutter)<br>
[Enabling stringification](#enabling-stringification)<br>
[Disabling exceptions](#disabling-exceptions)<br>
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
@@ -16,14 +23,14 @@ Nonetheless there are still some occasions where finer control is needed. For th
## main()/ implementation ## main()/ implementation
CATCH_CONFIG_MAIN // Designates this as implementation file and defines main() CATCH_CONFIG_MAIN // Designates this as implementation file and defines main()
CATCH_CONFIG_RUNNER // Designates this as implementation file CATCH_CONFIG_RUNNER // Designates this as implementation file
Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*. Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*.
# Reporter / Listener interfaces ## 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. 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.
@@ -31,16 +38,16 @@ Implied by both `CATCH_CONFIG_MAIN` and `CATCH_CONFIG_RUNNER`.
## Prefixing Catch macros ## Prefixing Catch macros
CATCH_CONFIG_PREFIX_ALL CATCH_CONFIG_PREFIX_ALL
To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```). To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```).
## Terminal colour ## Terminal colour
CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring
CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used
CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used
Yes, I am English, so I will continue to spell "colour" with a 'u'. Yes, I am English, so I will continue to spell "colour" with a 'u'.
@@ -54,24 +61,81 @@ Typically you should place the ```#define``` before #including "catch.hpp" in yo
## Console width ## Console width
CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number
Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this. Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this.
By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value. By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value.
## stdout ## stdout
CATCH_CONFIG_NOSTDOUT 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& cout();
std::ostream& cerr(); std::ostream& cerr();
std::ostream& clog(); 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_CONFIG_CPP17_STRING_VIEW // Provide StringMaker specialization for std::string_view
CATCH_CONFIG_CPP17_VARIANT // Override C++17 detection for CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
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 ## Other toggles
@@ -83,6 +147,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_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
CATCH_CONFIG_DISABLE // Disables assertions and test case registration 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. 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.
@@ -90,14 +156,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. `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` ### `CATCH_CONFIG_FAST_COMPILE`
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes: This compile-time flag speeds up compilation of assertion macros by ~20%,
* 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*. by disabling the generation of assertion-local try-catch blocks for
* 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. 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` ### `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. 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.
@@ -105,7 +179,7 @@ When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matcher
_Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._ _Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._
### `CATCH_CONFIG_DISABLE_STRINGIFICATION` ### `CATCH_CONFIG_DISABLE_STRINGIFICATION`
This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#Visual Studio 2017 -- raw string literal in assert fails to compile) This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#visual-studio-2017----raw-string-literal-in-assert-fails-to-compile).
### `CATCH_CONFIG_DISABLE` ### `CATCH_CONFIG_DISABLE`
This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files. This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files.
@@ -121,6 +195,52 @@ On Windows Catch includes `windows.h`. To minimize global namespace clutter in t
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
## Enabling stringification
By default, Catch does not stringify some types from the standard library. This is done to avoid dragging in various standard library headers by default. However, Catch does contain these and can be configured to provide them, using these macros:
CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER // Provide StringMaker specialization for std::pair
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple
CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER // Provide StringMaker specialization for std::variant, std::monostate (on C++17)
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
## Disabling exceptions
By default, Catch2 uses exceptions to signal errors and to abort tests
when an assertion from the `REQUIRE` family of assertions fails. We also
provide an experimental support for disabling exceptions. Catch2 should
automatically detect when it is compiled with exceptions disabled, but
it can be forced to compile without exceptions by defining
CATCH_CONFIG_DISABLE_EXCEPTIONS
Note that when using Catch2 without exceptions, there are 2 major
limitations:
1) If there is an error that would normally be signalled by an exception,
the exception's message will instead be written to `Catch::cerr` and
`std::terminate` will be called.
2) If an assertion from the `REQUIRE` family of macros fails,
`std::terminate` will be called after the active reporter returns.
There is also a customization point for the exact behaviour of what
happens instead of exception being thrown. To use it, define
CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
and provide a definition for this function:
```cpp
namespace Catch {
[[noreturn]]
void throw_exception(std::exception const&);
}
```
--- ---
[Home](Readme.md#top) [Home](Readme.md#top)

View File

@@ -19,7 +19,7 @@ file that defines `CATCH_CONFIG_EXTERNAL_INTERFACES`.
Then register it using `CATCH_REGISTER_LISTENER`. Then register it using `CATCH_REGISTER_LISTENER`.
For example: For example ([complete source code](../examples/210-Evt-EventListeners.cpp)):
```c++ ```c++
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
@@ -44,7 +44,7 @@ _Note that you should not use any assertion macros within a Listener!_
## Events that can be hooked ## 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++ ```c++
// The whole test run, starting and ending // The whole test run, starting and ending

50
docs/generators.md Normal file
View File

@@ -0,0 +1,50 @@
<a id="top"></a>
# Data Generators
_Generators are currently considered an experimental feature and their
API can change between versions freely._
Data generators (also known as _data driven/parametrized test cases_)
let you reuse the same set of assertions across different input values.
In Catch2, this means that they respect the ordering and nesting
of the `TEST_CASE` and `SECTION` macros.
How does combining generators and test cases work might be better
explained by an example:
```cpp
TEST_CASE("Generators") {
auto i = GENERATE( range(1, 11) );
SECTION( "Some section" ) {
auto j = GENERATE( range( 11, 21 ) );
REQUIRE(i < j);
}
}
```
the assertion will be checked 100 times, because there are 10 possible
values for `i` (1, 2, ..., 10) and for each of them, there are 10 possible
values for `j` (11, 12, ..., 20).
You can also combine multiple generators by concatenation:
```cpp
static int square(int x) { return x * x; }
TEST_CASE("Generators 2") {
auto i = GENERATE(0, 1, -1, range(-20, -10), range(10, 20));
CAPTURE(i);
REQUIRE(square(i) >= 0);
}
```
This will call `square` with arguments `0`, `1`, `-1`, `-20`, ..., `-11`,
`10`, ..., `19`.
----------
Because of the experimental nature of the current Generator implementation,
we won't list all of the first-party generators in Catch2. Instead you
should look at our current usage tests in
[projects/SelfTest/UsageTests/Generators.tests.cpp](/projects/SelfTest/UsageTests/Generators.tests.cpp).
For implementing your own generators, you can look at their implementation in
[include/internal/catch_generators.hpp](/include/internal/catch_generators.hpp).

View File

@@ -1,12 +1,19 @@
<a id="top"></a> <a id="top"></a>
# Known limitations # Known limitations
Catch has some known limitations, that we are not planning to change. Some of these are caused by our desire to support C++98 compilers, some of these are caused by our desire to keep Catch crossplatform, some exist because their priority is seen as low compared to the development effort they would need and some other yet are compiler/runtime bugs. Over time, some limitations of Catch2 emerged. Some of these are due
to implementation details that cannot be easily changed, some of these
are due to lack of development resources on our part, and some of these
are due to plain old 3rd party bugs.
## Implementation limits ## Implementation limits
### Sections nested in loops ### Sections nested in loops
If you are using `SECTION`s inside loops, you have to create them with different name per loop's iteration. The recommended way to do so is to incorporate the loop's counter into section's name, like so If you are using `SECTION`s inside loops, you have to create them with
different name per loop's iteration. The recommended way to do so is to
incorporate the loop's counter into section's name, like so:
```cpp ```cpp
TEST_CASE( "Looped section" ) { TEST_CASE( "Looped section" ) {
for (char i = '0'; i < '5'; ++i) { for (char i = '0'; i < '5'; ++i) {
@@ -17,11 +24,34 @@ TEST_CASE( "Looped section" ) {
} }
``` ```
or with a `DYNAMIC_SECTION` macro (that was made for exactly this purpose):
```cpp
TEST_CASE( "Looped section" ) {
for (char i = '0'; i < '5'; ++i) {
DYNAMIC_SECTION( "Looped section " << i) {
SUCCEED( "Everything is OK" );
}
}
}
```
### Tests might be run again if last section fails
If the last section in a test fails, it might be run again. This is because
Catch2 discovers `SECTION`s dynamically, as they are about to run, and
if the last section in test case is aborted during execution (e.g. via
the `REQUIRE` family of macros), Catch2 does not know that there are no
more sections in that test case and must run the test case again.
## Features ## Features
This section outlines some missing features, what is their status and their possible workarounds. This section outlines some missing features, what is their status and their possible workarounds.
### Thread safe assertions ### 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 This means that this is ok
```cpp ```cpp
@@ -49,8 +79,8 @@ because only one thread passes the `REQUIRE` macro and this is not
REQUIRE(cnt == 16); REQUIRE(cnt == 16);
``` ```
Because C++11 provides the necessary tools to do this, we are planning
_This limitation is highly unlikely to be lifted before Catch 2 is released._ to remove this limitation in the future.
### Process isolation in a test ### 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. 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,34 +126,20 @@ with expansion:
""\" == ""\" ""\" == ""\"
``` ```
### Visual Studio 2015 -- Alignment compilation error (C2718)
### Visual Studio 2013 -- do-while loop withing range based for fails to compile (C2059) VS 2015 has a known bug, where `declval<T>` can cause compilation error
There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error if `T` has alignment requirements that it cannot meet.
```cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("Syntax error with VC12") {
for ( auto x : { 1 , 2, 3 } )
REQUIRE( x < 3.14 );
}
```
An easy workaround is possible, use braces:
```cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("No longer a syntax error with VC12") { A workaround is to explicitly specialize `Catch::is_range` for given
for ( auto x : { 1 , 2, 3 } ) { type (this avoids code path that uses `declval<T>` in a SFINAE context).
REQUIRE( x < 3.14 );
}
}
```
### Visual Studio 2003 -- Syntax error caused by improperly expanded `__LINE__` macro
Older version of Visual Studio can have trouble compiling Catch, not expanding the `__LINE__` macro properly when recompiling the test binary. This is caused by Edit and Continue being on.
A workaround is to turn off Edit and Continue when compiling the test binary. ### Visual Studio 2015 -- Wrong line number reported in debug mode
VS 2015 has a known bug where `__LINE__` macro can be improperly expanded under certain circumstances, while compiling multi-file project in Debug mode.
A workaround is to compile the binary in Release mode.
### Clang/G++ -- skipping leaf sections after an exception ### Clang/G++ -- skipping leaf sections after an exception
Some versions of `libc++` and `libstdc++` (or their runtimes) have a bug with `std::uncaught_exception()` getting stuck returning `true` after rethrow, even if there are no active exceptions. One such case is this snippet, which skipped the sections "a" and "b", when compiled against `libcxxrt` from master Some versions of `libc++` and `libstdc++` (or their runtimes) have a bug with `std::uncaught_exception()` getting stuck returning `true` after rethrow, even if there are no active exceptions. One such case is this snippet, which skipped the sections "a" and "b", when compiled against `libcxxrt` from master
@@ -144,3 +160,19 @@ TEST_CASE("b") {
``` ```
If you are seeing a problem like this, i.e. a weird test paths that trigger only under Clang with `libc++`, or only under very specific version of `libstdc++`, it is very likely you are seeing this. The only known workaround is to use a fixed version of your standard library. If you are seeing a problem like this, i.e. a weird test paths that trigger only under Clang with `libc++`, or only under very specific version of `libstdc++`, it is very likely you are seeing this. The only known workaround is to use a fixed version of your standard library.
### Clang/G++ -- `Matches` string matcher always returns false
This is a bug in `libstdc++-4.8`, where all matching methods from `<regex>` return false. Since `Matches` uses `<regex>` internally, if the underlying implementation does not work, it doesn't work either.
Workaround: Use newer version of `libstdc++`.
### libstdc++, `_GLIBCXX_DEBUG` macro and random ordering of tests
Running a Catch2 binary compiled against libstdc++ with `_GLIBCXX_DEBUG`
macro defined with `--order rand` will cause a debug check to trigger and
abort the run due to self-assignment.
[This is a known bug inside libstdc++](https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle/23691322)
Workaround: Don't use `--order rand` when compiling against debug-enabled
libstdc++.

43
docs/list-of-examples.md Normal file
View File

@@ -0,0 +1,43 @@
<a id="top"></a>
# List of examples
## Already available
- Catch main: [Catch-provided main](../examples/000-CatchMain.cpp)
- Test Case: [Single-file](../examples/010-TestCase.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)
- Report: [Catch-provided main](../examples/200-Rpt-CatchMain.cpp)
- Report: [TeamCity reporter](../examples/207-Rpt-TeamCityReporter.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)
- 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)
- Logging: [WARN - Issue warning](../examples/160-Log-Warn.cpp)
- Logging: [FAIL, FAIL_CHECK - Issue message and force failure/continue](../examples/170-Log-Fail.cpp)
- Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
- Report: [User-defined reporter](../examples/202-Rpt-UserDefinedReporter.cpp)
- Report: [Automake reporter](../examples/205-Rpt-AutomakeReporter.cpp)
- Report: [TAP reporter](../examples/206-Rpt-TapReporter.cpp)
- Report: [Multiple reporter](../examples/208-Rpt-MultipleReporters.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)
---
[Home](Readme.md#top)

View File

@@ -72,12 +72,6 @@ This would log something like:
<pre>"theAnswer := 42"</pre> <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) [Home](Readme.md#top)

View File

@@ -36,10 +36,41 @@ REQUIRE_THAT( str,
``` ```
## Built in matchers ## Built in matchers
Currently Catch has some string matchers and some vector matchers. They are in the `Catch::Matchers` and `Catch` namespaces. Catch currently provides some matchers, they are in the `Catch::Matchers` and `Catch` namespaces.
The string matchers are `StartsWith`, `EndsWith`, `Contains` and `Equals`. Each of them also takes an optional second argument, that decides case sensitivity (by-default, they are case sensitive).
### String matchers
The string matchers are `StartsWith`, `EndsWith`, `Contains`, `Equals` and `Matches`. The first four match a literal (sub)string against a result, while `Matches` takes and matches an ECMAScript regex. Do note that `Matches` matches the string as a whole, meaning that "abc" will not match against "abcd", but "abc.*" will.
Each of the provided `std::string` matchers also takes an optional second argument, that decides case sensitivity (by-default, they are case sensitive).
### Vector matchers
The vector matchers are `Contains`, `VectorContains` and `Equals`. `VectorContains` looks for a single element in the matched vector, `Contains` looks for a set (vector) of elements inside the matched vector. The vector matchers are `Contains`, `VectorContains` and `Equals`. `VectorContains` looks for a single element in the matched vector, `Contains` looks for a set (vector) of elements inside the matched vector.
### Floating point matchers
The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts floating point numbers that are within a certain margin of target. `WithinULP` performs an [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place)-based comparison of two floating point numbers and accepts them if they are less than certain number of ULPs apart.
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 ## Custom matchers
It's easy to provide your own matchers to extend Catch or just to work with your own types. 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> <a id="top"></a>
# Open Source projects using Catch # Open Source projects using Catch
Catch is great for open source. With it's [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? it's easy to just drop the header into your project and start writing tests - what's not to like?
As a result Catch is now being used in many Open Source projects, including some quite well known ones. As a result Catch is now being used in many Open Source projects, including some quite well known ones.
This page is an attempt to track those projects. Obviously it can never be complete. 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 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). [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. 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. 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. 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 ## 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 Boost Asio style bindings for ZeroMQ
### [ChakraCore](https://github.com/Microsoft/ChakraCore) ### [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) ### [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 A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
@@ -30,13 +30,28 @@ A, header-only, embedded scripting language designed from the ground up to direc
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings. A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core) ### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
The next-generation core storage and query engine for Couchbase Lite/ 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)
Template Library of Tree Data Structures
### [Fuxedo](https://github.com/fuxedo/fuxedo)
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
### [Inja](https://github.com/pantor/inja)
A header-only template engine for modern C++.
### [JSON for Modern C++](https://github.com/nlohmann/json) ### [JSON for Modern C++](https://github.com/nlohmann/json)
A, single-header, JSON parsing library that takes advantage of what C++ has to offer. 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) ### [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 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.
### [nanodbc](https://github.com/lexicalunit/nanodbc/) ### [nanodbc](https://github.com/lexicalunit/nanodbc/)
A small C++ library wrapper for the native C ODBC API. A small C++ library wrapper for the native C ODBC API.
@@ -56,6 +71,9 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp) ### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
A library of algorithms for values-distributed-in-time A library of algorithms for values-distributed-in-time
### [thor](https://github.com/xorz57/thor)
Wrapper Library for CUDA
### [TextFlowCpp](https://github.com/philsquared/textflowcpp) ### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
A small, single-header-only, library for wrapping and composing columns of text A small, single-header-only, library for wrapping and composing columns of text
@@ -79,6 +97,9 @@ MAME originally stood for Multiple Arcade Machine Emulator
### [Newsbeuter](https://github.com/akrennmair/newsbeuter) ### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
Newsbeuter is an open-source RSS/Atom feed reader for text terminals. 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](https://github.com/foonathan/standardese)
Standardese aims to be a nextgen Doxygen Standardese aims to be a nextgen Doxygen

View File

@@ -1,6 +1,12 @@
<a id="top"></a> <a id="top"></a>
# Supplying main() yourself # Supplying main() yourself
**Contents**<br>
[Let Catch take full control of args and config](#let-catch-take-full-control-of-args-and-config)<br>
[Amending the config](#amending-the-config)<br>
[Adding your own command line options](#adding-your-own-command-line-options)<br>
[Version detection](#version-detection)<br>
The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line. The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line.
This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file. This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file.
@@ -30,7 +36,7 @@ int main( int argc, char* argv[] ) {
## Amending the config ## 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++ ```c++
#define CATCH_CONFIG_RUNNER #define CATCH_CONFIG_RUNNER
@@ -39,34 +45,20 @@ If you still want Catch to process the command line, but you want to programatic
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
Catch::Session session; // There must be exactly one instance Catch::Session session; // There must be exactly one instance
// writing to session.configData() here sets defaults // writing to session.configData() here sets defaults
// this is the preferred way to set them // this is the preferred way to set them
// Verify that all tests, aliases, etc registered properly
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
if ( !exceptions.empty() ) {
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
std::rethrow_exception(ex_ptr);
} catch (std::exception const& ex) {
Catch::cerr() << ex.what();
}
}
// Indicate that an error occured before main
return 1;
}
int returnCode = session.applyCommandLine( argc, argv ); int returnCode = session.applyCommandLine( argc, argv );
if( returnCode != 0 ) // Indicates a command line error if( returnCode != 0 ) // Indicates a command line error
return returnCode; return returnCode;
// writing to session.configData() or session.Config() here // writing to session.configData() or session.Config() here
// overrides command line args // overrides command line args
// only do this if you know you need to // only do this if you know you need to
int numFailed = session.run(); int numFailed = session.run();
// numFailed is clamped to 255 as some unices only use the lower 8 bits. // numFailed is clamped to 255 as some unices only use the lower 8 bits.
// This clamping has already been applied, so just return it here // This clamping has already been applied, so just return it here
// You can also do any post run clean-up here // You can also do any post run clean-up here
@@ -80,7 +72,59 @@ To take full control of the config simply omit the call to ```applyCommandLine()
## Adding your own command line options ## Adding your own command line options
Catch embeds a powerful command line parser which you can also use to parse your own options out. This capability is still in active development but will be documented here when it is ready. Catch embeds a powerful command line parser called [Clara](https://github.com/philsquared/Clara).
As of Catch2 (and Clara 1.0) Clara allows you to write _composable_ option and argument parsers,
so extending Catch's own command line options is now easy.
```c++
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
int main( int argc, char* argv[] )
{
Catch::Session session; // There must be exactly one instance
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
["-g"]["--height"] // the option names it will respond to
("how high?"); // description string for the help output
// Now pass the new composite back to Catch so it uses that
session.cli( cli );
// Let Catch (using Clara) parse the command line
int returnCode = session.applyCommandLine( argc, argv );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
// if set on the command line then 'height' is now set at this point
if( height > 0 )
std::cout << "height: " << height << std::endl;
return session.run();
}
```
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.
--- ---

View File

@@ -1,7 +1,271 @@
<a id="top"></a> <a id="top"></a>
# 2.0.0 (in progress)
## Breaking changes # Release notes
**Contents**<br>
[2.4.1](#241)<br>
[2.4.0](#240)<br>
[2.3.0](#230)<br>
[2.2.3](#223)<br>
[2.2.2](#222)<br>
[2.2.1](#221)<br>
[2.2.0](#220)<br>
[2.1.2](#212)<br>
[2.1.1](#211)<br>
[2.1.0](#210)<br>
[2.0.1](#201)<br>
[Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br>
## 2.4.1
### Improvements
* Added a StringMaker for `std::(w)string_view` (#1375, #1376)
* Added a StringMaker for `std::variant` (#1380)
* This one is disabled by default to avoid increased compile-time drag
* Added detection for cygwin environment without `std::to_string` (#1396, #1397)
### Fixes
* `UnorderedEqualsMatcher` will no longer accept erroneously accept
vectors that share suffix, but are not permutation of the desired vector
* Abort after (`-x N`) can no longer be overshot by nested `REQUIRES` and
subsequently ignored (#1391, #1392)
## 2.4.0
**This release brings two new experimental features, generator support
and a `-fno-exceptions` support. Being experimental means that they
will not be subject to the usual stability guarantees provided by semver.**
### Improvements
* Various small runtime performance improvements
* `CAPTURE` macro is now variadic
* Added `AND_GIVEN` macro (#1360)
* Added experimental support for data generators
* See [their documentation](generators.md) for details
* Added support for compiling and running Catch without exceptions
* Doing so limits the functionality somewhat
* Look [into the documentation](configuration.md#disablingexceptions) for details
### Fixes
* Suppressed `-Wnon-virtual-dtor` warnings in Matchers (#1357)
* Suppressed `-Wunreachable-code` warnings in floating point matchers (#1350)
### CMake
* It is now possible to override which Python is used to run Catch's tests (#1365)
* Catch now provides infrastructure for adding tests that check compile-time configuration
* Catch no longer tries to install itself when used as a subproject (#1373)
* Catch2ConfigVersion.cmake is now generated as arch-independent (#1368)
* This means that installing Catch from 32-bit machine and copying it to 64-bit one works
* This fixes conan installation of Catch
## 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
* Various performance improvements
* On top of the performance regression fixes
* Experimental support for PCH was added (#1061)
* `CATCH_CONFIG_EXTERNAL_INTERFACES` now brings in declarations of Console, Compact, XML and JUnit reporters
* `MatcherBase` no longer has a pointless second template argument
* Reduced the number of warning suppressions that leak into user's code
* Bugs in g++ 4.x and 5.x mean that some of them have to be left in
### Fixes
* Fixed performance regression from Catch classic
* One of the performance improvement patches for Catch classic was not applied to Catch2
* Fixed platform detection for iOS (#1084)
* Fixed compilation when `g++` is used together with `libc++` (#1110)
* Fixed TeamCity reporter compilation with the single header version
* To fix the underlying issue we will be versioning reporters in single_include folder per release
* The XML reporter will now report `WARN` messages even when not used with `-s`
* Fixed compilation when `VectorContains` matcher was combined using `&&` (#1092)
* Fixed test duration overflowing after 10 seconds (#1125, #1129)
* Fixed `std::uncaught_exception` deprecation warning (#1124)
### New features
* New Matchers
* Regex matcher for strings, `Matches`.
* Set-equal matcher for vectors, `UnorderedEquals`
* Floating point matchers, `WithinAbs` and `WithinULP`.
* Stringification now attempts to decompose all containers (#606)
* Containers are objects that respond to ADL `begin(T)` and `end(T)`.
### Other changes
* Reporters will now be versioned in the `single_include` folder to ensure their compatibility with the last released version
## 2.0.1
### Breaking changes
* Removed C++98 support * Removed C++98 support
* Removed legacy reporter support * Removed legacy reporter support
* Removed legacy generator support * Removed legacy generator support
@@ -17,13 +281,26 @@
* `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type. * `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type.
* `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions * `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions
* This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section. * This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section.
* Removed deprecated matcher utility functions `Not`, `AllOf` and `AnyOf`.
* They are superseded by operators `!`, `&&` and `||`, which are natural and do not have limited arity
* Removed support for non-const comparison operators
* Non-const comparison operators are an abomination that should not exist
* They were breaking support for comparing function to function pointer
* `std::pair` and `std::tuple` are no longer stringified by default
* This is done to avoid dragging in `<tuple>` and `<utility>` headers in common path
* Their stringification can be enabled per-file via new configuration macros
* `Approx` is subtly different and hopefully behaves more as users would expect
* `Approx::scale` defaults to `0.0`
* `Approx::epsilon` no longer applies to the larger of the two compared values, but only to the `Approx`'s value
* `INFINITY == Approx(INFINITY)` returns true
## Improvements
### Improvements
* Reporters and Listeners can be defined in files different from the main file * Reporters and Listeners can be defined in files different from the main file
* The file has to define `CATCH_CONFIG_EXTERNAL_INTERFACES` before including catch.hpp. * The file has to define `CATCH_CONFIG_EXTERNAL_INTERFACES` before including catch.hpp.
* Errors that happen during set up before main are now caught and properly reported once main is entered * Errors that happen during set up before main are now caught and properly reported once main is entered
* If you are providing your own main, you can access and use these as well. * If you are providing your own main, you can access and use these as well.
* New assertion macros, *_THROWS_WITH(expr, exception_type, matcher) are provided * New assertion macros, *_THROWS_MATCHES(expr, exception_type, matcher) are provided
* As the arguments suggest, these allow you to assert that an expression throws desired type of exception and pass the exception to a matcher. * As the arguments suggest, these allow you to assert that an expression throws desired type of exception and pass the exception to a matcher.
* JUnit reporter no longer has significantly different output for test cases with and without sections * JUnit reporter no longer has significantly different output for test cases with and without sections
* Most assertions now support expressions containing commas (ie `REQUIRE(foo() == std::vector<int>{1, 2, 3});`) * Most assertions now support expressions containing commas (ie `REQUIRE(foo() == std::vector<int>{1, 2, 3});`)
@@ -36,16 +313,35 @@
* All parts of matchers can be removed from a TU by defining `CATCH_CONFIG_DISABLE_MATCHERS` * All parts of matchers can be removed from a TU by defining `CATCH_CONFIG_DISABLE_MATCHERS`
* This can be used to somewhat speed up compilation times * This can be used to somewhat speed up compilation times
* An experimental implementation of `CATCH_CONFIG_DISABLE` has been added * An experimental implementation of `CATCH_CONFIG_DISABLE` has been added
* Speeds up compilation by removing away Catch tests * Inspired by Doctest's `DOCTEST_CONFIG_DISABLE`
* Currently removes all assertions and prevents `TEST_CASE` registrations
* Useful for implementing tests in source files * Useful for implementing tests in source files
* ie for functions in anonymous namespaces * ie for functions in anonymous namespaces
* Inspired by Doctest's `DOCTEST_CONFIG_DISABLE` * Removes all assertions
* Prevents `TEST_CASE` registrations
## Fixes * Exception translators are not registered
* Reporters are not registered
* Listeners are not registered
* Reporters/Listeners are now notified of fatal errors
* This means specific signals or structured exceptions
* The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility
* Stringification of `std::chrono::duration` and `std::chrono::time_point` is now supported
* Needs to be enabled by a per-file compile time configuration option
* Add `pkg-config` support to CMake install command
## Internal changes ### Fixes
* Don't use console colour if running in XCode
* Explicit constructor in reporter base class
* Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings
* Compilation for Universal Windows Platform (UWP) is supported
* SEH handling and colorized output are disabled when compiling for UWP
* Implemented a workaround for `std::uncaught_exception` issues in libcxxrt
* These issues caused incorrect section traversals
* The workaround is only partial, user's test can still trigger the issue by using `throw;` to rethrow an exception
* Suppressed C4061 warning under MSVC
### Internal changes
* The development version now uses .cpp files instead of header files containing implementation. * The development version now uses .cpp files instead of header files containing implementation.
* This makes partial rebuilds much faster during development * This makes partial rebuilds much faster during development
* The expression decomposition layer has been rewritten * The expression decomposition layer has been rewritten
@@ -53,23 +349,77 @@
* New library (TextFlow) is used for formatting text to output * New library (TextFlow) is used for formatting text to output
## Older versions
# Older versions ### 1.12.x
## 1.9.x #### 1.12.2
##### Fixes
* Fixed missing <cassert> include
### 1.9.6 #### 1.12.1
#### Improvements ##### Fixes
* Fixed deprecation warning in `ScopedMessage::~ScopedMessage`
* All uses of `min` or `max` identifiers are now wrapped in parentheses
* This avoids problems when Windows headers define `min` and `max` macros
#### 1.12.0
##### Fixes
* Fixed compilation for strict C++98 mode (ie not gnu++98) and older compilers (#1103)
* `INFO` messages are included in the `xml` reporter output even without `-s` specified.
### 1.11.x
#### 1.11.0
##### Fixes
* The original expression in `REQUIRE_FALSE( expr )` is now reporter properly as `!( expr )` (#1051)
* Previously the parentheses were missing and `x != y` would be expanded as `!x != x`
* `Approx::Margin` is now inclusive (#952)
* Previously it was meant and documented as inclusive, but the check itself wasn't
* This means that `REQUIRE( 0.25f == Approx( 0.0f ).margin( 0.25f ) )` passes, instead of fails
* `RandomNumberGenerator::result_type` is now unsigned (#1050)
##### Improvements
* `__JETBRAINS_IDE__` macro handling is now CLion version specific (#1017)
* When CLion 2017.3 or newer is detected, `__COUNTER__` is used instead of
* TeamCity reporter now explicitly flushes output stream after each report (#1057)
* On some platforms, output from redirected streams would show up only after the tests finished running
* `ParseAndAddCatchTests` now can add test files as dependency to CMake configuration
* This means you do not have to manually rerun CMake configuration step to detect new tests
### 1.10.x
#### 1.10.0
##### Fixes
* Evaluation layer has been rewritten (backported from Catch 2)
* The new layer is much simpler and fixes some issues (#981)
* Implemented workaround for VS 2017 raw string literal stringification bug (#995)
* Fixed interaction between `[!shouldfail]` and `[!mayfail]` tags and sections
* Previously sections with failing assertions would be marked as failed, not failed-but-ok
##### Improvements
* Added [libidentify](https://github.com/janwilmans/LibIdentify) support
* Added "wait-for-keypress" option
### 1.9.x
#### 1.9.6
##### Improvements
* Catch's runtime overhead has been significantly decreased (#937, #939) * Catch's runtime overhead has been significantly decreased (#937, #939)
* Added `--list-extra-info` cli option (#934). * Added `--list-extra-info` cli option (#934).
* It lists all tests together with extra information, ie filename, line number and description. * It lists all tests together with extra information, ie filename, line number and description.
### 1.9.5 #### 1.9.5
#### Fixes ##### Fixes
* Truthy expressions are now reconstructed properly, not as booleans (#914) * Truthy expressions are now reconstructed properly, not as booleans (#914)
* Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871) * Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871)
* Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855) * Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855)
@@ -77,35 +427,35 @@
* Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`. * Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`.
* Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927) * Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927)
#### Improvements ##### Improvements
* CMake integration script now incorporates debug messages and registers tests in an improved way (#911) * CMake integration script now incorporates debug messages and registers tests in an improved way (#911)
* Various documentation improvements * Various documentation improvements
### 1.9.4 #### 1.9.4
#### Fixes ##### Fixes
* `CATCH_FAIL` macro no longer causes compilation error without variadic macro support * `CATCH_FAIL` macro no longer causes compilation error without variadic macro support
* `INFO` messages are no longer cleared after being reported once * `INFO` messages are no longer cleared after being reported once
#### Improvements and minor changes ##### Improvements and minor changes
* Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined. * Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined.
* Note that Catch still officially supports only ASCII * Note that Catch still officially supports only ASCII
### 1.9.3 #### 1.9.3
#### Fixes ##### Fixes
* Completed the fix for (lack of) uint64_t in earlier Visual Studios * Completed the fix for (lack of) uint64_t in earlier Visual Studios
### 1.9.2 #### 1.9.2
#### Improvements and minor changes ##### Improvements and minor changes
* All of `Approx`'s member functions now accept strong typedefs in C++11 mode (#888) * All of `Approx`'s member functions now accept strong typedefs in C++11 mode (#888)
* Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't. * Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't.
#### Fixes ##### Fixes
* POSIX signals are now disabled by default under QNX (#889) * POSIX signals are now disabled by default under QNX (#889)
* QNX does not support current enough (2001) POSIX specification * QNX does not support current enough (2001) POSIX specification
* JUnit no longer counts exceptions as failures if given test case is marked as ok to fail. * JUnit no longer counts exceptions as failures if given test case is marked as ok to fail.
@@ -113,22 +463,22 @@
* Catch no longer attempts to define `uint64_t` on windows (#862) * Catch no longer attempts to define `uint64_t` on windows (#862)
* This was causing trouble when compiled under Cygwin * This was causing trouble when compiled under Cygwin
#### Other ##### Other
* Catch is now compiled under MSVC 2017 using `std:c++latest` (C++17 mode) in CI * Catch is now compiled under MSVC 2017 using `std:c++latest` (C++17 mode) in CI
* We now provide cmake script that autoregisters Catch tests into ctest. * We now provide cmake script that autoregisters Catch tests into ctest.
* See `contrib` folder. * See `contrib` folder.
### 1.9.1 #### 1.9.1
#### Fixes ##### Fixes
* Unexpected exceptions are no longer ignored by default (#885, #887) * Unexpected exceptions are no longer ignored by default (#885, #887)
### 1.9.0 #### 1.9.0
#### Improvements and minor changes ##### Improvements and minor changes
* Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference. * Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference.
* It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions * It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions
* This actually reverts changes made in v1.7.2 * This actually reverts changes made in v1.7.2
@@ -142,7 +492,7 @@
* When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`. * When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`.
* Captured messages are now printed on unexpected exceptions * Captured messages are now printed on unexpected exceptions
#### Fixes: ##### Fixes:
* Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals * Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals
* GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`. * GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`.
* This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work. * This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work.
@@ -151,18 +501,18 @@
* [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check) * [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check)
#### Other notes: ##### Other notes:
* We have added VS 2017 to our CI * We have added VS 2017 to our CI
* Work on Catch 2 should start soon * Work on Catch 2 should start soon
## 1.8.x ### 1.8.x
### 1.8.2 #### 1.8.2
#### Improvements and minor changes ##### Improvements and minor changes
* TAP reporter now behaves as if `-s` was always set * TAP reporter now behaves as if `-s` was always set
* This should be more consistent with the protocol desired behaviour. * This should be more consistent with the protocol desired behaviour.
* Compact reporter now obeys `-d yes` argument (#780) * Compact reporter now obeys `-d yes` argument (#780)
@@ -176,7 +526,7 @@
* Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion. * Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion.
#### Fixes: ##### Fixes:
* Catch no longer attempts to reconstruct expression that led to a fatal error (#810) * Catch no longer attempts to reconstruct expression that led to a fatal error (#810)
* This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition. * This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition.
* Fixed (C4265) missing virtual destructor warning in Matchers (#844) * Fixed (C4265) missing virtual destructor warning in Matchers (#844)
@@ -193,21 +543,21 @@
* Regression in Objective-C bindings (Matchers) fixed (#854) * Regression in Objective-C bindings (Matchers) fixed (#854)
#### Other notes: ##### Other notes:
* We have added VS 2013 and 2015 to our CI * We have added VS 2013 and 2015 to our CI
* Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser). * Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser).
### 1.8.1 #### 1.8.1
#### Fixes ##### Fixes
Cygwin issue with `gettimeofday` - `#define` was not early enough Cygwin issue with `gettimeofday` - `#define` was not early enough
### 1.8.0 #### 1.8.0
#### New features/ minor changes ##### New features/ minor changes
* Matchers have new, simpler (and documented) interface. * Matchers have new, simpler (and documented) interface.
* Catch provides string and vector matchers. * Catch provides string and vector matchers.
@@ -227,33 +577,33 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
* `Approx` now supports an optional margin of absolute error * `Approx` now supports an optional margin of absolute error
* It has also received [new documentation](assertions.md#top). * It has also received [new documentation](assertions.md#top).
#### Fixes ##### Fixes
* Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer. * Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer.
* Fixed C4512 ("assignment operator could not be generated") warnings under VS2013. * Fixed C4512 ("assignment operator could not be generated") warnings under VS2013.
* Cygwin compatibility fixes * Cygwin compatibility fixes
* Signal handling is no longer compiled by default. * Signal handling is no longer compiled by default.
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors. * Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
* Improved `-Wparentheses` supression for gcc (#674) * Improved `-Wparentheses` suppression for gcc (#674)
* When compiled with gcc 4.8 or newer, the supression is localized to assertions only * When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
* Otherwise it is supressed for the whole TU * Otherwise it is supressed for the whole TU
* Fixed test spec parser issue (with escapes in multiple names) * Fixed test spec parser issue (with escapes in multiple names)
#### Other ##### Other
* Various documentation fixes and improvements * Various documentation fixes and improvements
## 1.7.x ### 1.7.x
### 1.7.2 #### 1.7.2
#### Fixes and minor improvements ##### Fixes and minor improvements
Xml: Xml:
(technically the first two are breaking changes but are also fixes and arguably break few if any people) (technically the first two are breaking changes but are also fixes and arguably break few if any people)
* C-escape control characters instead of XML encoding them (which requires XML 1.1) * C-escape control characters instead of XML encoding them (which requires XML 1.1)
* Revert XML output to XML 1.0 * Revert XML output to XML 1.0
* Can provide stylesheet references by extending the XML reporter * 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 * Tags are closed and the stream flushed more eagerly to avoid stdout interpolation
@@ -265,9 +615,9 @@ Other:
* Silenced a few more warnings in different circumstances * Silenced a few more warnings in different circumstances
* Travis improvements * Travis improvements
### 1.7.1 #### 1.7.1
#### Fixes: ##### Fixes:
* Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`. * Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`.
* Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC. * Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC.
* For specifics, look into the [documentation](configuration.md#top). * For specifics, look into the [documentation](configuration.md#top).
@@ -277,9 +627,9 @@ Other:
* Fixed possible infinite recursion in Windows SEH. * Fixed possible infinite recursion in Windows SEH.
* Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators. * Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators.
### 1.7.0 #### 1.7.0
#### Features/ Changes: ##### Features/ Changes:
* Catch now runs significantly faster for passing tests * Catch now runs significantly faster for passing tests
* Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s. * Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s.
* Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s. * Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s.
@@ -293,30 +643,30 @@ Other:
* Certain characters (space, tab, etc) are now pretty printed. * Certain characters (space, tab, etc) are now pretty printed.
* This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`. * This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`.
#### Fixes: ##### Fixes:
* Text formatting no longer attempts to access out-of-bounds characters under certain conditions. * Text formatting no longer attempts to access out-of-bounds characters under certain conditions.
* THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast. * THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast.
* Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined. * Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined.
* Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro. * Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro.
#### Other: ##### Other:
* Catch's CMakeLists now defines install command. * Catch's CMakeLists now defines install command.
* Catch's CMakeLists now generates projects with warnings enabled. * Catch's CMakeLists now generates projects with warnings enabled.
## 1.6.x ### 1.6.x
### 1.6.1 #### 1.6.1
#### Features/ Changes: ##### Features/ Changes:
* Catch now supports breaking into debugger on Linux * Catch now supports breaking into debugger on Linux
#### Fixes: ##### Fixes:
* Generators no longer leak memory (generators are still unsupported in general) * Generators no longer leak memory (generators are still unsupported in general)
* JUnit reporter now reports UTC timestamps, instead of "tbd" * JUnit reporter now reports UTC timestamps, instead of "tbd"
* `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros * `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros
#### Other: ##### Other:
* Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro. * Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
* The use of `__COUNTER__` is supressed when Catch is parsed by CLion * The use of `__COUNTER__` is supressed when Catch is parsed by CLion
* This change is not active when compiling a binary * This change is not active when compiling a binary
@@ -326,28 +676,28 @@ Other:
* This can be disabled if needed, see [documentation](configuration.md#top) for details. * This can be disabled if needed, see [documentation](configuration.md#top) for details.
### 1.6.0 #### 1.6.0
#### Cmake/ projects: ##### Cmake/ projects:
* Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects. * Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects.
#### Features/ Changes: ##### Features/ Changes:
* Approx now supports `>=` and `<=` * Approx now supports `>=` and `<=`
* Can now use `\` to escape chars in test names on command line * Can now use `\` to escape chars in test names on command line
* Standardize C++11 feature toggles * Standardize C++11 feature toggles
#### Fixes: ##### Fixes:
* Blue shell colour * Blue shell colour
* Missing argument to `CATCH_CHECK_THROWS` * Missing argument to `CATCH_CHECK_THROWS`
* Don't encode extended ASCII in XML * Don't encode extended ASCII in XML
* use `std::shuffle` on more compilers (fixes deprecation warning/error) * use `std::shuffle` on more compilers (fixes deprecation warning/error)
* Use `__COUNTER__` more consistently (where available) * Use `__COUNTER__` more consistently (where available)
#### Other: ##### Other:
* Tweaks and changes to scripts - particularly for Approval test - to make them more portable * Tweaks and changes to scripts - particularly for Approval test - to make them more portable
# Even Older versions ## Even Older versions
Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
--- ---

View File

@@ -1,11 +1,11 @@
<a id="top"></a> <a id="top"></a>
# How to release # 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 ### 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. 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.
This will take care of generating the single include header, updating
### Generate updated single-include header version numbers everywhere and pushing the new version to Wandbox.
After updating version number, regenerate single-include header using `generateSingleHeader.py`.
### Release notes ### Release notes
@@ -39,26 +37,17 @@ After version number is incremented, single-include header is regenerated and re
### Release on GitHub ### 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 ## 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. Because Catch's [vcpkg](https://github.com/Microsoft/vcpkg) port updates
itself automagically, there are no optional steps at this time.
### 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.

View File

@@ -25,8 +25,8 @@ Because of the way the junit format is structured the run must complete before a
There are a few additional reporters, for specific build systems, in the Catch repository (in `include\reporters`) which you can `#include` in your project if you would like to make use of them. There are a few additional reporters, for specific build systems, in the Catch repository (in `include\reporters`) which you can `#include` in your project if you would like to make use of them.
Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`. Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`.
* `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands. * `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands.
Use this when building as part of a TeamCity build to see results as they happen. Use this when building as part of a TeamCity build to see results as they happen ([code example](../examples/207-Rpt-TeamCityReporter.cpp)).
* `tap` writes in the TAP ([Test Anything Protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol)) format. * `tap` writes in the TAP ([Test Anything Protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol)) format.
* `automake` writes in a format that correspond to [automake .trs](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html) files * `automake` writes in a format that correspond to [automake .trs](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html) files

View File

@@ -1,11 +1,11 @@
<a id="top"></a> <a id="top"></a>
# Why do my tests take so long to compile? # Why do my tests take so long to compile?
**Contents** **Contents**<br>
[Short answer](#short-answer) [Short answer](#short-answer)<br>
[Long answer](#long-answer) [Long answer](#long-answer)<br>
[Practical example](#practical-example) [Practical example](#practical-example)<br>
[Other possible solutions](#other-possible-solutions) [Other possible solutions](#other-possible-solutions)<br>
Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that?

View File

@@ -20,10 +20,10 @@ Tags allow an arbitrary number of additional strings to be associated with a tes
As an example - given the following test cases: As an example - given the following test cases:
TEST_CASE( "A", "[widget]" ) { /* ... */ } TEST_CASE( "A", "[widget]" ) { /* ... */ }
TEST_CASE( "B", "[widget]" ) { /* ... */ } TEST_CASE( "B", "[widget]" ) { /* ... */ }
TEST_CASE( "C", "[gadget]" ) { /* ... */ } TEST_CASE( "C", "[gadget]" ) { /* ... */ }
TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ } TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ }
The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects C & D. ```"[widget][gadget]"``` selects just D and ```"[widget],[gadget]"``` selects all four test cases. The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects C & D. ```"[widget][gadget]"``` selects just D and ```"[widget],[gadget]"``` selects all four test cases.
@@ -37,15 +37,15 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
* `[!hide]` or `[.]` - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them. * `[!hide]` or `[.]` - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them.
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`. * `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests. * `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
* `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes. * `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes.
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers. * `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`. * `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
* `[@<alias>]` - tag aliases all begin with `@` (see below). * `[@<alias>]` - tag aliases all begin with `@` (see below).
@@ -53,13 +53,13 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
## Tag aliases ## Tag aliases
Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form: Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. This can be done, in code, using the following form:
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> ) CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
Aliases must begin with the `@` character. An example of a tag alias is: Aliases must begin with the `@` character. An example of a tag alias is:
CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
Now when `[@nhf]` is used on the command line this matches all tests that are tagged `[failing]`, but which are not also hidden. Now when `[@nhf]` is used on the command line this matches all tests that are tagged `[failing]`, but which are not also hidden.

View File

@@ -1,6 +1,12 @@
<a id="top"></a> <a id="top"></a>
# String conversions # String conversions
**Contents**<br>
[operator << overload for std::ostream](#operator--overload-for-stdostream)<br>
[Catch::StringMaker specialisation](#catchstringmaker-specialisation)<br>
[Catch::is_range specialisation](#catchis_range-specialisation)<br>
[Exceptions](#exceptions)<br>
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
@@ -10,8 +16,8 @@ This is the standard way of providing string conversions in C++ - and the chance
``` ```
std::ostream& operator << ( std::ostream& os, T const& value ) { std::ostream& operator << ( std::ostream& os, T const& value ) {
os << convertMyTypeToString( value ); os << convertMyTypeToString( value );
return os; return os;
} }
``` ```
@@ -19,27 +25,44 @@ std::ostream& operator << ( std::ostream& os, T const& value ) {
You should put this function in the same namespace as your type and have it declared before including Catch's header. You should put this function in the same namespace as your type and have it declared before including Catch's header.
## Catch::StringMaker<T> specialisation ## Catch::StringMaker specialisation
If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide a specialization for `Catch::StringMaker<T>`: If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide a specialization for `Catch::StringMaker<T>`:
``` ```
namespace Catch { namespace Catch {
template<> template<>
struct StringMaker<T> { struct StringMaker<T> {
static std::string convert( T const& value ) { static std::string convert( T const& value ) {
return convertMyTypeToString( value ); return convertMyTypeToString( value );
} }
}; };
} }
``` ```
## Catch::is_range 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 ## 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: By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example:
``` ```
CATCH_TRANSLATE_EXCEPTION( MyType& ex ) { CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
return ex.message(); return ex.message();
} }
``` ```

View File

@@ -1,31 +1,37 @@
<a id="top"></a> <a id="top"></a>
# Tutorial # Tutorial
**Contents** **Contents**<br>
[Getting Catch](#getting-catch) [Getting Catch2](#getting-catch2)<br>
[Where to put it?](#where-to-put-it) [Where to put it?](#where-to-put-it)<br>
[Writing tests](#writing-tests) [Writing tests](#writing-tests)<br>
[Test cases and sections](#test-cases-and-sections) [Test cases and sections](#test-cases-and-sections)<br>
[BDD-Style](#bdd-style) [BDD-Style](#bdd-style)<br>
[Scaling up](#scaling-up) [Scaling up](#scaling-up)<br>
[Next steps](#next-steps) [Next steps](#next-steps)<br>
## Getting Catch ## Getting Catch2
The simplest way to get Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. The 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.
The full source for Catch, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there. Alternative ways of getting Catch2 include using your system package
manager, or installing it using [its CMake package](cmake-integration.md#installing-catch2-from-git-repository).
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.
## Where to put it? ## Where to put it?
Catch is header only. All you need to do is drop the file(s) somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html). Catch2 is header only. All you need to do is drop the file somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html).
The rest of this tutorial will assume that the Catch single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary. 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 ## Writing tests
Let's start with a really simple example. Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now). 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).
```c++ ```c++
unsigned int Factorial( unsigned int number ) { unsigned int Factorial( unsigned int number ) {
@@ -33,7 +39,7 @@ unsigned int Factorial( unsigned int number ) {
} }
``` ```
To keep things simple we'll put everything in a single file (<a href="#scaling-up">see later for more on how to structure your test files</a>) To keep things simple we'll put everything in a single file (<a href="#scaling-up">see later for more on how to structure your test files</a>).
```c++ ```c++
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
@@ -110,7 +116,7 @@ Most test frameworks have a class-based fixture mechanism. That is, test cases m
While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>). While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>).
Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example: Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example ([code](../examples/100-Fix-Section.cpp)):
```c++ ```c++
TEST_CASE( "vectors can be sized and resized", "[vector]" ) { TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
@@ -175,7 +181,7 @@ Sections can be nested to an arbitrary depth (limited only by your stack size).
If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively. For more details see [Test cases and sections](test-cases-and-sections.md#top). If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively. For more details see [Test cases and sections](test-cases-and-sections.md#top).
The vector example can be adjusted to use these macros like so: The vector example can be adjusted to use these macros like so ([example code](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)):
```c++ ```c++
SCENARIO( "vectors can be sized and resized", "[vector]" ) { SCENARIO( "vectors can be sized and resized", "[vector]" ) {
@@ -245,7 +251,7 @@ The requirement is that the following block of code ([or equivalent](own-main.md
appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```! appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```!
In fact it is usually a good idea to put the block with the ```#define``` [in its own source file](slow-compiles.md#top). In fact it is usually a good idea to put the block with the ```#define``` [in its own source file](slow-compiles.md#top) (code example [main](../examples/020-TestCase-1.cpp), [tests](../examples/020-TestCase-2.cpp)).
Do not write your tests in header files! Do not write your tests in header files!

View File

@@ -0,0 +1,15 @@
// 000-CatchMain.cpp
// In a Catch project with multiple files, dedicate one file to compile the
// source code of Catch itself and reuse the resulting object file for linking.
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
// That's it
// Compile implementation of Catch for use with files that do contain tests:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -c 000-CatchMain.cpp
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% -c 000-CatchMain.cpp

36
examples/010-TestCase.cpp Normal file
View File

@@ -0,0 +1,36 @@
// 010-TestCase.cpp
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
int Factorial( int number ) {
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
// return number <= 1 ? 1 : Factorial( number - 1 ) * number; // pass
}
TEST_CASE( "Factorial of 0 is 1 (fail)", "[single-file]" ) {
REQUIRE( Factorial(0) == 1 );
}
TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" ) {
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 );
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 010-TestCase 010-TestCase.cpp && 010-TestCase --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 010-TestCase.cpp && 010-TestCase --success
// Expected compact output (all assertions):
//
// prompt> 010-TestCase --reporter compact --success
// 010-TestCase.cpp:14: failed: Factorial(0) == 1 for: 0 == 1
// 010-TestCase.cpp:18: passed: Factorial(1) == 1 for: 1 == 1
// 010-TestCase.cpp:19: passed: Factorial(2) == 2 for: 2 == 2
// 010-TestCase.cpp:20: passed: Factorial(3) == 6 for: 6 == 6
// 010-TestCase.cpp:21: passed: Factorial(10) == 3628800 for: 3628800 (0x375f00) == 3628800 (0x375f00)
// Failed 1 test case, failed 1 assertion.

View File

@@ -0,0 +1,35 @@
// 020-TestCase-1.cpp
// In a Catch project with multiple files, dedicate one file to compile the
// source code of Catch itself and reuse the resulting object file for linking.
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
TEST_CASE( "1: All test cases reside in other .cpp files (empty)", "[multi-file:1]" ) {
}
// ^^^
// Normally no TEST_CASEs in this file.
// Here just to show there are two source files via option --list-tests.
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -c 020-TestCase-1.cpp
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 020-TestCase TestCase-1.o 020-TestCase-2.cpp && 020-TestCase --success
//
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% -c 020-TestCase-1.cpp
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% -Fe020-TestCase.exe 020-TestCase-1.obj 020-TestCase-2.cpp && 020-TestCase --success
// Expected test case listing:
//
// prompt> 020-TestCase --list-tests *
// Matching test cases:
// 1: All test cases reside in other .cpp files (empty)
// [multi-file:1]
// 2: Factorial of 0 is computed (fail)
// [multi-file:2]
// 2: Factorials of 1 and higher are computed (pass)
// [multi-file:2]
// 3 matching test cases

View File

@@ -0,0 +1,33 @@
// 020-TestCase-2.cpp
// main() provided by Catch in file 020-TestCase-1.cpp.
#include <catch2/catch.hpp>
int Factorial( int number ) {
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
// return number <= 1 ? 1 : Factorial( number - 1 ) * number; // pass
}
TEST_CASE( "2: Factorial of 0 is 1 (fail)", "[multi-file:2]" ) {
REQUIRE( Factorial(0) == 1 );
}
TEST_CASE( "2: Factorials of 1 and higher are computed (pass)", "[multi-file:2]" ) {
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 );
}
// Compile: see 020-TestCase-1.cpp
// Expected compact output (all assertions):
//
// prompt> 020-TestCase --reporter compact --success
// 020-TestCase-2.cpp:13: failed: Factorial(0) == 1 for: 0 == 1
// 020-TestCase-2.cpp:17: passed: Factorial(1) == 1 for: 1 == 1
// 020-TestCase-2.cpp:18: passed: Factorial(2) == 2 for: 2 == 2
// 020-TestCase-2.cpp:19: passed: Factorial(3) == 6 for: 6 == 6
// 020-TestCase-2.cpp:20: passed: Factorial(10) == 3628800 for: 3628800 (0x375f00) == 3628800 (0x375f00)
// Failed 1 test case, failed 1 assertion.

View File

@@ -0,0 +1,74 @@
// 030-Asn-Require-Check.cpp
// Catch has two natural expression assertion macro's:
// - REQUIRE() stops at first failure.
// - CHECK() continues after failure.
// There are two variants to support decomposing negated expressions:
// - REQUIRE_FALSE() stops at first failure.
// - CHECK_FALSE() continues after failure.
// main() provided in 000-CatchMain.cpp
#include <catch2/catch.hpp>
std::string one() {
return "1";
}
TEST_CASE( "Assert that something is true (pass)", "[require]" ) {
REQUIRE( one() == "1" );
}
TEST_CASE( "Assert that something is true (fail)", "[require]" ) {
REQUIRE( one() == "x" );
}
TEST_CASE( "Assert that something is true (stop at first failure)", "[require]" ) {
WARN( "REQUIRE stops at first failure:" );
REQUIRE( one() == "x" );
REQUIRE( one() == "1" );
}
TEST_CASE( "Assert that something is true (continue after failure)", "[check]" ) {
WARN( "CHECK continues after failure:" );
CHECK( one() == "x" );
REQUIRE( one() == "1" );
}
TEST_CASE( "Assert that something is false (stops at first failure)", "[require-false]" ) {
WARN( "REQUIRE_FALSE stops at first failure:" );
REQUIRE_FALSE( one() == "1" );
REQUIRE_FALSE( one() != "1" );
}
TEST_CASE( "Assert that something is false (continue after failure)", "[check-false]" ) {
WARN( "CHECK_FALSE continues after failure:" );
CHECK_FALSE( one() == "1" );
REQUIRE_FALSE( one() != "1" );
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 030-Asn-Require-Check 030-Asn-Require-Check.cpp 000-CatchMain.o && 030-Asn-Require-Check --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 030-Asn-Require-Check.cpp 000-CatchMain.obj && 030-Asn-Require-Check --success
// Expected compact output (all assertions):
//
// prompt> 030-Asn-Require-Check.exe --reporter compact --success
// 030-Asn-Require-Check.cpp:20: passed: one() == "1" for: "1" == "1"
// 030-Asn-Require-Check.cpp:24: failed: one() == "x" for: "1" == "x"
// 030-Asn-Require-Check.cpp:28: warning: 'REQUIRE stops at first failure:'
// 030-Asn-Require-Check.cpp:30: failed: one() == "x" for: "1" == "x"
// 030-Asn-Require-Check.cpp:35: warning: 'CHECK continues after failure:'
// 030-Asn-Require-Check.cpp:37: failed: one() == "x" for: "1" == "x"
// 030-Asn-Require-Check.cpp:38: passed: one() == "1" for: "1" == "1"
// 030-Asn-Require-Check.cpp:42: warning: 'REQUIRE_FALSE stops at first failure:'
// 030-Asn-Require-Check.cpp:44: failed: !(one() == "1") for: !("1" == "1")
// 030-Asn-Require-Check.cpp:49: warning: 'CHECK_FALSE continues after failure:'
// 030-Asn-Require-Check.cpp:51: failed: !(one() == "1") for: !("1" == "1")
// 030-Asn-Require-Check.cpp:52: passed: !(one() != "1") for: !("1" != "1")
// Failed 5 test cases, failed 5 assertions.

View File

@@ -0,0 +1,69 @@
// 100-Fix-Section.cpp
// Catch has two ways to express fixtures:
// - Sections (this file)
// - Traditional class-based fixtures
// main() provided in 000-CatchMain.cpp
#include <catch2/catch.hpp>
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
// For each section, vector v is anew:
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
SECTION( "resizing bigger changes size and capacity" ) {
v.resize( 10 );
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "resizing smaller changes size but not capacity" ) {
v.resize( 0 );
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
}
SECTION( "reserving bigger changes capacity but not size" ) {
v.reserve( 10 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "reserving smaller does not change size or capacity" ) {
v.reserve( 0 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
}
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 100-Fix-Section 100-Fix-Section.cpp 000-CatchMain.o && 100-Fix-Section --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 100-Fix-Section.cpp 000-CatchMain.obj && 100-Fix-Section --success
// Expected compact output (all assertions):
//
// prompt> 100-Fix-Section.exe --reporter compact --success
// 100-Fix-Section.cpp:17: passed: v.size() == 5 for: 5 == 5
// 100-Fix-Section.cpp:18: passed: v.capacity() >= 5 for: 5 >= 5
// 100-Fix-Section.cpp:23: passed: v.size() == 10 for: 10 == 10
// 100-Fix-Section.cpp:24: passed: v.capacity() >= 10 for: 10 >= 10
// 100-Fix-Section.cpp:17: passed: v.size() == 5 for: 5 == 5
// 100-Fix-Section.cpp:18: passed: v.capacity() >= 5 for: 5 >= 5
// 100-Fix-Section.cpp:29: passed: v.size() == 0 for: 0 == 0
// 100-Fix-Section.cpp:30: passed: v.capacity() >= 5 for: 5 >= 5
// 100-Fix-Section.cpp:17: passed: v.size() == 5 for: 5 == 5
// 100-Fix-Section.cpp:18: passed: v.capacity() >= 5 for: 5 >= 5
// 100-Fix-Section.cpp:35: passed: v.size() == 5 for: 5 == 5
// 100-Fix-Section.cpp:36: passed: v.capacity() >= 10 for: 10 >= 10
// 100-Fix-Section.cpp:17: passed: v.size() == 5 for: 5 == 5
// 100-Fix-Section.cpp:18: passed: v.capacity() >= 5 for: 5 >= 5
// 100-Fix-Section.cpp:41: passed: v.size() == 5 for: 5 == 5
// 100-Fix-Section.cpp:42: passed: v.capacity() >= 5 for: 5 >= 5
// Passed 1 test case with 16 assertions.

View File

@@ -0,0 +1,63 @@
// 110-Fix-ClassFixture.cpp
// Catch has two ways to express fixtures:
// - Sections
// - Traditional class-based fixtures (this file)
// main() provided in 000-CatchMain.cpp
#include <catch2/catch.hpp>
class DBConnection
{
public:
static DBConnection createConnection( std::string const & /*dbName*/ ) {
return DBConnection();
}
bool executeSQL( std::string const & /*query*/, int const /*id*/, std::string const & arg ) {
if ( arg.length() == 0 ) {
throw std::logic_error("empty SQL query argument");
}
return true; // ok
}
};
class UniqueTestsFixture
{
protected:
UniqueTestsFixture()
: conn( DBConnection::createConnection( "myDB" ) )
{}
int getID() {
return ++uniqueID;
}
protected:
DBConnection conn;
private:
static int uniqueID;
};
int UniqueTestsFixture::uniqueID = 0;
TEST_CASE_METHOD( UniqueTestsFixture, "Create Employee/No Name", "[create]" ) {
REQUIRE_THROWS( conn.executeSQL( "INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "") );
}
TEST_CASE_METHOD( UniqueTestsFixture, "Create Employee/Normal", "[create]" ) {
REQUIRE( conn.executeSQL( "INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "Joe Bloggs" ) );
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp 000-CatchMain.o && 110-Fix-ClassFixture --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 110-Fix-ClassFixture.cpp 000-CatchMain.obj && 110-Fix-ClassFixture --success
// Expected compact output (all assertions):
//
// prompt> 110-Fix-ClassFixture.exe --reporter compact --success
// 110-Fix-ClassFixture.cpp:47: passed: conn.executeSQL( "INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "")
// 110-Fix-ClassFixture.cpp:51: passed: conn.executeSQL( "INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "Joe Bloggs" ) for: true
// Passed both 2 test cases with 2 assertions.

View File

@@ -0,0 +1,73 @@
// 120-Bdd-ScenarioGivenWhenThen.cpp
// main() provided in 000-CatchMain.cpp
#include <catch2/catch.hpp>
SCENARIO( "vectors can be sized and resized", "[vector]" ) {
GIVEN( "A vector with some items" ) {
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
WHEN( "the size is increased" ) {
v.resize( 10 );
THEN( "the size and capacity change" ) {
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
}
WHEN( "the size is reduced" ) {
v.resize( 0 );
THEN( "the size changes but not capacity" ) {
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
}
}
WHEN( "more capacity is reserved" ) {
v.reserve( 10 );
THEN( "the capacity changes but not the size" ) {
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
}
}
WHEN( "less capacity is reserved" ) {
v.reserve( 0 );
THEN( "neither size nor capacity are changed" ) {
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
}
}
}
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 120-Bdd-ScenarioGivenWhenThen 120-Bdd-ScenarioGivenWhenThen.cpp 000-CatchMain.o && 120-Bdd-ScenarioGivenWhenThen --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 120-Bdd-ScenarioGivenWhenThen.cpp 000-CatchMain.obj && 120-Bdd-ScenarioGivenWhenThen --success
// Expected compact output (all assertions):
//
// prompt> 120-Bdd-ScenarioGivenWhenThen.exe --reporter compact --success
// 120-Bdd-ScenarioGivenWhenThen.cpp:12: passed: v.size() == 5 for: 5 == 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:13: passed: v.capacity() >= 5 for: 5 >= 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:19: passed: v.size() == 10 for: 10 == 10
// 120-Bdd-ScenarioGivenWhenThen.cpp:20: passed: v.capacity() >= 10 for: 10 >= 10
// 120-Bdd-ScenarioGivenWhenThen.cpp:12: passed: v.size() == 5 for: 5 == 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:13: passed: v.capacity() >= 5 for: 5 >= 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:27: passed: v.size() == 0 for: 0 == 0
// 120-Bdd-ScenarioGivenWhenThen.cpp:28: passed: v.capacity() >= 5 for: 5 >= 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:12: passed: v.size() == 5 for: 5 == 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:13: passed: v.capacity() >= 5 for: 5 >= 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:35: passed: v.size() == 5 for: 5 == 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:36: passed: v.capacity() >= 10 for: 10 >= 10
// 120-Bdd-ScenarioGivenWhenThen.cpp:12: passed: v.size() == 5 for: 5 == 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:13: passed: v.capacity() >= 5 for: 5 >= 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:43: passed: v.size() == 5 for: 5 == 5
// 120-Bdd-ScenarioGivenWhenThen.cpp:44: passed: v.capacity() >= 5 for: 5 >= 5
// Passed 1 test case with 16 assertions.

View File

@@ -0,0 +1,27 @@
// 200-Rpt-CatchMain.cpp
// In a Catch project with multiple files, dedicate one file to compile the
// source code of Catch itself and reuse the resulting object file for linking.
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#ifdef CATCH_EXAMPLE_RPT_1
#include CATCH_EXAMPLE_RPT_1
#endif
#ifdef CATCH_EXAMPLE_RPT_2
#include CATCH_EXAMPLE_RPT_2
#endif
#ifdef CATCH_EXAMPLE_RPT_3
#include CATCH_EXAMPLE_RPT_3
#endif
// That's it
// Compile implementation of Catch for use with files that do contain tests:
// - g++ -std=c++11 -Wall -I$(CATCH_ROOT) -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -o 200-Rpt-CatchMainTeamCity.o -c 200-Rpt-CatchMain.cpp
// cl -EHsc -I%CATCH_ROOT% -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -Fo200-Rpt-CatchMainTeamCity.obj -c 200-Rpt-CatchMain.cpp

View File

@@ -0,0 +1,171 @@
// 207-Rpt-TeamCityReporter.cpp
// Catch has built-in and external reporters:
// Built-in:
// - compact
// - console
// - junit
// - xml
// External:
// - automake
// - tap
// - teamcity (this example)
// main() and reporter code provided in 200-Rpt-CatchMain.cpp
#include <catch2/catch.hpp>
#ifdef _MSC_VER
# pragma warning (disable : 4702) // Disable warning: unreachable code
#endif
TEST_CASE( "TeamCity passes unconditionally succeeding assertion", "[teamcity]" ) {
SUCCEED();
}
TEST_CASE( "TeamCity reports unconditionally failing assertion", "[teamcity]" ) {
FAIL();
}
TEST_CASE( "TeamCity reports failing check", "[teamcity]" ) {
REQUIRE( 3 == 7 );
}
TEST_CASE( "TeamCity reports failing check-false", "[teamcity]" ) {
REQUIRE_FALSE( 3 == 3 );
}
TEST_CASE( "TeamCity reports failing check-that", "[teamcity]" ) {
using namespace Catch;
REQUIRE_THAT( "hello", Contains( "world" ) );
}
TEST_CASE( "TeamCity reports unexpected exception", "[teamcity]" ) {
REQUIRE( (throw std::runtime_error("surprise!"), true) );
}
TEST_CASE( "TeamCity reports undesired exception", "[teamcity]" ) {
REQUIRE_NOTHROW( (throw std::runtime_error("surprise!"), true) );
}
TEST_CASE( "TeamCity reports missing expected exception", "[teamcity]" ) {
REQUIRE_THROWS( true );
}
TEST_CASE( "TeamCity reports missing specific expected exception", "[teamcity]" ) {
REQUIRE_THROWS_AS( throw std::bad_alloc(), std::runtime_error );
}
TEST_CASE( "TeamCity reports unexpected message in expected exception", "[teamcity]" ) {
using namespace Catch;
CHECK_THROWS_WITH( throw std::runtime_error("hello"), "world" );
CHECK_THROWS_WITH( throw std::runtime_error("hello"), Contains("world") );
}
struct MyException: public std::runtime_error
{
MyException( char const * text )
: std::runtime_error( text ) {}
~MyException() override;
};
// prevent -Wweak-vtables:
MyException::~MyException() = default;
struct MyExceptionMatcher : Catch::MatcherBase< std::runtime_error >
{
std::string m_text;
MyExceptionMatcher( char const * text )
: m_text( text )
{}
~MyExceptionMatcher() override;
bool match( std::runtime_error const & arg ) const override
{
return m_text == arg.what() ;
}
std::string describe() const override
{
return "it's me";
}
};
// prevent -Wweak-vtables:
MyExceptionMatcher::~MyExceptionMatcher() = default;
TEST_CASE( "TeamCity failing check-throws-matches", "[teamcity]" ) {
CHECK_THROWS_MATCHES( throw MyException("hello"), MyException, MyExceptionMatcher("world") );
}
// [!throws] - lets Catch know that this test is likely to throw an exception even if successful.
// This causes the test to be excluded when running with -e or --nothrow.
// No special effects for the reporter.
TEST_CASE( "TeamCity throwing exception with tag [!throws]", "[teamcity][!throws]" ) {
REQUIRE_THROWS( throw std::runtime_error("unsurprisingly") );
}
// [!mayfail] - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
TEST_CASE( "TeamCity failing assertion with tag [!mayfail]", "[teamcity][!mayfail] " ) {
REQUIRE( 3 == 7 ); // doesn't fail test case this time, reports: testIgnored
REQUIRE( 3 == 3 );
}
// [!shouldfail] - like [!mayfail] but fails the test if it passes.
// This can be useful if you want to be notified of accidental, or third-party, fixes.
TEST_CASE( "TeamCity succeeding assertion with tag [!shouldfail]", "[teamcity][!shouldfail]" ) {
SUCCEED( "Marked [!shouldfail]" );
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_ROOT) -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -o 200-Rpt-CatchMainTeamCity.o -c 200-Rpt-CatchMain.cpp
// - g++ -std=c++11 -Wall -I$(CATCH_ROOT) -o 207-Rpt-TeamCityReporter 207-Rpt-TeamCityReporter.cpp 200-Rpt-CatchMainTeamCity.o && 207-Rpt-TeamCityReporter --list-reporters
//
// - cl -EHsc -I%CATCH_ROOT% -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -Fo200-Rpt-CatchMainTeamCity.obj -c 200-Rpt-CatchMain.cpp
// - cl -EHsc -I%CATCH_ROOT% 207-Rpt-TeamCityReporter.cpp 200-Rpt-CatchMainTeamCity.o && 207-Rpt-TeamCityReporter --list-reporters
// Compilation output (--list-reporters):
// Available reporters:
// compact: Reports test results on a single line, suitable for IDEs
// console: Reports test results as plain lines of text
// junit: Reports test results in an XML format that looks like Ant's
// junitreport target
// teamcity: Reports test results as TeamCity service messages
// xml: Reports test results as an XML document
// Expected output (abbreviated and broken into shorter lines):
//
// prompt> 207-Rpt-TeamCityReporter.exe --reporter teamcity
// ##teamcity[testSuiteStarted name='207-Rpt-TeamCityReporter.exe']
// ##teamcity[testStarted name='TeamCity passes unconditionally succeeding assertion']
// ##teamcity[testFinished name='TeamCity passes unconditionally succeeding assertion' duration='1']
// ##teamcity[testStarted name='TeamCity reports unconditionally failing assertion']
// ##teamcity[testFailed name='TeamCity reports unconditionally failing assertion' /
// message='.../examples/207-Rpt-TeamCityReporter.cpp:23|n/
// ...............................................................................|n|n/
// .../examples/207-Rpt-TeamCityReporter.cpp:25|nexplicit failure']
// ##teamcity[testFinished name='TeamCity reports unconditionally failing assertion' duration='3']
// ...

View File

@@ -0,0 +1,422 @@
// 210-Evt-EventListeners.cpp
// Contents:
// 1. Printing of listener data
// 2. My listener and registration
// 3. Test cases
// main() provided in 000-CatchMain.cpp
// Let Catch provide the required interfaces:
#define CATCH_CONFIG_EXTERNAL_INTERFACES
#include <catch2/catch.hpp>
#include <iostream>
// -----------------------------------------------------------------------
// 1. Printing of listener data:
//
std::string ws(int const level) {
return std::string( 2 * level, ' ' );
}
template< typename T >
std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {
os << "{ ";
for ( auto x : v )
os << x << ", ";
return os << "}";
}
// struct SourceLineInfo {
// char const* file;
// std::size_t line;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::SourceLineInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- file: " << info.file << "\n"
<< ws(level+1) << "- line: " << info.line << "\n";
}
//struct MessageInfo {
// std::string macroName;
// std::string message;
// SourceLineInfo lineInfo;
// ResultWas::OfType type;
// unsigned int sequence;
//};
void print( std::ostream& os, int const level, Catch::MessageInfo const& info ) {
os << ws(level+1) << "- macroName: '" << info.macroName << "'\n"
<< ws(level+1) << "- message '" << info.message << "'\n";
print( os,level+1 , "- lineInfo", info.lineInfo );
os << ws(level+1) << "- sequence " << info.sequence << "\n";
}
void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
os << ws(level ) << title << ":\n";
for ( auto x : v )
{
os << ws(level+1) << "{\n";
print( os, level+2, x );
os << ws(level+1) << "}\n";
}
// os << ws(level+1) << "\n";
}
// struct TestRunInfo {
// std::string name;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- name: " << info.name << "\n";
}
// struct Counts {
// std::size_t total() const;
// bool allPassed() const;
// bool allOk() const;
//
// std::size_t passed = 0;
// std::size_t failed = 0;
// std::size_t failedButOk = 0;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::Counts const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- total(): " << info.total() << "\n"
<< ws(level+1) << "- allPassed(): " << info.allPassed() << "\n"
<< ws(level+1) << "- allOk(): " << info.allOk() << "\n"
<< ws(level+1) << "- passed: " << info.passed << "\n"
<< ws(level+1) << "- failed: " << info.failed << "\n"
<< ws(level+1) << "- failedButOk: " << info.failedButOk << "\n";
}
// struct Totals {
// Counts assertions;
// Counts testCases;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::Totals const& info ) {
os << ws(level) << title << ":\n";
print( os, level+1, "- assertions", info.assertions );
print( os, level+1, "- testCases" , info.testCases );
}
// struct TestRunStats {
// TestRunInfo runInfo;
// Totals totals;
// bool aborting;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunStats const& info ) {
os << ws(level) << title << ":\n";
print( os, level+1 , "- runInfo", info.runInfo );
print( os, level+1 , "- totals" , info.totals );
os << ws(level+1) << "- aborting: " << info.aborting << "\n";
}
// struct TestCaseInfo {
// enum SpecialProperties{
// None = 0,
// IsHidden = 1 << 1,
// ShouldFail = 1 << 2,
// MayFail = 1 << 3,
// Throws = 1 << 4,
// NonPortable = 1 << 5,
// Benchmark = 1 << 6
// };
//
// bool isHidden() const;
// bool throws() const;
// bool okToFail() const;
// bool expectedToFail() const;
//
// std::string tagsAsString() const;
//
// std::string name;
// std::string className;
// std::string description;
// std::vector<std::string> tags;
// std::vector<std::string> lcaseTags;
// SourceLineInfo lineInfo;
// SpecialProperties properties;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- isHidden(): " << info.isHidden() << "\n"
<< ws(level+1) << "- throws(): " << info.throws() << "\n"
<< ws(level+1) << "- okToFail(): " << info.okToFail() << "\n"
<< ws(level+1) << "- expectedToFail(): " << info.expectedToFail() << "\n"
<< ws(level+1) << "- tagsAsString(): '" << info.tagsAsString() << "'\n"
<< ws(level+1) << "- name: '" << info.name << "'\n"
<< ws(level+1) << "- className: '" << info.className << "'\n"
<< ws(level+1) << "- description: '" << info.description << "'\n"
<< ws(level+1) << "- tags: " << info.tags << "\n"
<< ws(level+1) << "- lcaseTags: " << info.lcaseTags << "\n";
print( os, level+1 , "- lineInfo", info.lineInfo );
os << ws(level+1) << "- properties (flags): 0x" << std::hex << info.properties << std::dec << "\n";
}
// struct TestCaseStats {
// TestCaseInfo testInfo;
// Totals totals;
// std::string stdOut;
// std::string stdErr;
// bool aborting;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseStats const& info ) {
os << ws(level ) << title << ":\n";
print( os, level+1 , "- testInfo", info.testInfo );
print( os, level+1 , "- totals" , info.totals );
os << ws(level+1) << "- stdOut: " << info.stdOut << "\n"
<< ws(level+1) << "- stdErr: " << info.stdErr << "\n"
<< ws(level+1) << "- aborting: " << info.aborting << "\n";
}
// struct SectionInfo {
// std::string name;
// std::string description;
// SourceLineInfo lineInfo;
// };
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";
print( os, level+1 , "- lineInfo", info.lineInfo );
}
// struct SectionStats {
// SectionInfo sectionInfo;
// Counts assertions;
// double durationInSeconds;
// bool missingAssertions;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::SectionStats const& info ) {
os << ws(level ) << title << ":\n";
print( os, level+1 , "- sectionInfo", info.sectionInfo );
print( os, level+1 , "- assertions" , info.assertions );
os << ws(level+1) << "- durationInSeconds: " << info.durationInSeconds << "\n"
<< ws(level+1) << "- missingAssertions: " << info.missingAssertions << "\n";
}
// struct AssertionInfo
// {
// StringRef macroName;
// SourceLineInfo lineInfo;
// StringRef capturedExpression;
// ResultDisposition::Flags resultDisposition;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- macroName: '" << info.macroName << "'\n";
print( os, level+1 , "- lineInfo" , info.lineInfo );
os << ws(level+1) << "- capturedExpression: '" << info.capturedExpression << "'\n"
<< ws(level+1) << "- resultDisposition (flags): 0x" << std::hex << info.resultDisposition << std::dec << "\n";
}
//struct AssertionResultData
//{
// std::string reconstructExpression() const;
//
// std::string message;
// mutable std::string reconstructedExpression;
// LazyExpression lazyExpression;
// ResultWas::OfType resultType;
//};
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResultData const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- reconstructExpression(): '" << info.reconstructExpression() << "'\n"
<< ws(level+1) << "- message: '" << info.message << "'\n"
<< ws(level+1) << "- lazyExpression: '" << "(info.lazyExpression)" << "'\n"
<< ws(level+1) << "- resultType: '" << info.resultType << "'\n";
}
//class AssertionResult {
// bool isOk() const;
// bool succeeded() const;
// ResultWas::OfType getResultType() const;
// bool hasExpression() const;
// bool hasMessage() const;
// std::string getExpression() const;
// std::string getExpressionInMacro() const;
// bool hasExpandedExpression() const;
// std::string getExpandedExpression() const;
// std::string getMessage() const;
// SourceLineInfo getSourceInfo() const;
// std::string getTestMacroName() const;
//
// AssertionInfo m_info;
// AssertionResultData m_resultData;
//};
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResult const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- isOk(): " << info.isOk() << "\n"
<< ws(level+1) << "- succeeded(): " << info.succeeded() << "\n"
<< ws(level+1) << "- getResultType(): " << info.getResultType() << "\n"
<< ws(level+1) << "- hasExpression(): " << info.hasExpression() << "\n"
<< ws(level+1) << "- hasMessage(): " << info.hasMessage() << "\n"
<< ws(level+1) << "- getExpression(): '" << info.getExpression() << "'\n"
<< ws(level+1) << "- getExpressionInMacro(): '" << info.getExpressionInMacro() << "'\n"
<< ws(level+1) << "- hasExpandedExpression(): " << info.hasExpandedExpression() << "\n"
<< ws(level+1) << "- getExpandedExpression(): " << info.getExpandedExpression() << "'\n"
<< ws(level+1) << "- getMessage(): '" << info.getMessage() << "'\n";
print( os, level+1 , "- getSourceInfo(): ", info.getSourceInfo() );
os << ws(level+1) << "- getTestMacroName(): '" << info.getTestMacroName() << "'\n";
// print( os, level+1 , "- *** m_info (AssertionInfo)", info.m_info );
// print( os, level+1 , "- *** m_resultData (AssertionResultData)", info.m_resultData );
}
// struct AssertionStats {
// AssertionResult assertionResult;
// std::vector<MessageInfo> infoMessages;
// Totals totals;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionStats const& info ) {
os << ws(level ) << title << ":\n";
print( os, level+1 , "- assertionResult", info.assertionResult );
print( os, level+1 , "- infoMessages", info.infoMessages );
print( os, level+1 , "- totals", info.totals );
}
// -----------------------------------------------------------------------
// 2. My listener and registration:
//
char const * dashed_line =
"--------------------------------------------------------------------------";
struct MyListener : Catch::TestEventListenerBase {
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
// Get rid of Wweak-tables
~MyListener();
// The whole test run starting
virtual void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
std::cout
<< std::boolalpha
<< "\nEvent: testRunStarting:\n";
print( std::cout, 1, "- testRunInfo", testRunInfo );
}
// The whole test run ending
virtual void testRunEnded( Catch::TestRunStats const& testRunStats ) override {
std::cout
<< dashed_line
<< "\nEvent: testRunEnded:\n";
print( std::cout, 1, "- testRunStats", testRunStats );
}
// A test is being skipped (because it is "hidden")
virtual void skipTest( Catch::TestCaseInfo const& testInfo ) override {
std::cout
<< dashed_line
<< "\nEvent: skipTest:\n";
print( std::cout, 1, "- testInfo", testInfo );
}
// Test cases starting
virtual void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
std::cout
<< dashed_line
<< "\nEvent: testCaseStarting:\n";
print( std::cout, 1, "- testInfo", testInfo );
}
// Test cases ending
virtual void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
std::cout << "\nEvent: testCaseEnded:\n";
print( std::cout, 1, "testCaseStats", testCaseStats );
}
// Sections starting
virtual void sectionStarting( Catch::SectionInfo const& sectionInfo ) override {
std::cout << "\nEvent: sectionStarting:\n";
print( std::cout, 1, "- sectionInfo", sectionInfo );
}
// Sections ending
virtual void sectionEnded( Catch::SectionStats const& sectionStats ) override {
std::cout << "\nEvent: sectionEnded:\n";
print( std::cout, 1, "- sectionStats", sectionStats );
}
// Assertions before/ after
virtual void assertionStarting( Catch::AssertionInfo const& assertionInfo ) override {
std::cout << "\nEvent: assertionStarting:\n";
print( std::cout, 1, "- assertionInfo", assertionInfo );
}
virtual bool assertionEnded( Catch::AssertionStats const& assertionStats ) override {
std::cout << "\nEvent: assertionEnded:\n";
print( std::cout, 1, "- assertionStats", assertionStats );
return true;
}
};
CATCH_REGISTER_LISTENER( MyListener )
// Get rid of Wweak-tables
MyListener::~MyListener() {}
// -----------------------------------------------------------------------
// 3. Test cases:
//
TEST_CASE( "1: Hidden testcase", "[.hidden]" ) {
}
TEST_CASE( "2: Testcase with sections", "[tag-A][tag-B]" ) {
int i = 42;
REQUIRE( i == 42 );
SECTION("Section 1") {
INFO("Section 1")
i = 7;
SECTION("Section 1.1") {
INFO("Section 1.1")
REQUIRE( i == 42 );
}
}
SECTION("Section 2") {
INFO("Section 2")
REQUIRE( i == 42 );
}
WARN("At end of test case");
}
struct Fixture {
int fortytwo() const {
return 42;
}
};
TEST_CASE_METHOD( Fixture, "3: Testcase with class-based fixture", "[tag-C][tag-D]" ) {
REQUIRE( fortytwo() == 42 );
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp 000-CatchMain.o && 210-Evt-EventListeners --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp 000-CatchMain.obj && 210-Evt-EventListeners --success
// Expected compact output (all assertions):
//
// prompt> 210-Evt-EventListeners --reporter compact --success
// result omitted for brevity.

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.");
}

153
examples/CMakeLists.txt Normal file
View File

@@ -0,0 +1,153 @@
#
# Build examples.
#
# Requires CATCH_BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
#
cmake_minimum_required( VERSION 3.0 )
project( CatchExamples CXX )
message( STATUS "Examples included" )
# define folders used:
set( EXAMPLES_DIR ${CATCH_DIR}/examples )
set( HEADER_DIR ${CATCH_DIR}/single_include )
set( REPORTER_HEADER_DIR ${CATCH_DIR}/include/reporters )
# single-file sources:
set( SOURCES_SINGLE_FILE
010-TestCase.cpp
231-Cfg-OutputStreams.cpp
)
# multiple-file modules:
set( SOURCES_020
020-TestCase-1.cpp
020-TestCase-2.cpp
)
# main for idiomatic test sources:
set( SOURCES_IDIOMATIC_MAIN
000-CatchMain.cpp
)
# sources to combine with 000-CatchMain.cpp:
set( SOURCES_IDIOMATIC_TESTS
030-Asn-Require-Check.cpp
100-Fix-Section.cpp
110-Fix-ClassFixture.cpp
120-Bdd-ScenarioGivenWhenThen.cpp
210-Evt-EventListeners.cpp
)
# main-s for reporter-specific test sources:
set( SOURCES_REPORTERS_MAIN
200-Rpt-CatchMain.cpp
)
string( REPLACE ".cpp" "" BASENAMES_REPORTERS_MAIN 200-Rpt-CatchMain.cpp )
set( NAMES_REPORTERS TeamCity )
foreach( reporter ${NAMES_REPORTERS} )
list( APPEND SOURCES_SPECIFIC_REPORTERS_MAIN ${BASENAMES_REPORTERS_MAIN}${reporter}.cpp )
endforeach()
# sources to combine with 200-Rpt-CatchMain{Reporter}.cpp:
set( SOURCES_REPORTERS_TESTS
207-Rpt-TeamCityReporter.cpp
)
# check if all sources are listed, warn if not:
set( SOURCES_ALL
${SOURCES_020}
${SOURCES_SINGLE_FILE}
${SOURCES_IDIOMATIC_MAIN}
${SOURCES_IDIOMATIC_TESTS}
${SOURCES_REPORTERS_MAIN}
${SOURCES_REPORTERS_TESTS}
)
foreach( name ${SOURCES_ALL} )
list( APPEND SOURCES_ALL_PATH ${EXAMPLES_DIR}/${name} )
endforeach()
CheckFileList( SOURCES_ALL_PATH ${EXAMPLES_DIR} )
# create target names:
string( REPLACE ".cpp" "" BASENAMES_SINGLE_FILE "${SOURCES_SINGLE_FILE}" )
string( REPLACE ".cpp" "" BASENAMES_IDIOMATIC_TESTS "${SOURCES_IDIOMATIC_TESTS}" )
string( REPLACE ".cpp" "" BASENAMES_REPORTERS_TESTS "${SOURCES_REPORTERS_TESTS}" )
string( REPLACE ".cpp" "" BASENAMES_REPORTERS_MAIN "${SOURCES_REPORTERS_MAIN}" )
set( TARGETS_SINGLE_FILE ${BASENAMES_SINGLE_FILE} )
set( TARGETS_IDIOMATIC_TESTS ${BASENAMES_IDIOMATIC_TESTS} )
set( TARGETS_REPORTERS_TESTS ${BASENAMES_REPORTERS_TESTS} )
set( TARGETS_REPORTERS_MAIN ${BASENAMES_REPORTERS_MAIN} )
set( TARGETS_ALL
${TARGETS_SINGLE_FILE}
020-TestCase
${TARGETS_IDIOMATIC_TESTS} CatchMain
${TARGETS_REPORTERS_TESTS} CatchMainTeamCity
)
# define program targets:
add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch2/catch.hpp )
#add_library( CatchMainAutomake OBJECT ${EXAMPLES_DIR}/200-Rpt-CatchMain.cpp ${HEADER_DIR}/catch2/catch.hpp )
#add_library( CatchMainTap OBJECT ${EXAMPLES_DIR}/200-Rpt-CatchMain.cpp ${HEADER_DIR}/catch2/catch.hpp )
add_library( CatchMainTeamCity OBJECT ${EXAMPLES_DIR}/200-Rpt-CatchMain.cpp ${HEADER_DIR}/catch2/catch.hpp )
#target_compile_definitions( CatchMainAutomake PRIVATE CATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_automake.hpp\" )
#target_compile_definitions( CatchMainTap PRIVATE CATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_tap.hpp\" )
target_compile_definitions( CatchMainTeamCity PRIVATE CATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" )
foreach( name ${TARGETS_SINGLE_FILE} )
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}/catch2/catch.hpp )
endforeach()
add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch2/catch.hpp )
#add_executable( 207-Rpt-AutomakeReporter ${EXAMPLES_DIR}/207-Rpt-AutomakeReporter.cpp $<TARGET_OBJECTS:CatchMainAutomake> ${HEADER_DIR}/catch2/catch.hpp )
#add_executable( 207-Rpt-TapReporter ${EXAMPLES_DIR}/207-Rpt-TapReporter.cpp $<TARGET_OBJECTS:CatchMainTap> ${HEADER_DIR}/catch2/catch.hpp )
add_executable( 207-Rpt-TeamCityReporter ${EXAMPLES_DIR}/207-Rpt-TeamCityReporter.cpp $<TARGET_OBJECTS:CatchMainTeamCity> ${HEADER_DIR}/catch2/catch.hpp )
#foreach( name ${TARGETS_REPORTERS_TESTS} )
# add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp )
#endforeach()
foreach( name ${TARGETS_ALL} )
target_include_directories( ${name} PRIVATE ${HEADER_DIR} ${CATCH_DIR} )
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS OFF)
# Add desired warnings
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
target_compile_options( ${name} PRIVATE -Wall -Wextra -Wunreachable-code )
endif()
# Clang specific warning go here
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
# Actually keep these
target_compile_options( ${name} PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
target_compile_options( ${name} PRIVATE /W4 /w44265 /WX )
endif()
endforeach()

View File

@@ -9,6 +9,10 @@
#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_HPP_INCLUDED #define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 4
#define CATCH_VERSION_PATCH 1
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header
#elif defined __GNUC__ #elif defined __GNUC__
@@ -19,9 +23,22 @@
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL # define CATCH_IMPL
# define CATCH_CONFIG_EXTERNAL_INTERFACES # define CATCH_CONFIG_ALL_PARTS
#endif #endif
// In the impl file, we want to have access to all parts of the headers
// Can also be used to sanely support PCHs
#if defined(CATCH_CONFIG_ALL_PARTS)
# define CATCH_CONFIG_EXTERNAL_INTERFACES
# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
# undef CATCH_CONFIG_DISABLE_MATCHERS
# endif
# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
# endif
#endif
#if !defined(CATCH_CONFIG_IMPL_ONLY)
#include "internal/catch_platform.h" #include "internal/catch_platform.h"
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
@@ -31,19 +48,21 @@
# endif # endif
#endif #endif
#include "internal/catch_user_interfaces.h"
#include "internal/catch_tag_alias_autoregistrar.h" #include "internal/catch_tag_alias_autoregistrar.h"
#include "internal/catch_test_registry.hpp" #include "internal/catch_test_registry.h"
#include "internal/catch_capture.hpp" #include "internal/catch_capture.hpp"
#include "internal/catch_section.h" #include "internal/catch_section.h"
#include "internal/catch_benchmark.h" #include "internal/catch_benchmark.h"
#include "internal/catch_interfaces_exception.h" #include "internal/catch_interfaces_exception.h"
#include "internal/catch_approx.hpp" #include "internal/catch_approx.h"
#include "internal/catch_compiler_capabilities.h" #include "internal/catch_compiler_capabilities.h"
#include "internal/catch_interfaces_tag_alias_registry.h" #include "internal/catch_string_manip.h"
#ifndef CATCH_CONFIG_DISABLE_MATCHERS #ifndef CATCH_CONFIG_DISABLE_MATCHERS
#include "internal/catch_capture_matchers.h" #include "internal/catch_capture_matchers.h"
#endif #endif
#include "internal/catch_generators.hpp"
// These files are included here so the single_include script doesn't put them // These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections // in the conditionally compiled sections
@@ -58,6 +77,8 @@
#include "internal/catch_external_interfaces.h" #include "internal/catch_external_interfaces.h"
#endif #endif
#endif // ! CATCH_CONFIG_IMPL_ONLY
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
#include "internal/catch_impl.hpp" #include "internal/catch_impl.hpp"
#endif #endif
@@ -66,6 +87,7 @@
#include "internal/catch_default_main.hpp" #include "internal/catch_default_main.hpp"
#endif #endif
#if !defined(CATCH_CONFIG_IMPL_ONLY)
#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
# undef CLARA_CONFIG_MAIN # undef CLARA_CONFIG_MAIN
@@ -109,13 +131,14 @@
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_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( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
@@ -125,11 +148,12 @@
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + 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 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else #else
@@ -168,13 +192,14 @@
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __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( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
@@ -188,15 +213,17 @@
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
#define WHEN( desc ) SECTION( std::string(" When: ") + desc ) #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
#define THEN( desc ) SECTION( std::string(" Then: ") + desc ) #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
using Catch::Detail::Approx; using Catch::Detail::Approx;
#else #else // CATCH_CONFIG_DISABLE
////// //////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL #ifdef CATCH_CONFIG_PREFIX_ALL
@@ -241,6 +268,7 @@ using Catch::Detail::Approx;
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) #define CATCH_METHOD_AS_TEST_CASE( method, ... )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define CATCH_SECTION( ... ) #define CATCH_SECTION( ... )
#define CATCH_DYNAMIC_SECTION( ... )
#define CATCH_FAIL( ... ) (void)(0) #define CATCH_FAIL( ... ) (void)(0)
#define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_FAIL_CHECK( ... ) (void)(0)
#define CATCH_SUCCEED( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0)
@@ -251,6 +279,7 @@ using Catch::Detail::Approx;
#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
#define CATCH_GIVEN( desc ) #define CATCH_GIVEN( desc )
#define CATCH_AND_GIVEN( desc )
#define CATCH_WHEN( desc ) #define CATCH_WHEN( desc )
#define CATCH_AND_WHEN( desc ) #define CATCH_AND_WHEN( desc )
#define CATCH_THEN( desc ) #define CATCH_THEN( desc )
@@ -300,6 +329,7 @@ using Catch::Detail::Approx;
#define METHOD_AS_TEST_CASE( method, ... ) #define METHOD_AS_TEST_CASE( method, ... )
#define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define SECTION( ... ) #define SECTION( ... )
#define DYNAMIC_SECTION( ... )
#define FAIL( ... ) (void)(0) #define FAIL( ... ) (void)(0)
#define FAIL_CHECK( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0)
#define SUCCEED( ... ) (void)(0) #define SUCCEED( ... ) (void)(0)
@@ -314,6 +344,7 @@ using Catch::Detail::Approx;
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
#define GIVEN( desc ) #define GIVEN( desc )
#define AND_GIVEN( desc )
#define WHEN( desc ) #define WHEN( desc )
#define AND_WHEN( desc ) #define AND_WHEN( desc )
#define THEN( desc ) #define THEN( desc )
@@ -324,6 +355,8 @@ using Catch::Detail::Approx;
#endif #endif
#endif // ! CATCH_CONFIG_IMPL_ONLY
#include "internal/catch_reenable_warnings.h" #include "internal/catch_reenable_warnings.h"
#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_HPP_INCLUDED

View File

@@ -1,264 +0,0 @@
/*
* Created by Phil on 31/10/2010.
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
#include "internal/catch_commandline.hpp"
#include "internal/catch_console_colour.hpp"
#include "internal/catch_enforce.h"
#include "internal/catch_list.h"
#include "internal/catch_run_context.hpp"
#include "internal/catch_stream.h"
#include "internal/catch_test_spec.hpp"
#include "internal/catch_version.h"
#include "internal/catch_interfaces_reporter.h"
#include "internal/catch_startup_exception_registry.h"
#include "internal/catch_text.h"
#include <fstream>
#include <cstdlib>
#include <limits>
#include <iomanip>
namespace Catch {
IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) {
auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config );
CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" );
return reporter;
}
#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 );
IStreamingReporterPtr reporter;
for( auto const& name : reporterNames )
addReporter( reporter, createReporter( name, config ) );
return reporter;
}
void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) {
auto const& listeners = getRegistryHub().getReporterRegistry().getListeners();
for( auto const& listener : listeners )
addReporter(reporters, listener->create( ReporterConfig( config ) ) );
}
Totals runTests( std::shared_ptr<Config> const& config ) {
IStreamingReporterPtr reporter = makeReporter( config );
addListeners( reporter, config );
RunContext context( config, std::move( reporter ) );
Totals totals;
context.testGroupStarting( config->name(), 1, 1 );
TestSpec testSpec = config->testSpec();
if( !testSpec.hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *config );
for( auto const& testCase : allTestCases ) {
if( !context.aborting() && matchTest( testCase, testSpec, *config ) )
totals += context.runTest( testCase );
else
context.reporter().skipTest( testCase );
}
context.testGroupEnded( config->name(), totals, 1, 1 );
return totals;
}
void applyFilenamesAsTags( IConfig const& config ) {
auto& tests = const_cast<std::vector<TestCase>&>( getAllTestCasesSorted( config ) );
for( auto& testCase : tests ) {
auto tags = testCase.tags;
std::string filename = testCase.lineInfo.file;
std::string::size_type lastSlash = filename.find_last_of( "\\/" );
if( lastSlash != std::string::npos )
filename = filename.substr( lastSlash+1 );
std::string::size_type lastDot = filename.find_last_of( '.' );
if( lastDot != std::string::npos )
filename = filename.substr( 0, lastDot );
tags.push_back( '#' + filename );
setTags( testCase, tags );
}
}
class Session : NonCopyable {
static const int MaxExitCode;
public:
Session() {
static bool alreadyInstantiated = false;
if( alreadyInstantiated )
CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" );
alreadyInstantiated = true;
m_cli = makeCommandLineParser( m_configData );
}
~Session() override {
Catch::cleanUp();
}
void showHelp() const {
Catch::cout()
<< "\nCatch v" << libraryVersion() << "\n"
<< m_cli << std::endl
<< "For more detailed usage please see the project docs\n" << std::endl;
}
void libIdentify() {
Catch::cout()
<< std::left << std::setw(16) << "description: " << "A Catch test executable\n"
<< std::left << std::setw(16) << "category: " << "testframework\n"
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
}
int applyCommandLine( int argc, char* argv[] ) {
auto result = m_cli.parse( clara::Args( argc, argv ) );
if( !result ) {
Catch::cerr()
<< Colour( Colour::Red )
<< "\nError(s) in input:\n"
<< Column( result.errorMessage() ).indent( 2 )
<< "\n\n";
Catch::cerr() << "Run with -? for usage\n" << std::endl;
return MaxExitCode;
}
if( m_configData.showHelp )
showHelp();
if( m_configData.libIdentify )
libIdentify();
m_config.reset();
return 0;
}
void useConfigData( ConfigData const& configData ) {
m_configData = configData;
m_config.reset();
}
int run( int argc, char* argv[] ) {
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
if ( !exceptions.empty() ) {
Catch::cerr() << "Errors occured during startup!" << '\n';
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
std::rethrow_exception(ex_ptr);
} catch ( std::exception const& ex ) {
Catch::cerr() << ex.what() << '\n';
}
}
return 1;
}
int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 )
returnCode = run();
return returnCode;
}
#if defined(WIN32) && defined(UNICODE)
int run( int argc, wchar_t* const argv[] ) {
char **utf8Argv = new char *[ argc ];
for ( int i = 0; i < argc; ++i ) {
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
utf8Argv[ i ] = new char[ bufSize ];
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
}
int returnCode = run( argc, utf8Argv );
for ( int i = 0; i < argc; ++i )
delete [] utf8Argv[ i ];
delete [] utf8Argv;
return returnCode;
}
#endif
int run() {
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
static_cast<void>(std::getchar());
}
int exitCode = runInternal();
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
static_cast<void>(std::getchar());
}
return exitCode;
}
clara::Parser const& cli() const {
return m_cli;
}
void cli( clara::Parser const& newParser ) {
m_cli = newParser;
}
ConfigData& configData() {
return m_configData;
}
Config& config() {
if( !m_config )
m_config = std::make_shared<Config>( m_configData );
return *m_config;
}
private:
int runInternal() {
if( m_configData.showHelp || m_configData.libIdentify )
return 0;
try
{
config(); // Force config to be constructed
seedRng( *m_config );
if( m_configData.filenamesAsTags )
applyFilenamesAsTags( *m_config );
// Handle list request
if( Option<std::size_t> listed = list( config() ) )
return static_cast<int>( *listed );
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;
return MaxExitCode;
}
}
clara::Parser m_cli;
ConfigData m_configData;
std::shared_ptr<Config> m_config;
};
const int Session::MaxExitCode = 255;
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@@ -6,24 +6,29 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#include "catch_approx.hpp" #include "catch_approx.h"
#include "catch_enforce.h"
#include <cmath>
#include <limits> #include <limits>
namespace {
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
// But without the subtraction to allow for INFINITY in comparison
bool marginComparison(double lhs, double rhs, double margin) {
return (lhs + margin >= rhs) && (rhs + margin >= lhs);
}
}
namespace Catch { namespace Catch {
namespace Detail { namespace Detail {
double max(double lhs, double rhs) {
if (lhs < rhs) {
return rhs;
}
return lhs;
}
Approx::Approx ( double value ) Approx::Approx ( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ), : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_margin( 0.0 ), m_margin( 0.0 ),
m_scale( 1.0 ), m_scale( 0.0 ),
m_value( value ) m_value( value )
{} {}
@@ -31,14 +36,50 @@ namespace Detail {
return Approx( 0 ); return Approx( 0 );
} }
Approx Approx::operator-() const {
auto temp(*this);
temp.m_value = -temp.m_value;
return temp;
}
std::string Approx::toString() const { std::string Approx::toString() const {
std::ostringstream oss; ReusableStringStream rss;
oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
return oss.str(); return rss.str();
}
bool Approx::equalityComparisonImpl(const double other) const {
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
// Thanks to Richard Harris for his help refining the scaled margin value
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
}
void Approx::setMargin(double margin) {
CATCH_ENFORCE(margin >= 0,
"Invalid Approx::margin: " << margin << '.'
<< " Approx::Margin has to be non-negative.");
m_margin = margin;
}
void Approx::setEpsilon(double epsilon) {
CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
"Invalid Approx::epsilon: " << epsilon << '.'
<< " Approx::epsilon has to be in [0, 1]");
m_epsilon = epsilon;
} }
} // end 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) { std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
return value.toString(); return value.toString();
} }

View File

@@ -10,27 +10,34 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include <cmath>
#include <type_traits> #include <type_traits>
namespace Catch { namespace Catch {
namespace Detail { namespace Detail {
double max(double lhs, double rhs);
class Approx { class Approx {
private:
bool equalityComparisonImpl(double other) const;
// Validates the new margin (margin >= 0)
// out-of-line to avoid including stdexcept in the header
void setMargin(double margin);
// Validates the new epsilon (0 < epsilon < 1)
// out-of-line to avoid including stdexcept in the header
void setEpsilon(double epsilon);
public: public:
explicit Approx ( double value ); explicit Approx ( double value );
static Approx custom(); static Approx custom();
Approx operator-() const;
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx operator()( T const& value ) { Approx operator()( T const& value ) {
Approx approx( static_cast<double>(value) ); Approx approx( static_cast<double>(value) );
approx.epsilon( m_epsilon ); approx.m_epsilon = m_epsilon;
approx.margin( m_margin ); approx.m_margin = m_margin;
approx.scale( m_scale ); approx.m_scale = m_scale;
return approx; return approx;
} }
@@ -41,13 +48,8 @@ namespace Detail {
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
friend bool operator == ( const T& lhs, Approx const& rhs ) { friend bool operator == ( const T& lhs, Approx const& rhs ) {
// Thanks to Richard Harris for his help refining this formula
auto lhs_v = static_cast<double>(lhs); auto lhs_v = static_cast<double>(lhs);
bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); return rhs.equalityComparisonImpl(lhs_v);
if (relativeOK) {
return true;
}
return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
@@ -87,13 +89,15 @@ namespace Detail {
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& epsilon( T const& newEpsilon ) { Approx& epsilon( T const& newEpsilon ) {
m_epsilon = static_cast<double>(newEpsilon); double epsilonAsDouble = static_cast<double>(newEpsilon);
setEpsilon(epsilonAsDouble);
return *this; return *this;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& margin( T const& newMargin ) { Approx& margin( T const& newMargin ) {
m_margin = static_cast<double>(newMargin); double marginAsDouble = static_cast<double>(newMargin);
setMargin(marginAsDouble);
return *this; return *this;
} }
@@ -111,7 +115,12 @@ namespace Detail {
double m_scale; double m_scale;
double m_value; 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<> template<>
struct StringMaker<Catch::Detail::Approx> { struct StringMaker<Catch::Detail::Approx> {

View File

@@ -8,21 +8,21 @@
#include "catch_assertionhandler.h" #include "catch_assertionhandler.h"
#include "catch_assertionresult.h" #include "catch_assertionresult.h"
#include "catch_interfaces_capture.h"
#include "catch_interfaces_runner.h" #include "catch_interfaces_runner.h"
#include "catch_interfaces_config.h" #include "catch_interfaces_config.h"
#include "catch_context.h" #include "catch_context.h"
#include "catch_debugger.h" #include "catch_debugger.h"
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
#include "catch_capture_matchers.h" #include "catch_capture_matchers.h"
#include "catch_run_context.h"
#include <cassert>
namespace Catch { namespace Catch {
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { namespace {
expr.streamReconstructedExpression( os ); auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
return os; expr.streamReconstructedExpression( os );
return os;
}
} }
LazyExpression::LazyExpression( bool isNegated ) LazyExpression::LazyExpression( bool isNegated )
@@ -52,95 +52,69 @@ namespace Catch {
} }
AssertionHandler::AssertionHandler AssertionHandler::AssertionHandler
( StringRef macroName, ( StringRef const& macroName,
SourceLineInfo const& lineInfo, SourceLineInfo const& lineInfo,
StringRef capturedExpression, StringRef capturedExpression,
ResultDisposition::Flags resultDisposition ) ResultDisposition::Flags resultDisposition )
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
{ m_resultCapture( getResultCapture() )
getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); {}
void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
} }
AssertionHandler::~AssertionHandler() { void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
if ( m_inExceptionGuard ) { m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" );
getCurrentContext().getResultCapture()->exceptionEarlyReported();
}
}
void AssertionHandler::handle( ITransientExpression const& expr ) {
bool negated = isFalseTest( m_assertionInfo.resultDisposition );
bool result = expr.getResult() != negated;
handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated );
}
void AssertionHandler::handle( ResultWas::OfType resultType ) {
handle( resultType, nullptr, false );
}
void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) {
AssertionResultData data( resultType, LazyExpression( false ) );
data.message = message;
handle( data, nullptr );
}
void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) {
AssertionResultData data( resultType, LazyExpression( negated ) );
handle( data, expr );
}
void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) {
getResultCapture().assertionRun();
AssertionResult assertionResult{ m_assertionInfo, resultData };
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
getResultCapture().assertionEnded( assertionResult );
if( !assertionResult.isOk() ) {
m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak();
m_shouldThrow =
getCurrentContext().getRunner()->aborting() ||
(m_assertionInfo.resultDisposition & ResultDisposition::Normal);
}
} }
auto AssertionHandler::allowThrows() const -> bool { auto AssertionHandler::allowThrows() const -> bool {
return getCurrentContext().getConfig()->allowThrows(); return getCurrentContext().getConfig()->allowThrows();
} }
auto AssertionHandler::shouldDebugBreak() const -> bool { void AssertionHandler::complete() {
return m_shouldDebugBreak; setCompleted();
} if( m_reaction.shouldDebugBreak ) {
void AssertionHandler::reactWithDebugBreak() const {
if (m_shouldDebugBreak) { // If you find your debugger stopping you here then go one level up on the
/////////////////////////////////////////////////////////////////// // call-stack for the code that caused it (typically a failed assertion)
// To inspect the state during test, you need to go one level up the callstack
// To go back to the test and change execution, jump over the reactWithoutDebugBreak() call // (To go back to the test and change execution, jump over the throw, next)
///////////////////////////////////////////////////////////////////
CATCH_BREAK_INTO_DEBUGGER(); CATCH_BREAK_INTO_DEBUGGER();
} }
reactWithoutDebugBreak(); if (m_reaction.shouldThrow) {
} #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
void AssertionHandler::reactWithoutDebugBreak() const {
if( m_shouldThrow )
throw Catch::TestFailureException(); throw Catch::TestFailureException();
#else
CATCH_ERROR( "Test failure requires aborting test!" );
#endif
}
}
void AssertionHandler::setCompleted() {
m_completed = true;
} }
void AssertionHandler::useActiveException() { void AssertionHandler::handleUnexpectedInflightException() {
handle( ResultWas::ThrewException, Catch::translateActiveException() ); m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
} }
void AssertionHandler::setExceptionGuard() { void AssertionHandler::handleExceptionThrownAsExpected() {
assert( m_inExceptionGuard == false ); m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
m_inExceptionGuard = true;
} }
void AssertionHandler::unsetExceptionGuard() { void AssertionHandler::handleExceptionNotThrownAsExpected() {
assert( m_inExceptionGuard == true ); m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
m_inExceptionGuard = false; }
void AssertionHandler::handleUnexpectedExceptionNotThrown() {
m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
}
void AssertionHandler::handleThrowingCallSkipped() {
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
} }
// This is the overload that takes a string and infers the Equals matcher from it // This is the overload that takes a string and infers the Equals matcher from it
// The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) { void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) {
handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
} }

View File

@@ -8,17 +8,21 @@
#ifndef TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED
#define TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED #define TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED
#include "catch_decomposer.h"
#include "catch_assertioninfo.h" #include "catch_assertioninfo.h"
#include "catch_decomposer.h"
#include "catch_interfaces_capture.h"
namespace Catch { namespace Catch {
struct TestFailureException{}; struct TestFailureException{};
struct AssertionResultData; struct AssertionResultData;
struct IResultCapture;
class RunContext;
class LazyExpression { class LazyExpression {
friend class AssertionHandler; friend class AssertionHandler;
friend struct AssertionStats; friend struct AssertionStats;
friend class RunContext;
ITransientExpression const* m_transientExpression = nullptr; ITransientExpression const* m_transientExpression = nullptr;
bool m_isNegated; bool m_isNegated;
@@ -32,41 +36,52 @@ namespace Catch {
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
}; };
struct AssertionReaction {
bool shouldDebugBreak = false;
bool shouldThrow = false;
};
class AssertionHandler { class AssertionHandler {
AssertionInfo m_assertionInfo; AssertionInfo m_assertionInfo;
bool m_shouldDebugBreak = false; AssertionReaction m_reaction;
bool m_shouldThrow = false; bool m_completed = false;
bool m_inExceptionGuard = false; IResultCapture& m_resultCapture;
public: public:
AssertionHandler AssertionHandler
( StringRef macroName, ( StringRef const& macroName,
SourceLineInfo const& lineInfo, SourceLineInfo const& lineInfo,
StringRef capturedExpression, StringRef capturedExpression,
ResultDisposition::Flags resultDisposition ); ResultDisposition::Flags resultDisposition );
~AssertionHandler(); ~AssertionHandler() {
if ( !m_completed ) {
m_resultCapture.handleIncomplete( m_assertionInfo );
}
}
void handle( ITransientExpression const& expr );
template<typename T> template<typename T>
void handle( ExprLhs<T> const& expr ) { void handleExpr( ExprLhs<T> const& expr ) {
handle( expr.makeUnaryExpr() ); handleExpr( expr.makeUnaryExpr() );
} }
void handle( ResultWas::OfType resultType ); void handleExpr( ITransientExpression const& expr );
void handle( ResultWas::OfType resultType, StringRef const& message );
void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated );
void handle( AssertionResultData const& resultData, ITransientExpression const* expr );
auto shouldDebugBreak() const -> bool; void handleMessage(ResultWas::OfType resultType, StringRef const& message);
void handleExceptionThrownAsExpected();
void handleUnexpectedExceptionNotThrown();
void handleExceptionNotThrownAsExpected();
void handleThrowingCallSkipped();
void handleUnexpectedInflightException();
void complete();
void setCompleted();
// query
auto allowThrows() const -> bool; auto allowThrows() const -> bool;
void reactWithDebugBreak() const;
void reactWithoutDebugBreak() const;
void useActiveException();
void setExceptionGuard();
void unsetExceptionGuard();
}; };
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
} // namespace Catch } // namespace Catch

View File

@@ -10,17 +10,16 @@
namespace Catch { namespace Catch {
AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
resultType(_resultType), lazyExpression(_lazyExpression),
lazyExpression(_lazyExpression) {} resultType(_resultType) {}
std::string AssertionResultData::reconstructExpression() const { std::string AssertionResultData::reconstructExpression() const {
if( reconstructedExpression.empty() ) { if( reconstructedExpression.empty() ) {
if( lazyExpression ) { if( lazyExpression ) {
// !TBD Use stringstream for now, but rework above to pass stream in ReusableStringStream rss;
std::ostringstream oss; rss << lazyExpression;
oss << lazyExpression; reconstructedExpression = rss.str();
reconstructedExpression = oss.str();
} }
} }
return reconstructedExpression; return reconstructedExpression;
@@ -54,8 +53,8 @@ namespace Catch {
} }
std::string AssertionResult::getExpression() const { std::string AssertionResult::getExpression() const {
if (isFalseTest(m_info.resultDisposition)) if( isFalseTest( m_info.resultDisposition ) )
return '!' + std::string(m_info.capturedExpression); return "!(" + m_info.capturedExpression + ")";
else else
return m_info.capturedExpression; return m_info.capturedExpression;
} }
@@ -92,7 +91,7 @@ namespace Catch {
return m_info.lineInfo; return m_info.lineInfo;
} }
std::string AssertionResult::getTestMacroName() const { StringRef AssertionResult::getTestMacroName() const {
return m_info.macroName; return m_info.macroName;
} }

View File

@@ -23,13 +23,12 @@ namespace Catch {
AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
ResultWas::OfType resultType = ResultWas::Unknown;
std::string message; std::string message;
mutable std::string reconstructedExpression;
LazyExpression lazyExpression; LazyExpression lazyExpression;
ResultWas::OfType resultType;
std::string reconstructExpression() const; std::string reconstructExpression() const;
mutable std::string reconstructedExpression;
}; };
class AssertionResult { class AssertionResult {
@@ -48,7 +47,7 @@ namespace Catch {
std::string getExpandedExpression() const; std::string getExpandedExpression() const;
std::string getMessage() const; std::string getMessage() const;
SourceLineInfo getSourceInfo() const; SourceLineInfo getSourceInfo() const;
std::string getTestMacroName() const; StringRef getTestMacroName() const;
//protected: //protected:
AssertionInfo m_info; AssertionInfo m_info;

View File

@@ -19,8 +19,8 @@ namespace Catch {
class BenchmarkLooper { class BenchmarkLooper {
std::string m_name; std::string m_name;
size_t m_count = 0; std::size_t m_count = 0;
size_t m_iterationsToRun = 1; std::size_t m_iterationsToRun = 1;
uint64_t m_resolution; uint64_t m_resolution;
Timer m_timer; Timer m_timer;

View File

@@ -9,8 +9,9 @@
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
#include "catch_assertionhandler.h" #include "catch_assertionhandler.h"
#include "catch_message.h"
#include "catch_interfaces_capture.h" #include "catch_interfaces_capture.h"
#include "catch_message.h"
#include "catch_stringref.h"
#if !defined(CATCH_CONFIG_DISABLE) #if !defined(CATCH_CONFIG_DISABLE)
@@ -20,51 +21,34 @@
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
#endif #endif
#if defined(CATCH_CONFIG_FAST_COMPILE) #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
///////////////////////////////////////////////////////////////////////////////
// We can speedup compilation significantly by breaking into debugger lower in
// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
// macro in each assertion
#define INTERNAL_CATCH_REACT( handler ) \
handler.reactWithDebugBreak();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Another way to speed-up compilation is to omit local try-catch for REQUIRE* // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
// macros. // macros.
// This can potentially cause false negative, if the test code catches #define INTERNAL_CATCH_TRY
// the exception before it propagates back up to the runner. #define INTERNAL_CATCH_CATCH( capturer )
#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard();
#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard();
#else // CATCH_CONFIG_FAST_COMPILE #else // CATCH_CONFIG_FAST_COMPILE
#include "catch_debugger.h" #define INTERNAL_CATCH_TRY try
#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
///////////////////////////////////////////////////////////////////////////////
// In the event of a failure works out if the debugger needs to be invoked
// and/or an exception thrown and takes appropriate action.
// This needs to be done as a macro so the debugger will stop in the user
// source code rather than in Catch library code
#define INTERNAL_CATCH_REACT( handler ) \
if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
handler.reactWithoutDebugBreak();
#define INTERNAL_CATCH_TRY( capturer ) try
#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); }
#endif #endif
#define INTERNAL_CATCH_REACT( handler ) handler.complete();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ INTERNAL_CATCH_TRY { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::isTrue( false && static_cast<bool>( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -80,84 +64,89 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
try { \ try { \
static_cast<void>(__VA_ARGS__); \ static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
catchAssertionHandler.useActiveException(); \ catchAssertionHandler.handleUnexpectedInflightException(); \
} \ } \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
static_cast<void>(__VA_ARGS__); \ static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleExceptionThrownAsExpected(); \
} \ } \
else \ else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
static_cast<void>(expr); \ static_cast<void>(expr); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( exceptionType const& ) { \ catch( exceptionType const& ) { \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleExceptionThrownAsExpected(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
catchAssertionHandler.useActiveException(); \ catchAssertionHandler.handleUnexpectedInflightException(); \
} \ } \
else \ else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
varName.captureValues( 0, __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_INFO( macroName, log ) \ #define INTERNAL_CATCH_INFO( macroName, log ) \
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Although this is matcher-based, it can be used with just a string // Although this is matcher-based, it can be used with just a string
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
static_cast<void>(__VA_ARGS__); \ static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
} \ } \
else \ else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
#endif // CATCH_CONFIG_DISABLE #endif // CATCH_CONFIG_DISABLE

View File

@@ -13,12 +13,12 @@ namespace Catch {
using StringMatcher = Matchers::Impl::MatcherBase<std::string>; using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
// This is the general overload that takes a any string matcher // 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) // the Equals matcher (so the header does not mention matchers)
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) {
std::string exceptionMessage = Catch::translateActiveException(); std::string exceptionMessage = Catch::translateActiveException();
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString ); MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
handler.handle( expr ); handler.handleExpr( expr );
} }
} // namespace Catch } // namespace Catch

View File

@@ -9,9 +9,12 @@
#define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
#include "catch_capture.hpp" #include "catch_capture.hpp"
#include "catch_matchers.hpp" #include "catch_matchers.h"
#include "catch_matchers_floating.h"
#include "catch_matchers_generic.hpp"
#include "catch_matchers_string.h" #include "catch_matchers_string.h"
#include "catch_matchers_vector.h" #include "catch_matchers_vector.h"
#include "catch_stringref.h"
namespace Catch { namespace Catch {
@@ -20,18 +23,14 @@ namespace Catch {
ArgT const& m_arg; ArgT const& m_arg;
MatcherT m_matcher; MatcherT m_matcher;
StringRef m_matcherString; StringRef m_matcherString;
bool m_result;
public: public:
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
: m_arg( arg ), : ITransientExpression{ true, matcher.match( arg ) },
m_arg( arg ),
m_matcher( matcher ), m_matcher( matcher ),
m_matcherString( matcherString ), m_matcherString( matcherString )
m_result( matcher.match( arg ) )
{} {}
auto isBinaryExpression() const -> bool override { return true; }
auto getResult() const -> bool override { return m_result; }
void streamReconstructedExpression( std::ostream &os ) const override { void streamReconstructedExpression( std::ostream &os ) const override {
auto matcherAsString = m_matcher.toString(); auto matcherAsString = m_matcher.toString();
os << Catch::Detail::stringify( m_arg ) << ' '; os << Catch::Detail::stringify( m_arg ) << ' ';
@@ -44,10 +43,10 @@ namespace Catch {
using StringMatcher = Matchers::Impl::MatcherBase<std::string>; using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString );
template<typename ArgT, typename MatcherT> template<typename ArgT, typename MatcherT>
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> { auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> {
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
} }
@@ -57,32 +56,32 @@ namespace Catch {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ INTERNAL_CATCH_TRY { \
catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
static_cast<void>(__VA_ARGS__ ); \ static_cast<void>(__VA_ARGS__ ); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( exceptionType const& ex ) { \ catch( exceptionType const& ex ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
} \ } \
catch( ... ) { \ catch( ... ) { \
catchAssertionHandler.useActiveException(); \ catchAssertionHandler.handleUnexpectedInflightException(); \
} \ } \
else \ else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() ) } while( false )
#endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED

View File

@@ -16,9 +16,18 @@
#endif #endif
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wshadow"
#endif
#include "../external/clara.hpp" #include "../external/clara.hpp"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
// Restore Clara's value for console width, if present // Restore Clara's value for console width, if present
#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH

View File

@@ -6,7 +6,7 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#include "catch_commandline.hpp" #include "catch_commandline.h"
#include "catch_string_manip.h" #include "catch_string_manip.h"
@@ -20,9 +20,19 @@ namespace Catch {
using namespace clara; using namespace clara;
auto const setWarning = [&]( std::string const& warning ) { 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 + "'" ); 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 ); return ParserResult::ok( ParseResultType::Matched );
}; };
auto const loadTestNamesFromFile = [&]( std::string const& filename ) { auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
@@ -98,84 +108,84 @@ namespace Catch {
auto cli auto cli
= ExeName( config.processName ) = ExeName( config.processName )
+ Help( config.showHelp ) | Help( config.showHelp )
+ Opt( config.listTests ) | Opt( config.listTests )
["-l"]["--list-tests"] ["-l"]["--list-tests"]
( "list all/matching test cases" ) ( "list all/matching test cases" )
+ Opt( config.listTags ) | Opt( config.listTags )
["-t"]["--list-tags"] ["-t"]["--list-tags"]
( "list all/matching tags" ) ( "list all/matching tags" )
+ Opt( config.showSuccessfulTests ) | Opt( config.showSuccessfulTests )
["-s"]["--success"] ["-s"]["--success"]
( "include successful tests in output" ) ( "include successful tests in output" )
+ Opt( config.shouldDebugBreak ) | Opt( config.shouldDebugBreak )
["-b"]["--break"] ["-b"]["--break"]
( "break into debugger on failure" ) ( "break into debugger on failure" )
+ Opt( config.noThrow ) | Opt( config.noThrow )
["-e"]["--nothrow"] ["-e"]["--nothrow"]
( "skip exception tests" ) ( "skip exception tests" )
+ Opt( config.showInvisibles ) | Opt( config.showInvisibles )
["-i"]["--invisibles"] ["-i"]["--invisibles"]
( "show invisibles (tabs, newlines)" ) ( "show invisibles (tabs, newlines)" )
+ Opt( config.outputFilename, "filename" ) | Opt( config.outputFilename, "filename" )
["-o"]["--out"] ["-o"]["--out"]
( "output filename" ) ( "output filename" )
+ Opt( config.reporterNames, "name" ) | Opt( config.reporterName, "name" )
["-r"]["--reporter"] ["-r"]["--reporter"]
( "reporter to use (defaults to console)" ) ( "reporter to use (defaults to console)" )
+ Opt( config.name, "name" ) | Opt( config.name, "name" )
["-n"]["--name"] ["-n"]["--name"]
( "suite name" ) ( "suite name" )
+ Opt( [&]( bool ){ config.abortAfter = 1; } ) | Opt( [&]( bool ){ config.abortAfter = 1; } )
["-a"]["--abort"] ["-a"]["--abort"]
( "abort at first failure" ) ( "abort at first failure" )
+ Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
["-x"]["--abortx"] ["-x"]["--abortx"]
( "abort after x failures" ) ( "abort after x failures" )
+ Opt( setWarning, "warning name" ) | Opt( setWarning, "warning name" )
["-w"]["--warn"] ["-w"]["--warn"]
( "enable warnings" ) ( "enable warnings" )
+ Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
["-d"]["--durations"] ["-d"]["--durations"]
( "show test durations" ) ( "show test durations" )
+ Opt( loadTestNamesFromFile, "filename" ) | Opt( loadTestNamesFromFile, "filename" )
["-f"]["--input-file"] ["-f"]["--input-file"]
( "load test names to run from a file" ) ( "load test names to run from a file" )
+ Opt( config.filenamesAsTags ) | Opt( config.filenamesAsTags )
["-#"]["--filenames-as-tags"] ["-#"]["--filenames-as-tags"]
( "adds a tag for the filename" ) ( "adds a tag for the filename" )
+ Opt( config.sectionsToRun, "section name" ) | Opt( config.sectionsToRun, "section name" )
["-c"]["--section"] ["-c"]["--section"]
( "specify section to run" ) ( "specify section to run" )
+ Opt( setVerbosity, "quiet|normal|high" ) | Opt( setVerbosity, "quiet|normal|high" )
["-v"]["--verbosity"] ["-v"]["--verbosity"]
( "set output verbosity" ) ( "set output verbosity" )
+ Opt( config.listTestNamesOnly ) | Opt( config.listTestNamesOnly )
["--list-test-names-only"] ["--list-test-names-only"]
( "list all/matching test cases names only" ) ( "list all/matching test cases names only" )
+ Opt( config.listReporters ) | Opt( config.listReporters )
["--list-reporters"] ["--list-reporters"]
( "list all reporters" ) ( "list all reporters" )
+ Opt( setTestOrder, "decl|lex|rand" ) | Opt( setTestOrder, "decl|lex|rand" )
["--order"] ["--order"]
( "test case order (defaults to decl)" ) ( "test case order (defaults to decl)" )
+ Opt( setRngSeed, "'time'|number" ) | Opt( setRngSeed, "'time'|number" )
["--rng-seed"] ["--rng-seed"]
( "set a specific seed for random numbers" ) ( "set a specific seed for random numbers" )
+ Opt( setColourUsage, "yes|no" ) | Opt( setColourUsage, "yes|no" )
["--use-colour"] ["--use-colour"]
( "should output be colourised" ) ( "should output be colourised" )
+ Opt( config.libIdentify ) | Opt( config.libIdentify )
["--libidentify"] ["--libidentify"]
( "report name and version according to libidentify standard" ) ( "report name and version according to libidentify standard" )
+ Opt( setWaitForKeypress, "start|exit|both" ) | Opt( setWaitForKeypress, "start|exit|both" )
["--wait-for-keypress"] ["--wait-for-keypress"]
( "waits for a keypress before exiting" ) ( "waits for a keypress before exiting" )
+ Opt( config.benchmarkResolutionMultiple, "multiplier" ) | Opt( config.benchmarkResolutionMultiple, "multiplier" )
["--benchmark-resolution-multiple"] ["--benchmark-resolution-multiple"]
( "multiple of clock resolution to run benchmarks" ) ( "multiple of clock resolution to run benchmarks" )
+ Arg( config.testsOrTags, "test name|pattern|tags" ) | Arg( config.testsOrTags, "test name|pattern|tags" )
( "which test or tests to use" ); ( "which test or tests to use" );
return cli; return cli;

View File

@@ -15,10 +15,6 @@
namespace Catch { namespace Catch {
SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept
: file( _file ),
line( _line )
{}
bool SourceLineInfo::empty() const noexcept { bool SourceLineInfo::empty() const noexcept {
return file[0] == '\0'; return file[0] == '\0';
} }
@@ -26,15 +22,9 @@ namespace Catch {
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
} }
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); // We can assume that the same file will usually have the same pointer.
} // Thus, if the pointers are the same, there is no point in calling the strcmp
return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
void seedRng( IConfig const& config ) {
if( config.rngSeed() != 0 )
std::srand( config.rngSeed() );
}
unsigned int rngSeed() {
return getCurrentContext().getConfig()->rngSeed();
} }
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
@@ -46,12 +36,11 @@ namespace Catch {
return os; return os;
} }
bool isTrue( bool value ){ return value; }
bool alwaysTrue() { return true; }
bool alwaysFalse() { return false; }
std::string StreamEndStop::operator+() const { std::string StreamEndStop::operator+() const {
return std::string(); return std::string();
} }
NonCopyable::NonCopyable() = default;
NonCopyable::~NonCopyable() = default;
} }

View File

@@ -18,17 +18,12 @@
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#endif #endif
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
#include <iosfwd> #include <iosfwd>
#include <string> #include <string>
#include <cstdint> #include <cstdint>
namespace Catch { namespace Catch {
struct IConfig;
struct CaseSensitive { enum Choice { struct CaseSensitive { enum Choice {
Yes, Yes,
No No
@@ -41,14 +36,17 @@ namespace Catch {
NonCopyable& operator = ( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete;
protected: protected:
NonCopyable() {} NonCopyable();
virtual ~NonCopyable(); virtual ~NonCopyable();
}; };
struct SourceLineInfo { struct SourceLineInfo {
SourceLineInfo() = delete; SourceLineInfo() = delete;
SourceLineInfo( char const* _file, std::size_t _line ) noexcept; SourceLineInfo( char const* _file, std::size_t _line ) noexcept
: file( _file ),
line( _line )
{}
SourceLineInfo( SourceLineInfo const& other ) = default; SourceLineInfo( SourceLineInfo const& other ) = default;
SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo( SourceLineInfo && ) = default;
@@ -65,14 +63,6 @@ namespace Catch {
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals
bool isTrue( bool value );
bool alwaysTrue();
bool alwaysFalse();
void seedRng( IConfig const& config );
unsigned int rngSeed();
// Use this in variadic streaming macros to allow // Use this in variadic streaming macros to allow
// >> +StreamEndStop // >> +StreamEndStop
// as well as // as well as

View File

@@ -14,6 +14,7 @@
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
// **************** // ****************
// Note to maintainers: if new toggles are added please document them // Note to maintainers: if new toggles are added please document them
// in configuration.md, too // in configuration.md, too
@@ -24,22 +25,31 @@
// Many features, at point of detection, define an _INTERNAL_ macro, so they // Many features, at point of detection, define an _INTERNAL_ macro, so they
// can be combined, en-mass, with the _NO_ forms later. // can be combined, en-mass, with the _NO_ forms later.
#include "catch_platform.h"
#ifdef __cplusplus #ifdef __cplusplus
# if __cplusplus >= 201402L # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
# define CATCH_CPP14_OR_GREATER # define CATCH_CPP14_OR_GREATER
# endif # endif
# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
# define CATCH_CPP17_OR_GREATER
# endif
#endif
#if defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif #endif
#ifdef __clang__ #ifdef __clang__
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
_Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
_Pragma( "clang diagnostic pop" ) _Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
@@ -48,17 +58,25 @@
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
_Pragma( "clang diagnostic pop" ) _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__ #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 // We know some environments not to support full POSIX signals
#if defined(__CYGWIN__) || defined(__QNX__) #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# endif
#endif #endif
#ifdef __OS400__ #ifdef __OS400__
@@ -66,6 +84,24 @@
# define CATCH_CONFIG_COLOUR_NONE # define CATCH_CONFIG_COLOUR_NONE
#endif #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 // Cygwin
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@@ -73,47 +109,149 @@
// Required for some versions of Cygwin to declare gettimeofday // Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# define _BSD_SOURCE # define _BSD_SOURCE
// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
# endif
#endif // __CYGWIN__ #endif // __CYGWIN__
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Visual C++ // Visual C++
#ifdef _MSC_VER #ifdef _MSC_VER
#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# 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)
# define CATCH_CONFIG_COLOUR_NONE
# else
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif
#endif // _MSC_VER #endif // _MSC_VER
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Check if we are compiled with -fno-exceptions or equivalent
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
#endif
// All supported compilers support COUNTER macro, ////////////////////////////////////////////////////////////////////////////////
//but user still might want to turn it off // DJGPP
#define CATCH_INTERNAL_CONFIG_COUNTER #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.
// Otherwise all supported compilers support COUNTER macro,
// but user still might want to turn it off
#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
////////////////////////////////////////////////////////////////////////////////
// Check if string_view is available and usable
// The check is split apart to work around v140 (VS2015) preprocessor issue...
#if defined(__has_include)
#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
#endif
#endif
////////////////////////////////////////////////////////////////////////////////
// Check if variant is available and usable
#if defined(__has_include)
# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
# if defined(__clang__) && (__clang_major__ < 8)
// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
// fix should be in clang 8, workaround in libstdc++ 8.2
# include <ciso646>
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
# define CATCH_CONFIG_NO_CPP17_VARIANT
# else
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
# endif // defined(__clang__) && (__clang_major__ < 8)
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
#endif // __has_include
// Now set the actual defines based on the above + anything the user has configured #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
// This does not affect compilation
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
# define CATCH_CONFIG_COUNTER # define CATCH_CONFIG_COUNTER
#endif #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 # define CATCH_CONFIG_WINDOWS_SEH
#endif #endif
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. // 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 # define CATCH_CONFIG_POSIX_SIGNALS
#endif #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_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
# define CATCH_CONFIG_CPP17_STRING_VIEW
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
# define CATCH_CONFIG_CPP17_VARIANT
#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_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
# define CATCH_CONFIG_DISABLE_EXCEPTIONS
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
#endif #endif
#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_ETD_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
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
#define CATCH_TRY if ((true))
#define CATCH_CATCH_ALL if ((false))
#define CATCH_CATCH_ANON(type) if ((false))
#else
#define CATCH_TRY try
#define CATCH_CATCH_ALL catch (...)
#define CATCH_CATCH_ANON(type) catch (type)
#endif #endif

View File

@@ -7,7 +7,7 @@
#include "catch_config.hpp" #include "catch_config.hpp"
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_stream.h" #include "catch_stringref.h"
namespace Catch { namespace Catch {
@@ -15,12 +15,16 @@ namespace Catch {
: m_data( data ), : m_data( data ),
m_stream( openStream() ) 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 ) for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags ); parser.parse( testOrTags );
m_testSpec = parser.testSpec();
} }
m_testSpec = parser.testSpec();
} }
std::string const& Config::getFilename() const { std::string const& Config::getFilename() const {
@@ -33,11 +37,13 @@ namespace Catch {
bool Config::listReporters() const { return m_data.listReporters; } bool Config::listReporters() const { return m_data.listReporters; }
std::string Config::getProcessName() const { return m_data.processName; } 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; } std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
TestSpec const& Config::testSpec() const { return m_testSpec; } TestSpec const& Config::testSpec() const { return m_testSpec; }
bool Config::hasTestFilters() const { return m_hasTestFilters; }
bool Config::showHelp() const { return m_data.showHelp; } bool Config::showHelp() const { return m_data.showHelp; }
@@ -46,7 +52,8 @@ namespace Catch {
std::ostream& Config::stream() const { return m_stream->stream(); } 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; } 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::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; } ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; } unsigned int Config::rngSeed() const { return m_data.rngSeed; }
@@ -58,16 +65,7 @@ namespace Catch {
Verbosity Config::verbosity() const { return m_data.verbosity; } Verbosity Config::verbosity() const { return m_data.verbosity; }
IStream const* Config::openStream() { IStream const* Config::openStream() {
if( m_data.outputFilename.empty() ) return Catch::makeStream(m_data.outputFilename);
return new CoutStream();
else if( m_data.outputFilename[0] == '%' ) {
if( m_data.outputFilename == "%debug" )
return new DebugOutStream();
else
CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" );
}
else
return new FileStream( m_data.outputFilename );
} }
} // end namespace Catch } // end namespace Catch

View File

@@ -8,9 +8,12 @@
#ifndef TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
#include "catch_test_spec_parser.hpp" #include "catch_test_spec_parser.h"
#include "catch_interfaces_config.h" #include "catch_interfaces_config.h"
// Libstdc++ doesn't like incomplete classes for unique_ptr
#include "catch_stream.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <string> #include <string>
@@ -51,15 +54,18 @@ namespace Catch {
std::string outputFilename; std::string outputFilename;
std::string name; std::string name;
std::string processName; 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> testsOrTags;
std::vector<std::string> sectionsToRun; std::vector<std::string> sectionsToRun;
}; };
class Config : public IConfig { class Config : public IConfig {
virtual void dummy();
public: public:
Config() = default; Config() = default;
@@ -74,11 +80,13 @@ namespace Catch {
bool listReporters() const; bool listReporters() const;
std::string getProcessName() 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; std::vector<std::string> const& getSectionsToRun() const override;
virtual TestSpec const& testSpec() const override; virtual TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const; bool showHelp() const;
@@ -88,6 +96,7 @@ namespace Catch {
std::string name() const override; std::string name() const override;
bool includeSuccessfulResults() const override; bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override; bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override;
ShowDurations::OrNot showDurations() const override; ShowDurations::OrNot showDurations() const override;
RunTests::InWhatOrder runOrder() const override; RunTests::InWhatOrder runOrder() const override;
unsigned int rngSeed() const override; unsigned int rngSeed() const override;
@@ -105,6 +114,7 @@ namespace Catch {
std::unique_ptr<IStream const> m_stream; std::unique_ptr<IStream const> m_stream;
TestSpec m_testSpec; TestSpec m_testSpec;
bool m_hasTestFilters = false;
}; };
} // end namespace Catch } // end namespace Catch

View File

@@ -6,13 +6,24 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#include "catch_console_colour.hpp"
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wexit-time-destructors"
#endif
#include "catch_console_colour.h"
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_errno_guard.h" #include "catch_errno_guard.h"
#include "catch_interfaces_config.h" #include "catch_interfaces_config.h"
#include "catch_stream.h" #include "catch_stream.h"
#include "catch_context.h" #include "catch_context.h"
#include "catch_platform.h" #include "catch_platform.h"
#include "catch_debugger.h"
#include "catch_windows_h_proxy.h"
#include <sstream>
namespace Catch { namespace Catch {
namespace { namespace {
@@ -45,8 +56,6 @@ namespace Catch {
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
#include "catch_windows_h_proxy.h"
namespace Catch { namespace Catch {
namespace { namespace {
@@ -75,8 +84,12 @@ namespace {
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
default:
CATCH_ERROR( "Unknown colour requested" );
} }
} }
@@ -134,8 +147,10 @@ namespace {
case Colour::BrightRed: return setColour( "[1;31m" ); case Colour::BrightRed: return setColour( "[1;31m" );
case Colour::BrightGreen: return setColour( "[1;32m" ); case Colour::BrightGreen: return setColour( "[1;32m" );
case Colour::BrightWhite: return setColour( "[1;37m" ); case Colour::BrightWhite: return setColour( "[1;37m" );
case Colour::BrightYellow: return setColour( "[1;33m" );
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
} }
} }
static IColourImpl* instance() { static IColourImpl* instance() {
@@ -149,6 +164,18 @@ namespace {
} }
}; };
bool useColourOnPlatform() {
return
#ifdef CATCH_PLATFORM_MAC
!isDebuggerActive() &&
#endif
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
isatty(STDOUT_FILENO)
#else
false
#endif
;
}
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
ErrnoGuard guard; ErrnoGuard guard;
IConfigPtr config = getCurrentContext().getConfig(); IConfigPtr config = getCurrentContext().getConfig();
@@ -156,7 +183,7 @@ namespace {
? config->useColour() ? config->useColour()
: UseColour::Auto; : UseColour::Auto;
if( colourMode == UseColour::Auto ) if( colourMode == UseColour::Auto )
colourMode = isatty(STDOUT_FILENO) colourMode = useColourOnPlatform()
? UseColour::Yes ? UseColour::Yes
: UseColour::No; : UseColour::No;
return colourMode == UseColour::Yes return colourMode == UseColour::Yes
@@ -180,7 +207,7 @@ namespace Catch {
namespace Catch { namespace Catch {
Colour::Colour( Code _colourCode ) { use( _colourCode ); } Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour::Colour( Colour&& rhs ) noexcept { Colour::Colour( Colour&& rhs ) noexcept {
m_moved = rhs.m_moved; m_moved = rhs.m_moved;
rhs.m_moved = true; rhs.m_moved = true;
} }
@@ -189,7 +216,7 @@ namespace Catch {
rhs.m_moved = true; rhs.m_moved = true;
return *this; return *this;
} }
Colour::~Colour(){ if( !m_moved ) use( None ); } Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) { void Colour::use( Code _colourCode ) {
@@ -202,3 +229,8 @@ namespace Catch {
} }
} // end namespace Catch } // end namespace Catch
#if defined(__clang__)
# pragma clang diagnostic pop
#endif

View File

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

View File

@@ -20,10 +20,12 @@ namespace Catch {
return m_runner; return m_runner;
} }
virtual IConfigPtr getConfig() const override { virtual IConfigPtr const& getConfig() const override {
return m_config; return m_config;
} }
virtual ~Context() override;
public: // IMutableContext public: // IMutableContext
virtual void setResultCapture( IResultCapture* resultCapture ) override { virtual void setResultCapture( IResultCapture* resultCapture ) override {
m_resultCapture = resultCapture; m_resultCapture = resultCapture;
@@ -43,20 +45,18 @@ namespace Catch {
IResultCapture* m_resultCapture = nullptr; IResultCapture* m_resultCapture = nullptr;
}; };
namespace { IMutableContext *IMutableContext::currentContext = nullptr;
Context* currentContext = nullptr;
} void IMutableContext::createContext()
IMutableContext& getCurrentMutableContext() { {
if( !currentContext ) currentContext = new Context();
currentContext = new Context();
return *currentContext;
}
IContext& getCurrentContext() {
return getCurrentMutableContext();
} }
void cleanUpContext() { void cleanUpContext() {
delete currentContext; delete IMutableContext::currentContext;
currentContext = nullptr; IMutableContext::currentContext = nullptr;
} }
IContext::~IContext() = default;
IMutableContext::~IMutableContext() = default;
Context::~Context() = default;
} }

View File

@@ -12,33 +12,48 @@
namespace Catch { namespace Catch {
class TestCase;
class Stream;
struct IResultCapture; struct IResultCapture;
struct IRunner; struct IRunner;
struct IConfig; struct IConfig;
struct IMutableContext;
using IConfigPtr = std::shared_ptr<IConfig const>; using IConfigPtr = std::shared_ptr<IConfig const>;
struct IContext struct IContext
{ {
virtual ~IContext() = default; virtual ~IContext();
virtual IResultCapture* getResultCapture() = 0; virtual IResultCapture* getResultCapture() = 0;
virtual IRunner* getRunner() = 0; virtual IRunner* getRunner() = 0;
virtual IConfigPtr getConfig() const = 0; virtual IConfigPtr const& getConfig() const = 0;
}; };
struct IMutableContext : IContext struct IMutableContext : IContext
{ {
virtual ~IMutableContext() = default; virtual ~IMutableContext();
virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
virtual void setRunner( IRunner* runner ) = 0; virtual void setRunner( IRunner* runner ) = 0;
virtual void setConfig( IConfigPtr const& config ) = 0; virtual void setConfig( IConfigPtr const& config ) = 0;
private:
static IMutableContext *currentContext;
friend IMutableContext& getCurrentMutableContext();
friend void cleanUpContext();
static void createContext();
}; };
IContext& getCurrentContext(); inline IMutableContext& getCurrentMutableContext()
IMutableContext& getCurrentMutableContext(); {
if( !IMutableContext::currentContext )
IMutableContext::createContext();
return *IMutableContext::currentContext;
}
inline IContext& getCurrentContext()
{
return getCurrentMutableContext();
}
void cleanUpContext(); void cleanUpContext();
} }

View File

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

View File

@@ -14,13 +14,15 @@
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
#include <assert.h> # include <assert.h>
#include <stdbool.h> # include <stdbool.h>
#include <sys/types.h> # include <sys/types.h>
#include <unistd.h> # include <unistd.h>
#include <sys/sysctl.h> # include <sys/sysctl.h>
# include <cstddef>
# include <ostream>
namespace Catch{ namespace Catch {
// The following function is taken directly from the following technical note: // The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
@@ -31,7 +33,7 @@
int mib[4]; int mib[4];
struct kinfo_proc info; struct kinfo_proc info;
size_t size; std::size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre // Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result. // reason, we get a predictable result.

View File

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

View File

@@ -11,7 +11,9 @@
namespace Catch { namespace Catch {
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { ITransientExpression::~ITransientExpression() = default;
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
if( lhs.size() + rhs.size() < 40 && if( lhs.size() + rhs.size() < 40 &&
lhs.find('\n') == std::string::npos && lhs.find('\n') == std::string::npos &&
rhs.find('\n') == std::string::npos ) rhs.find('\n') == std::string::npos )

View File

@@ -11,47 +11,53 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include "catch_stringref.h" #include "catch_stringref.h"
#include <ostream> #include <iosfwd>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
#pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4018) // more "signed/unsigned mismatch"
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
#pragma warning(disable:4180) // qualifier applied to function type has no meaning
#endif #endif
namespace Catch { namespace Catch {
struct ITransientExpression { struct ITransientExpression {
virtual auto isBinaryExpression() const -> bool = 0; auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
virtual auto getResult() const -> bool = 0; auto getResult() const -> bool { return m_result; }
virtual void streamReconstructedExpression( std::ostream &os ) const = 0; virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
// We don't actually need a virtual destructore, but many static analysers ITransientExpression( bool isBinaryExpression, bool result )
: m_isBinaryExpression( isBinaryExpression ),
m_result( result )
{}
// We don't actually need a virtual destructor, but many static analysers
// complain if it's not here :-( // complain if it's not here :-(
virtual ~ITransientExpression() = default; virtual ~ITransientExpression();
bool m_isBinaryExpression;
bool m_result;
}; };
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
template<typename LhsT, typename RhsT> template<typename LhsT, typename RhsT>
class BinaryExpr : public ITransientExpression { class BinaryExpr : public ITransientExpression {
bool m_result;
LhsT m_lhs; LhsT m_lhs;
std::string m_op; StringRef m_op;
RhsT m_rhs; RhsT m_rhs;
auto isBinaryExpression() const -> bool override { return true; }
auto getResult() const -> bool override { return m_result; }
void streamReconstructedExpression( std::ostream &os ) const override { void streamReconstructedExpression( std::ostream &os ) const override {
formatReconstructedExpression formatReconstructedExpression
( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
} }
public: public:
BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
: m_result( comparisionResult ), : ITransientExpression{ true, comparisonResult },
m_lhs( lhs ), m_lhs( lhs ),
m_op( op ), m_op( op ),
m_rhs( rhs ) m_rhs( rhs )
@@ -62,83 +68,83 @@ namespace Catch {
class UnaryExpr : public ITransientExpression { class UnaryExpr : public ITransientExpression {
LhsT m_lhs; LhsT m_lhs;
auto isBinaryExpression() const -> bool override { return false; }
auto getResult() const -> bool override { return m_lhs ? true : false; }
void streamReconstructedExpression( std::ostream &os ) const override { void streamReconstructedExpression( std::ostream &os ) const override {
os << Catch::Detail::stringify( m_lhs ); os << Catch::Detail::stringify( m_lhs );
} }
public: public:
UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} explicit UnaryExpr( LhsT lhs )
: ITransientExpression{ false, lhs ? true : false },
m_lhs( lhs )
{}
}; };
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
template<typename LhsT, typename RhsT> template<typename LhsT, typename RhsT>
auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast<LhsT&>( lhs ) == rhs; }; auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
template<typename T> template<typename T>
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }; auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
template<typename T> template<typename T>
auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }; auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
template<typename T> template<typename T>
auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }; auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
template<typename T> template<typename T>
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }; auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
template<typename LhsT, typename RhsT> template<typename LhsT, typename RhsT>
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast<LhsT&>( lhs ) != rhs; }; auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
template<typename T> template<typename T>
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }; auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
template<typename T> template<typename T>
auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }; auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
template<typename T> template<typename T>
auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }; auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
template<typename T> template<typename T>
auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }; auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
template<typename LhsT> template<typename LhsT>
class ExprLhs { class ExprLhs {
LhsT m_lhs; LhsT m_lhs;
public: public:
ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
template<typename RhsT> template<typename RhsT>
auto operator == ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return BinaryExpr<LhsT, RhsT&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
} }
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs ); return { m_lhs == rhs, m_lhs, "==", rhs };
} }
template<typename RhsT> template<typename RhsT>
auto operator != ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return BinaryExpr<LhsT, RhsT&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
} }
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs ); return { m_lhs != rhs, m_lhs, "!=", rhs };
} }
template<typename RhsT> template<typename RhsT>
auto operator > ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs > rhs, m_lhs, ">", rhs ); return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
} }
template<typename RhsT> template<typename RhsT>
auto operator < ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs < rhs, m_lhs, "<", rhs ); return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
} }
template<typename RhsT> template<typename RhsT>
auto operator >= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs >= rhs, m_lhs, ">=", rhs ); return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
} }
template<typename RhsT> template<typename RhsT>
auto operator <= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return BinaryExpr<LhsT, RhsT&>( m_lhs <= rhs, m_lhs, "<=", rhs ); return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
} }
auto makeUnaryExpr() const -> UnaryExpr<LhsT> { auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
return UnaryExpr<LhsT>( m_lhs ); return UnaryExpr<LhsT>{ m_lhs };
} }
}; };
@@ -150,16 +156,13 @@ namespace Catch {
} }
struct Decomposer { struct Decomposer {
template<typename T>
auto operator <= ( T& lhs ) -> ExprLhs<T&> {
return ExprLhs<T&>( lhs );
}
template<typename T> template<typename T>
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
return ExprLhs<T const&>( lhs ); return ExprLhs<T const&>{ lhs };
} }
auto operator <=( bool value ) -> ExprLhs<bool> { auto operator <=( bool value ) -> ExprLhs<bool> {
return ExprLhs<bool>( value ); return ExprLhs<bool>{ value };
} }
}; };

View File

@@ -8,9 +8,11 @@
#ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
#include "catch_session.h"
#ifndef __OBJC__ #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 // Standard C/C++ Win32 Unicode wmain entry point
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
#else #else
@@ -30,7 +32,7 @@ int main (int argc, char * const argv[]) {
#endif #endif
Catch::registerTestMethods(); Catch::registerTestMethods();
int result = Catch::Session().run( argc, (char* const*)argv ); int result = Catch::Session().run( argc, (char**)argv );
#if !CATCH_ARC_ENABLED #if !CATCH_ARC_ENABLED
[pool drain]; [pool drain];

View File

@@ -0,0 +1,19 @@
/*
* Created by Martin on 03/09/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_enforce.h"
namespace Catch {
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
[[noreturn]]
void throw_exception(std::exception const& e) {
Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
<< "The message was: " << e.what() << '\n';
std::terminate();
}
#endif
} // namespace Catch;

View File

@@ -8,17 +8,35 @@
#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED #define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
#include "catch_common.h" #include "catch_common.h"
#include "catch_compiler_capabilities.h"
#include "catch_stream.h"
#include <sstream>
#include <stdexcept> #include <stdexcept>
namespace Catch {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
template <typename Ex>
[[noreturn]]
void throw_exception(Ex const& e) {
throw e;
}
#else // ^^ Exceptions are enabled // Exceptions are disabled vv
[[noreturn]]
void throw_exception(std::exception const& e);
#endif
} // namespace Catch;
#define CATCH_PREPARE_EXCEPTION( type, msg ) \ #define CATCH_PREPARE_EXCEPTION( type, msg ) \
type( static_cast<std::ostringstream&&>( std::ostringstream() << msg ).str() ) type( ( Catch::ReusableStringStream() << msg ).str() )
#define CATCH_INTERNAL_ERROR( msg ) \ #define CATCH_INTERNAL_ERROR( msg ) \
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
#define CATCH_ERROR( msg ) \ #define CATCH_ERROR( msg ) \
throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
#define CATCH_RUNTIME_ERROR( msg ) \
Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
#define CATCH_ENFORCE( condition, msg ) \ #define CATCH_ENFORCE( condition, msg ) \
do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
#endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED #endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED

View File

@@ -6,8 +6,10 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#include "catch_assertionhandler.h"
#include "catch_exception_translator_registry.h" #include "catch_exception_translator_registry.h"
#include "catch_assertionhandler.h"
#include "catch_compiler_capabilities.h"
#include "catch_enforce.h"
#ifdef __OBJC__ #ifdef __OBJC__
#import "Foundation/Foundation.h" #import "Foundation/Foundation.h"
@@ -22,6 +24,7 @@ namespace Catch {
m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) ); m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
} }
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
std::string ExceptionTranslatorRegistry::translateActiveException() const { std::string ExceptionTranslatorRegistry::translateActiveException() const {
try { try {
#ifdef __OBJC__ #ifdef __OBJC__
@@ -30,14 +33,25 @@ namespace Catch {
return tryTranslators(); return tryTranslators();
} }
@catch (NSException *exception) { @catch (NSException *exception) {
return Catch::toString( [exception description] ); return Catch::Detail::stringify( [exception description] );
} }
#else #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(); return tryTranslators();
#endif #endif
} }
catch( TestFailureException& ) { catch( TestFailureException& ) {
throw; std::rethrow_exception(std::current_exception());
} }
catch( std::exception& ex ) { catch( std::exception& ex ) {
return ex.what(); return ex.what();
@@ -53,9 +67,16 @@ namespace Catch {
} }
} }
#else // ^^ Exceptions are enabled // Exceptions are disabled vv
std::string ExceptionTranslatorRegistry::translateActiveException() const {
CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
}
#endif
std::string ExceptionTranslatorRegistry::tryTranslators() const { std::string ExceptionTranslatorRegistry::tryTranslators() const {
if( m_translators.empty() ) if( m_translators.empty() )
throw; std::rethrow_exception(std::current_exception());
else else
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
} }

View File

@@ -8,6 +8,13 @@
#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED #define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED
#include "../reporters/catch_reporter_bases.hpp" #include "../reporters/catch_reporter_bases.hpp"
#include "catch_console_colour.h"
#include "catch_reporter_registrars.hpp" #include "catch_reporter_registrars.hpp"
// Allow users to base their work off existing reporters
#include "../reporters/catch_reporter_compact.h"
#include "../reporters/catch_reporter_console.h"
#include "../reporters/catch_reporter_junit.h"
#include "../reporters/catch_reporter_xml.h"
#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED #endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED

View File

@@ -12,26 +12,23 @@
#include "catch_context.h" #include "catch_context.h"
#include "catch_interfaces_capture.h" #include "catch_interfaces_capture.h"
namespace Catch { #if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
namespace {
// Report the error condition // Report the error condition
void reportFatal( std::string const& message ) { void reportFatal( char const * const message ) {
IContext& context = Catch::getCurrentContext(); Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
IResultCapture* resultCapture = context.getResultCapture();
resultCapture->handleFatalErrorCondition( message );
} }
} // namespace Catch
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch {
void FatalConditionHandler::reset() {}
} }
# else // CATCH_CONFIG_WINDOWS_SEH is defined #endif // signals/SEH handling
#if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch { namespace Catch {
struct SignalDefs { DWORD id; const char* name; }; struct SignalDefs { DWORD id; const char* name; };
@@ -39,7 +36,7 @@ namespace Catch {
// There is no 1-1 mapping between signals and windows exceptions. // There is no 1-1 mapping between signals and windows exceptions.
// Windows can easily distinguish between SO and SigSegV, // Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently. // but SigInt, SigTerm, etc are handled differently.
SignalDefs signalDefs[] = { static SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
@@ -71,7 +68,6 @@ namespace Catch {
void FatalConditionHandler::reset() { void FatalConditionHandler::reset() {
if (isSet) { if (isSet) {
// Unregister handler and restore the old guarantee
RemoveVectoredExceptionHandler(exceptionHandlerHandle); RemoveVectoredExceptionHandler(exceptionHandlerHandle);
SetThreadStackGuarantee(&guaranteeSize); SetThreadStackGuarantee(&guaranteeSize);
exceptionHandlerHandle = nullptr; exceptionHandlerHandle = nullptr;
@@ -90,20 +86,7 @@ PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
} // namespace Catch } // namespace Catch
# endif // CATCH_CONFIG_WINDOWS_SEH #elif defined( CATCH_CONFIG_POSIX_SIGNALS )
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
namespace Catch {
void FatalConditionHandler::reset() {}
}
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
#include <signal.h>
namespace Catch { namespace Catch {
@@ -111,7 +94,12 @@ namespace Catch {
int id; int id;
const char* name; const char* name;
}; };
SignalDefs signalDefs[] = {
// 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" }, { SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" }, { SIGILL, "SIGILL - Illegal instruction signal" },
{ SIGFPE, "SIGFPE - Floating point error signal" }, { SIGFPE, "SIGFPE - Floating point error signal" },
@@ -122,7 +110,7 @@ namespace Catch {
void FatalConditionHandler::handleSignal( int sig ) { void FatalConditionHandler::handleSignal( int sig ) {
std::string name = "<unknown signal>"; char const * name = "<unknown signal>";
for (auto const& def : signalDefs) { for (auto const& def : signalDefs) {
if (sig == def.id) { if (sig == def.id) {
name = def.name; name = def.name;
@@ -138,7 +126,7 @@ namespace Catch {
isSet = true; isSet = true;
stack_t sigStack; stack_t sigStack;
sigStack.ss_sp = altStackMem; sigStack.ss_sp = altStackMem;
sigStack.ss_size = SIGSTKSZ; sigStack.ss_size = sigStackSize;
sigStack.ss_flags = 0; sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack); sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { }; struct sigaction sa = { };
@@ -170,11 +158,19 @@ namespace Catch {
bool FatalConditionHandler::isSet = false; bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {}; stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; char FatalConditionHandler::altStackMem[sigStackSize] = {};
} // namespace Catch } // 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
#endif

View File

@@ -9,29 +9,12 @@
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
#include <string>
#include "catch_platform.h" #include "catch_platform.h"
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
namespace Catch {
// Report the error condition
void reportFatal( std::string const& message );
} // namespace Catch
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
#include "catch_windows_h_proxy.h" #include "catch_windows_h_proxy.h"
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch { #if defined( CATCH_CONFIG_WINDOWS_SEH )
struct FatalConditionHandler {
void reset();
};
}
# else // CATCH_CONFIG_WINDOWS_SEH is defined
namespace Catch { namespace Catch {
@@ -50,20 +33,7 @@ namespace Catch {
} // namespace Catch } // namespace Catch
# endif // CATCH_CONFIG_WINDOWS_SEH #elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
namespace Catch {
struct FatalConditionHandler {
void reset();
};
}
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
#include <signal.h> #include <signal.h>
@@ -72,7 +42,7 @@ namespace Catch {
struct FatalConditionHandler { struct FatalConditionHandler {
static bool isSet; static bool isSet;
static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; static struct sigaction oldSigActions[];
static stack_t oldSigStack; static stack_t oldSigStack;
static char altStackMem[]; static char altStackMem[];
@@ -85,8 +55,15 @@ namespace Catch {
} // 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 #endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED

View File

@@ -0,0 +1,50 @@
/*
* Created by Phil Nash on 15/6/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_generators.hpp"
#include "catch_random_number_generator.h"
#include "catch_interfaces_capture.h"
#include <limits>
#include <set>
namespace Catch {
IGeneratorTracker::~IGeneratorTracker() {}
namespace Generators {
GeneratorBase::~GeneratorBase() {}
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ) {
assert( selectionSize <= sourceSize );
std::vector<size_t> indices;
indices.reserve( selectionSize );
std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
std::set<size_t> seen;
// !TBD: improve this algorithm
while( indices.size() < selectionSize ) {
auto index = uid( rng() );
if( seen.insert( index ).second )
indices.push_back( index );
}
return indices;
}
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
return getResultCapture().acquireGeneratorTracker( lineInfo );
}
template<>
auto all<int>() -> Generator<int> {
return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
}
} // namespace Generators
} // namespace Catch

View File

@@ -0,0 +1,253 @@
/*
* Created by Phil Nash on 15/6/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_GENERATORS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
#include "catch_interfaces_generatortracker.h"
#include "catch_common.h"
#include "catch_enforce.h"
#include <memory>
#include <vector>
#include <cassert>
#include <utility>
namespace Catch {
namespace Generators {
// !TBD move this into its own location?
namespace pf{
template<typename T, typename... Args>
std::unique_ptr<T> make_unique( Args&&... args ) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
template<typename T>
struct IGenerator {
virtual ~IGenerator() {}
virtual auto get( size_t index ) const -> T = 0;
};
template<typename T>
class SingleValueGenerator : public IGenerator<T> {
T m_value;
public:
SingleValueGenerator( T const& value ) : m_value( value ) {}
auto get( size_t ) const -> T override {
return m_value;
}
};
template<typename T>
class FixedValuesGenerator : public IGenerator<T> {
std::vector<T> m_values;
public:
FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
auto get( size_t index ) const -> T override {
return m_values[index];
}
};
template<typename T>
class RangeGenerator : public IGenerator<T> {
T const m_first;
T const m_last;
public:
RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) {
assert( m_last > m_first );
}
auto get( size_t index ) const -> T override {
// ToDo:: introduce a safe cast to catch potential overflows
return static_cast<T>(m_first+index);
}
};
template<typename T>
struct NullGenerator : IGenerator<T> {
auto get( size_t ) const -> T override {
CATCH_INTERNAL_ERROR("A Null Generator is always empty");
}
};
template<typename T>
class Generator {
std::unique_ptr<IGenerator<T>> m_generator;
size_t m_size;
public:
Generator( size_t size, std::unique_ptr<IGenerator<T>> generator )
: m_generator( std::move( generator ) ),
m_size( size )
{}
auto size() const -> size_t { return m_size; }
auto operator[]( size_t index ) const -> T {
assert( index < m_size );
return m_generator->get( index );
}
};
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize );
template<typename T>
class GeneratorRandomiser : public IGenerator<T> {
Generator<T> m_baseGenerator;
std::vector<size_t> m_indices;
public:
GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems )
: m_baseGenerator( std::move( baseGenerator ) ),
m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
{}
auto get( size_t index ) const -> T override {
return m_baseGenerator[m_indices[index]];
}
};
template<typename T>
struct RequiresASpecialisationFor;
template<typename T>
auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); }
template<>
auto all<int>() -> Generator<int>;
template<typename T>
auto range( T const& first, T const& last ) -> Generator<T> {
return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) );
}
template<typename T>
auto random( T const& first, T const& last ) -> Generator<T> {
auto gen = range( first, last );
auto size = gen.size();
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
}
template<typename T>
auto random( size_t size ) -> Generator<T> {
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
}
template<typename T>
auto values( std::initializer_list<T> values ) -> Generator<T> {
return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) );
}
template<typename T>
auto value( T const& val ) -> Generator<T> {
return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
}
template<typename T>
auto as() -> Generator<T> {
return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
}
template<typename... Ts>
auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> {
return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
}
template<typename T>
struct Generators : GeneratorBase {
std::vector<Generator<T>> m_generators;
using type = T;
Generators() : GeneratorBase( 0 ) {}
void populate( T&& val ) {
m_size += 1;
m_generators.emplace_back( value( std::move( val ) ) );
}
template<typename U>
void populate( U&& val ) {
populate( T( std::move( val ) ) );
}
void populate( Generator<T>&& generator ) {
m_size += generator.size();
m_generators.emplace_back( std::move( generator ) );
}
template<typename U, typename... Gs>
void populate( U&& valueOrGenerator, Gs... moreGenerators ) {
populate( std::forward<U>( valueOrGenerator ) );
populate( std::forward<Gs>( moreGenerators )... );
}
auto operator[]( size_t index ) const -> T {
size_t sizes = 0;
for( auto const& gen : m_generators ) {
auto localIndex = index-sizes;
sizes += gen.size();
if( index < sizes )
return gen[localIndex];
}
CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')');
}
};
template<typename T, typename... Gs>
auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
Generators<T> generators;
generators.m_generators.reserve( 1+sizeof...(Gs) );
generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
return generators;
}
template<typename T>
auto makeGenerators( Generator<T>&& generator ) -> Generators<T> {
Generators<T> generators;
generators.populate( std::move( generator ) );
return generators;
}
template<typename T, typename... Gs>
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
}
template<typename T, typename U, typename... Gs>
auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators<T> {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
}
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
template<typename L>
// Note: The type after -> is weird, because VS2015 cannot parse
// the expression used in the typedef inside, when it is in
// return type. Yeah, ¯\_(ツ)_/¯
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) {
using UnderlyingType = typename decltype(generatorExpression())::type;
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
if( !tracker.hasGenerator() )
tracker.setGenerator( pf::make_unique<Generators<UnderlyingType>>( generatorExpression() ) );
auto const& generator = static_cast<Generators<UnderlyingType> const&>( *tracker.getGenerator() );
return generator[tracker.getIndex()];
}
} // namespace Generators
} // namespace Catch
#define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED

View File

@@ -8,55 +8,22 @@
#ifndef TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
// Collect all the implementation files together here
// These are the equivalent of what would usually be cpp files
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables" #pragma clang diagnostic ignored "-Wweak-vtables"
#endif #endif
// Keep these here for external reporters
#include "catch_test_spec.h"
#include "catch_test_case_tracker.h"
#include "internal/catch_notimplemented_exception.h" #include "catch_leak_detector.h"
// Temporary hack to fix separately provided reporters
#include "../reporters/catch_reporter_bases.hpp"
#include "catch_reporter_registrars.hpp"
//
#include "internal/catch_leak_detector.h"
#include "../catch_session.hpp"
#include "catch_test_spec.hpp"
#include "catch_test_case_tracker.hpp"
// Cpp files will be included in the single-header file here // Cpp files will be included in the single-header file here
// ~*~* CATCH_CPP_STITCH_PLACE *~*~ // ~*~* CATCH_CPP_STITCH_PLACE *~*~
namespace Catch { namespace Catch {
LeakDetector leakDetector; LeakDetector leakDetector;
// These are all here to avoid warnings about not having any out of line
// virtual methods
NonCopyable::~NonCopyable() {}
IStream::~IStream() noexcept {}
FileStream::~FileStream() noexcept {}
CoutStream::~CoutStream() noexcept {}
DebugOutStream::~DebugOutStream() noexcept {}
StreamBufBase::~StreamBufBase() noexcept {}
IResultCapture::~IResultCapture() {}
ITestInvoker::~ITestInvoker() {}
ITestCaseRegistry::~ITestCaseRegistry() {}
IRegistryHub::~IRegistryHub() {}
IMutableRegistryHub::~IMutableRegistryHub() {}
IExceptionTranslator::~IExceptionTranslator() {}
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
IRunner::~IRunner() {}
IConfig::~IConfig() {}
void Config::dummy() {}
} }
#ifdef __clang__ #ifdef __clang__

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