Compare commits

...

605 Commits

Author SHA1 Message Date
Martin Hořeňovský
00347f1e79 v2.8.0 2019-05-26 22:47:00 +02:00
Martin Hořeňovský
a5a2d08fbb Remove commented out code 2019-05-26 21:19:55 +02:00
Martin Hořeňovský
97602b248b Remove obsolete file with wrong advice 2019-05-25 21:20:37 +02:00
Martin Hořeňovský
e28e162795 Merge pull request #1638 from janisozaur/patch-1
Prevent building in source dir
2019-05-25 21:15:58 +02:00
Martin Hořeňovský
90378f4a59 Have conan test-build the package in a separate subdirectory 2019-05-25 19:58:49 +02:00
Jozef Grajciar
84f8e806b8 Nttp support tests approvals 2019-05-23 21:03:47 +02:00
Jozef Grajciar
732e4b06db docs for signature based parametrised test cases 2019-05-23 21:03:47 +02:00
Jozef Grajciar
0c43f98fa2 Nttp support
Closes #1531
2019-05-23 21:03:47 +02:00
Martin Hořeňovský
bd703dd74b Merge pull request #1611 from cincodenada/unscoped-disabled-prefixed
Add UNSCOPED_INFO to prefix/disabled sections
2019-05-23 14:19:22 +02:00
Martin Hořeňovský
99602787cd Fix error message when unmatched quotes are encountered by CAPTURE
Thanks to @ledvinap for noticing
2019-05-23 13:54:51 +02:00
Michał Janiszewski
bfb4ee1597 Prevent building in source dir
Fixes #1636
2019-05-21 06:38:06 +02:00
Phil Nash
31537c43d9 Rebased approvals 2019-05-21 00:05:39 +01:00
Phil Nash
96355da34e StringRef no longer repoints m_start to m_data after c_str() on a substring.
This fixes an issue where a self-assignment of a StringRef copy would point into internally (and now dangling) data.
(now self-assignment check is no longer needed)
2019-05-21 00:04:44 +01:00
Phil Nash
71fce429af Fix clang warning on self-assignment 2019-05-21 00:04:44 +01:00
Jozef Grajciar
d13e094598 Remove unique type check
Closes #1628
2019-05-20 21:13:05 +02:00
Phil Nash
d30f1dda02 Rebased approvals 2019-05-18 20:53:28 +01:00
Phil Nash
3bce8ba14b Fix StringRef self-assignment after substring
Thanks to Alex Tkachenko for spotting it.
2019-05-18 17:54:39 +01:00
Jozef Grajciar
e680c4b9fb fix SEGFAULT during construction of Session
coloured output tried to write startup exceptions
to stream which was not initialized
2019-05-15 20:14:25 +02:00
mlimber
f1e14a1168 Add missing word 2019-05-09 22:40:59 +02:00
Martin Hořeňovský
92ad9ee355 Merge pull request #1614 from mlimber/master
Allow custom precision in error reports for floating-point numbers
2019-05-03 17:46:03 +02:00
Martin Hořeňovský
e2862a8d71 Add documentation for custom precision in float stringification 2019-05-03 15:40:21 +02:00
Martin Hořeňovský
1161011dd0 Refactor custom precision in floating point stringification
Also fixup tests.
2019-05-03 15:38:06 +02:00
mlimber
53a83e855e Add support for custom precision in floating point stringification
Closes #1612
2019-05-02 21:34:47 +02:00
Petr Ledvina
9c741fe960 Allow quotes in CAPTURE arguments (#1608)
* Allow quotes in CAPTURE arguments

Fix CAPTURE to handle string and character literals properly
2019-05-01 19:12:44 +02:00
Phil nash
979bbf03bb Removed another redundant ; (from docs) 2019-04-27 18:52:38 +01:00
Phil nash
33ce3f3953 added cpp to another code block in docs 2019-04-27 18:51:26 +01:00
Phil nash
87a9424c9d Removed redundant ; 2019-04-27 18:50:05 +01:00
Phil nash
00cb0035c9 Enclosed generated StringMaker for enums in Catch namespace, rather than qualified 2019-04-26 18:24:52 +01:00
Phil nash
6267b06089 Added #include for <memory> (for unique_ptr) 2019-04-26 17:06:44 +01:00
Phil nash
9837c35df1 Rebased approvals for stringified enum tests 2019-04-26 11:30:19 +01:00
Phil nash
46066ede17 Merge branch enum stringification work 2019-04-26 11:26:45 +01:00
Phil nash
6981783178 Added some missing #includes 2019-04-25 14:19:00 +01:00
Phil nash
08c8df1e3b include StringRef, rather than fwd decl, for splitString 2019-04-25 10:32:55 +01:00
Phil nash
daeb5a87e6 Removed global qualification of specialisation 2019-04-25 10:23:58 +01:00
Phil nash
f2ee4f17ad Moved enum tests that depend on internals to IntrospectiveTests.
- also factored out makeEnumInfo, so tests don't need to touch registry
- and added usage test that involves namespace
2019-04-25 10:13:11 +01:00
Wu Yuanshou
182fc3e46e fix example's mistake in slow-compiles.md
the example lack the generation of factorial.o file which lead to an undefined reference error.
2019-04-25 09:48:22 +02:00
Joel Bradshaw
6b5b72651d Add UNSCOPED_INFO to prefix/disabled sections 2019-04-24 12:56:39 -07:00
Joel Bradshaw
f45bb00351 Add failing test for CATCH_UNSCOPED_CAPTURE
Actually fails to compile, which is good
2019-04-24 12:55:11 -07:00
Martin Hořeňovský
7c37501b07 v2.7.2 2019-04-22 23:15:59 +02:00
Martin Hostettler
4a1ca1ab55 TrackerContext: Remove misleading instance static method.
TrackerContext is not used as singleton, so just remove this misleading
method
2019-04-22 16:37:22 +02:00
Phil Nash
e02d9e788f Document CATCH_REGISTER_ENUM 2019-04-21 20:32:20 +03:00
Phil Nash
541f1ed1b3 Only provide CATCH_REGISTER_ENUM
No longer have version without the CATCH_ prefix
2019-04-21 20:26:46 +03:00
Phil Nash
346723c9b6 Renamed STRINGIFY_ENUM to REGISTER_ENUM 2019-04-21 20:15:26 +03:00
Phil Nash
5a74fcc9c9 Removed IEnumInfo (just use EnumInfo directly) 2019-04-21 20:09:58 +03:00
Phil Nash
9d5d719868 Changed splitString to splitStringRef
Now takes and returns StringRefs
2019-04-21 20:03:44 +03:00
Will Handley
91b617c462 Added a vector approximate matcher 2019-04-20 10:02:17 +02:00
Martin Hořeňovský
45e552528d Remove home-rolled algorithm replacements
Previously we had them to avoid including <algorithm> in the vector
matchers, but
* we included it anyway, even though we did not use it
* we use <algorithm> anyways in the generators
2019-04-19 17:54:21 +02:00
Martin Hořeňovský
3978e9653b Add more documentation on contributing 2019-04-18 16:18:30 +02:00
Stephen Newell
d6fce7bf34 Fix warnings generated with -Wshadow 2019-04-18 15:30:38 +02:00
Martin Hořeňovský
c3c82f539c Merge pull request #1336 from ax3l/topic-overrideVirtualRedundant
Refactor: override implies virtual
2019-04-18 14:10:24 +02:00
Martin Hořeňovský
c7653811a6 Add basic CPack support
@ThijsWithaar is responsible for giving me the idea, but his PR
had couple of things that meant it was simpler to rewrite it than
to fix and merge it.

Supersedes and closes #1599
2019-04-18 13:47:33 +02:00
JoeyGrajciar
79417b9afc Revert "draft of nttp support"
This reverts commit 0c39409da7.
2019-04-18 11:35:33 +02:00
JoeyGrajciar
11cdd72db9 Merge remote-tracking branch 'refs/remotes/origin/nttp_support' 2019-04-18 11:26:33 +02:00
Jozef Grajciar
0c39409da7 draft of nttp support
added _SIG macros
2019-04-17 21:41:19 +02:00
Martin Hořeňovský
edfac75347 Add test for omitting the 'Filters' heading when there were none 2019-04-16 23:49:22 +02:00
Martin Luelf
ac94bd0520 ParseAndAddCatchTests: Ignore cmake object libraries 2019-04-14 19:10:15 +02:00
Maciej Patro
d4eec016a9 CatchAddTests now adds tags as labels for ctest
- `ctest --print-labels` now will show list of available labels
- `ctest -L <regex>` will allow to run tests with given labels(tags)
2019-04-14 18:59:53 +02:00
Martin Hořeňovský
36fb856163 Fix JUnit reporter output so that it conforms to JUnit schema
The `properties` can only go under the `testsuite` tag, not under
the `testsuites` tag.

Fixes #1598
2019-04-11 13:04:54 +02:00
Martin Hořeňovský
4e32e0a563 Fix vendored dep because upstream is non-responsive
Eventually this needs to be fixed in the textflow project by Phil,
but he has not done so in the half a year this bug has been known
to be there, so...

Closes #1470
Closes #1455
2019-04-10 20:17:25 +02:00
Daniele E. Domenichelli
1e2270b370 ParseAndAddCatchTests: Do not change CMAKE_MINIMUM_REQUIRED_VERSION when included 2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
5096e39297 ParseAndAddCatchTests: Add scope to functions in order to avoid name collisions 2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
15ccced6da ParseAndAddCatchTests: Document AdditionalCatchParameters variable 2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
682617b5b7 ParseAndAddCatchTests: Fix tests not found
When using an optional launcher the target name is not interpreted as a
target, therefore it is not replaced automatically with its path.
2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
15150c7b46 ParseAndAddCatchTests: Set the ParseAndAddCatchTests_TESTS property
After the script, the ParseAndAddCatchTests_TESTS property for the
target, and for each source file in the target is set, and contains the
list of the tests extracted from that target, or from that file.

This is useful, for example to add further labels or properties to the
tests.
2019-04-10 10:50:13 +02:00
Torfinn Berset
5ce355a38c For macOS builds, disable isDebuggerActive() for non-AppleClang targets. Fixes #1588 2019-04-10 10:19:54 +02:00
Ryan Pavlik
edde6f4736 Fix typos identified by codespell.
Self test baselines also modified accordingly, due to
one typo found in a string in test code.
2019-04-10 09:42:11 +02:00
Martin Hořeňovský
6bc5d172ee Merge pull request #1596 from 50ty/patch-1
IndexOfHideLabel is never used
2019-04-10 09:31:00 +02:00
Stefan Rommel
3079b514d4 IndexOfHideLabel is never used 2019-04-10 08:00:08 +02:00
Martin Hořeňovský
e99f1efd28 Avoid adding a default test spec when none was provided 2019-04-09 11:50:59 +02:00
Martin Hořeňovský
b9dd1936e5 v2.7.1 2019-04-08 13:38:00 +02:00
Martin Hořeňovský
293d617c49 Merge pull request #1592 from robinlinden/fix-cmake-integration-typo
Use correct filename in CMake integration docs
2019-04-08 13:20:41 +02:00
Robin Lindén
7be35af167 Use correct filename in CMake integration docs 2019-04-07 15:41:34 +02:00
Phil nash
02f13cf95a Made onto dev build and regenerated single header 2019-04-04 16:02:58 +01:00
Phil nash
43428c6093 First commit of STRINGIFY_ENUM 2019-04-04 15:55:46 +01:00
Martin Hořeňovský
08147a23f9 Fix ObjC matchers
Closes #1571
2019-04-03 20:32:11 +02:00
Ziv Shahaf
8af8704089 support for printing test filters (PR #1585) 2019-04-03 20:24:52 +02:00
Martin Hořeňovský
3816e99d0c Add GENERATE_COPY and GENERATE_VAR capturing generator macros 2019-03-31 14:11:10 +02:00
Martin Hořeňovský
b77cec05c0 Fix test tag parsing to split [.foo] into [.][foo] 2019-03-29 10:48:56 +01:00
Omer Ozarslan
54089c4c8c Deducing return type of map generator helper (#1576)
* Deduce map return type implicitly

Giving the first template argument to map generator function to deduce
return type is now optional even if the return type is different from
the type generated by mapped generator.
2019-03-24 15:44:22 +01:00
Martin Hořeňovský
296d447452 Merge pull request #1575 from alabuzhev/warning_ntstatus
Suppress warning caused by ntstatus.h inclusion
2019-03-20 15:22:27 +01:00
Alex Alabuzhev
0531965349 Suppress warning caused by ntstatus.h inclusion 2019-03-19 23:57:56 +00:00
Tadeusz Puźniakowski
a1cdff4f18 raspigcd - opensource-users
Added raspigcd that uses Catch2 for tests
2019-03-19 20:35:59 +01:00
Steve Hollasch
4611125801 generators.md: fix extraneous back tick in doc 2019-03-14 09:14:02 +01:00
Clare Macrae
e509012e64 Update blog URL and fic typos in tutorial.md 2019-03-09 18:02:29 +01:00
Clare Macrae
448825db03 Readability improvements for assertions.md 2019-03-09 18:02:29 +01:00
Clare Macrae
0fff8e7791 Add ApprovalTests.cpp to list of open source users 2019-03-09 18:02:29 +01:00
Martin Hořeňovský
68a3c129ac Merge pull request #1562 from claremacrae/patch-2
Update url of blog post
2019-03-09 17:35:08 +01:00
Martin Hořeňovský
1ce5ec9b74 Merge pull request #1565 from inobelar/patch-1
Added override keyword near IntRange::describe() method
2019-03-09 17:33:42 +01:00
Yurii Nakonechnyi
37a4e32319 Added override keyword near IntRange::describe() method 2019-03-09 15:05:27 +02:00
Clare Macrae
0424c9a62c Update url of blog post 2019-03-08 08:56:00 +00:00
Martin Hořeňovský
d633072794 v2.7.0 2019-03-07 21:44:57 +01:00
Martin Hořeňovský
51ed08be22 Take changes to Clara from master 2019-03-07 20:48:36 +01:00
Omer Ozarslan
1701325caa Document unscoped info 2019-03-06 22:04:35 +01:00
Omer Ozarslan
7aee973a4a Add tests for unscoped info
Update approval tests as new tests are added for messaging.
2019-03-06 22:04:35 +01:00
Omer Ozarslan
99575b45db Add unscoped info functionality
This adds UNSCOPED_INFO macro, creating a log message that is stored
until the end of next assertion or the end of test case, whichever comes
first. These messages are not scoped locally, unlike messages created by
INFO macro.
2019-03-06 22:04:35 +01:00
Martin Hořeňovský
1a03918455 Force flush streams in tests for #1514
This avoids the problem where writes to stderr/stdout stop being
line-buffered when stderr/stdout is redirected to a file, which led
to different order of outputs between Linux and Windows in our tests.
2019-03-06 21:53:26 +01:00
Martin Hořeňovský
bd667f4d69 Add comma-escaping in test specs to ParseAndAddCatchTests.cmake
Fixes #1527
2019-03-03 13:11:11 +01:00
Martin Hořeňovský
28db5ed4c9 Add tests for #1514
If the regression comes back, it will only be caught by approvals,
but that's better than nothing.
2019-03-02 21:22:47 +01:00
SimonChh
7d2451f119 Fix output redirection in failing tests (#1525)
Fixes #1514
2019-03-02 21:18:48 +01:00
Martin Hořeňovský
5bf6e47381 Add another example for generators 2019-02-26 12:52:21 +01:00
Martin Hořeňovský
29b3b7ae6b Namespace our type traits in catch_meta
Previously they could conflict with user-defined type traits that
were in the global namespace.

Fixes #1548
2019-02-23 21:06:20 +01:00
Martin Hořeňovský
ef5fd8d42f Add another test for FilterGenerator 2019-02-23 20:37:35 +01:00
Martin Hořeňovský
693647c43f Add ChunkGenerator
This generator collects values from the underlying generator until it
has a specified amount of them, and then returns them in one "chunk".
In case the underlying generator does not have enough elements for
a specific chunk, the left-over elements are discarded.

Closes #1538
2019-02-23 20:28:58 +01:00
Martin Hořeňovský
288387fa10 Cleanup: move things around 2019-02-23 17:16:28 +01:00
Rick de Water
165de9b072 Add RangeGenerator 2019-02-23 16:58:34 +01:00
hbina4326
bf4771a7ed Script helper getBuildExecutable now works properly on Windows 2019-02-23 14:44:40 +01:00
Martin Hořeňovský
7012a31a39 Fix VS2015 warning issue 2019-02-20 10:14:46 +01:00
Martin Hořeňovský
269303d9d9 Introduce random number (Integral and Float) generators 2019-02-20 00:09:15 +01:00
Khem Raj
e8bfd882e8 Fix -Wdefaulted-function-deleted warning
Clang8 warns

catch_interfaces_reporter.h:84:25: error: explicitly defaulted move assignment operator is implicitly deleted [-Werror,-Wdefaulted-function-deleted]
|         AssertionStats& operator = ( AssertionStats && )     = default;
|                         ^

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2019-02-18 20:42:42 +01:00
Paul Lesur
2bd0722470 fix "code will never be executed" under clang 2019-02-18 19:01:43 +01:00
Igor Akhmetov
45ebf17ec7 Do not open the output file twice
7f229b4f caused the output file to get opened twice, while
some types of files (e.g. named pipes) can be only opened once.

After this change Session::applyCommandLine opens the output file
only when there is an error to print.
2019-02-18 18:59:54 +01:00
Martin Hořeňovský
093b72416d Remove non-ASCII characters from the distributable parts
Closes #1542
2019-02-18 10:33:41 +01:00
Tobias Ribizel
c99a346490 Use correct type name instead of index for TEMPLATE_PRODUCT_TEST_CASE (#1544)
Previously, for a TEMPLATE_PRODUCT_TEST_CASE("Test" ..., T, (P1, P2)),
the generated test case names were

  Test - 0
  Test - 1

With this commit, the correct typename is used:

  Test - T<P1>
  Test - T<P2>

-----------

MSVC needs another indirection to evaluate INTERNAL_CATCH_STRINGIZE
and also inserts a space before theINTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS
parameter, which we can get rid of by pointer arithmetic.
2019-02-17 21:52:22 +01:00
Martin Hořeňovský
359a54b6bd Merge pull request #1539 from mattclarke/patch-1
Docs: missing hyphens and full-stops added
2019-02-17 21:24:42 +01:00
Girts Folkmanis
711d750ca7 use "std" namespace for "sprintf"
Some compilers don't export C compatibility functions in `::`. Using
`std::sprintf` should work for those (and all other compilers).

Reference: https://en.cppreference.com/w/cpp/header#C_compatibility_headers
2019-02-17 21:02:21 +01:00
Matt Clarke
95f7712808 Missing hyphens and full-stops added
The use of full-stops is inconsistent, so I have added them where there are none.
The other option was to remove them instead.
2019-02-13 10:13:14 +01:00
Martin Hořeňovský
dbbab8727c v2.6.1 2019-02-12 19:58:12 +01:00
Martin Hořeňovský
5d4061af12 Update release process docs to include PGP-signing 2019-02-12 19:33:08 +01:00
Darren Gilroy
9ccea82d7f Catch: resolve inconsistency in CATCH_REQUIRE_THROWS
The REQUIRE_THROWS and CATCH_REQUIRE_THROWS macros have
a subtle inconsistency in their implementation which can
cause a warning if [-Wunused-value] is used.

This commit changes CATCH_REQUIRE_THROWS so it has the
same implementation as REQUIRE_THROWS

It looks like REQUIRE_THROWS was change in commit
fae0fa4ec but not CATCH_REQUIRE_THROWS.

Similar changes for CATCH_CHECK_THROWS
2019-02-09 17:42:53 +01:00
Berkus Karchebnyy
dd3d27de57 Fix TAP protocol reporter
According to TAP protocol version 13, the comments after the test name
only may contain Directives - # TODO or # SKIP. We should put
the comment (aka suite name) on a separate line before the test.

See http://testanything.org/tap-version-13-specification.html#directives
2019-02-08 10:48:32 +01:00
Jozef Grajciar
7f229b4ff1 fix SEGFAULTs
issue was that mutable context had no config thus trying to get stream
caused SEGFAULT

Closes #1533, #1534
2019-02-08 10:41:23 +01:00
Jozef Grajciar
c03b23c84b Added Makimo to list of commercial users
Closes #1528
2019-02-04 20:04:48 +01:00
Nathaniel Dosé
17686ba571 junit reporter reports random seed (--rng-seed)
Fixes #1520
2019-02-01 10:34:20 +01:00
Martin Hořeňovský
d75e9b3c0f v2.6.0 2019-01-31 22:32:55 +01:00
Martin Hořeňovský
67308bb606 Add documentation for CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
Related to #1510
2019-01-31 15:36:52 +01:00
Robin Moussu
16dc219704 Add to string for std::optional 2019-01-31 15:35:13 +01:00
Martin Hořeňovský
63d1a96908 Merge pull request #1516 from catchorg/dev-generators-take2
This replaces the old interface with a final one.
2019-01-31 14:24:30 +01:00
Martin Hořeňovský
061f1f836a Update documentation and examples for generators 2019-01-31 10:43:25 +01:00
Martin Hořeňovský
5929d9530c Add generic generator modifiers
This means mutiple generic generators and some inference helper
* take(n, generator)
* filter(predicate, generator)
* map(func, generator)
* repeat(generator, repeats)
2019-01-31 10:43:15 +01:00
Martin Hořeňovský
e46a70f829 Redo generator interface 2019-01-31 10:43:06 +01:00
Martin Hořeňovský
64a9c02315 Remove obsolete IndexTracker 2019-01-29 14:45:52 +01:00
Martin Hořeňovský
61f4c7ab85 Remove unused type from tests 2019-01-27 00:03:11 +01:00
Robin Moussu
50fefd059a fix variant detection with non-clang compiler 2019-01-26 18:35:14 +01:00
Robin Moussu
a2baabbf71 Fix variant test for libstdc++ version 9 (#1515)
By using non-trivially copyable types, we force libstdc++-9's variant to
properly enter the valueless-by-exception state for our stringification
test.

Related to #1511
2019-01-26 18:32:17 +01:00
Martin Hořeňovský
6f9cdd6583 Release builds on travis now respect C++17 if specified 2019-01-25 22:51:15 +01:00
Martin Hořeňovský
d9e99dc2ca Improve explanation of why -Wparentheses suppression leaks
Related to #1508
2019-01-25 21:29:12 +01:00
Martin Hořeňovský
804a2118c2 Merge pull request #1452 from drdanz/ParseAddAndCatchTest_DISABLED
ParseAndAddCatchTests: Add PARSE_CATCH_TESTS_HIDDEN_TESTS_DISABLED option
2019-01-23 15:07:03 +01:00
Martin Hořeňovský
aa1e470058 Merge hidden-test-disabled and hidden-test-hidden 2019-01-23 15:05:33 +01:00
Jozef Grajciar
8d5d54e529 Docs: note to INFO 2019-01-22 12:37:03 +01:00
Jozef Grajciar
73d533ff5c Examples: add semicolon after INFO 2019-01-22 12:37:03 +01:00
Jozef Grajciar
899c5ed3df Console Colour: fix compilation 2019-01-19 23:12:54 +01:00
Martin Hořeňovský
084b1d5fe6 Fix colourized output to file
This change should be backwards compatible, but it would be better
to make the console colour API take an argument in the long term.

Fixes #1502
2019-01-19 13:32:39 +01:00
Martin Hořeňovský
4109870435 Merge pull request #1484 from Lotterleben/extend_contributing
contributing.md: Add build instructions
2019-01-19 13:06:06 +01:00
Martin Hořeňovský
2988e9f6cf Update contributing.md to reflect current test setup 2019-01-19 13:05:27 +01:00
Lotte Steenbrink
bc02ada4b0 Add build instructions to contributing.md 2019-01-19 13:05:22 +01:00
Martin Hořeňovský
61e1ea9185 Merge pull request #1492 from Lotterleben/fix_1394
fix #1394: avoid superfluous re-run when specific section is selected
2019-01-18 16:46:40 +01:00
Martin Hořeňovský
b275ead8c3 Remove the obsolete issue template 2019-01-18 15:38:09 +01:00
Martin Hořeňovský
b0381e42b2 Update issue templates
The old template that combined both bug reports and issue requests has led to various weird issues being filed, maybe having a separate one for each will help.
2019-01-18 15:36:34 +01:00
Martin Hořeňovský
8989c9b560 Integrate tests for #1394 into our test suite 2019-01-18 15:14:17 +01:00
Lotte Steenbrink
d084162b2f Avoid superfluous re-run when specific section is selected
Fixes #1394
2019-01-18 15:13:40 +01:00
Torfinn Berset
0387fb64ce Added Bloomlife to list of commercial users 2019-01-14 18:11:38 +01:00
Martin Hořeňovský
75200b462c Change CATCH_BREAK_INTO_DEBUGGER to always expand into a function call
This avoids -Wextra-semi-stmt warning inside our code
2019-01-13 23:22:36 +01:00
Martin Hořeňovský
17e09be3b9 Fix stupid (C4800) warning 2019-01-13 19:01:12 +01:00
Martin Hořeňovský
1c99b0ff81 Minor cleanup in decomposer 2019-01-13 16:23:20 +01:00
Martin Hořeňovský
64a0f466ec Add missing noexcept in move constructors
Because both copy and move operations are trivial, this doesn't
actually change anything, but it silences a static analysis warning.
2019-01-13 16:17:42 +01:00
Axel Huebl
47602ac556 RunContext: Uninit Member
Fix an uninitialized member in `RunContext`.

Found with coverity in a downstream project.
2019-01-13 10:26:47 +01:00
Axel Huebl
d1e7344f16 ClockEstimate: DivByZero
The clock estimator has a potential division by zero.
Using `iteration + 1` seems also more logical to me for
an average.

Found with coverity in a downstream project.
2019-01-11 11:55:51 +01:00
NeroBurner
3ed5441067 fix ctest output with space before name
When PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME is enabled the cmake helper script fails to extract the testcase name if a whitespace is before the name string. Use regex to consider and remove this whitespace.

fix by Mike-Devel
fixes: https://github.com/catchorg/Catch2/issues/1493
2019-01-10 20:09:00 +01:00
Jozef Grajciar
bdee512057 small cleanup of code 2019-01-10 13:07:54 +01:00
Axel Huebl
188b3e6511 hexEscapeChar: restore stream
The ostream passed as reference to `hexEscapeChar` is manipulated
and its original state not restored. This fixes it.

Seen via coverity in a downstream project.
2019-01-10 13:05:36 +01:00
Antonio Mallia
bbf70ca74b Missing <type_traits> include 2019-01-10 12:52:15 +01:00
NeroBurner
23f023f9ed cpp higlighting for test-cases-and-sections.md
add c++ highlighting for the last two examples, all others already have highlighting
2019-01-10 12:29:21 +01:00
Martin Hořeňovský
c1720d0c42 Fix assert message
I messed up copy-paste when modifying the assert messages in last
commit.
2019-01-03 10:14:15 +01:00
hbina4326
d54c2258e0 Add additional static_assert for the REQUIRE(a == b && c == d) case 2019-01-02 22:44:54 +01:00
BiCapitalization
b3faceede2 Add nice error messages for unsupported && and ||
As explained in issue #1273, `operator&&` and `operator||` should give
a proper compile time error on use instead of the compiler complaining
about them not being defined. This commit adds an `always_false` type in
`catch_meta.hpp` used for implementing a nice `static_assert` for both
of the abovementioned operators.

Closes #1273
2019-01-01 19:13:47 +01:00
Uilian Ries
e7fce90b49 Force to install Conan 1.10.2
- Conan Package Tools is not ready for Conan 1.11.x

Signed-off-by: Uilian Ries <uilianries@gmail.com>
2019-01-01 12:22:11 +01:00
Khem Raj
799c7a2eed Remove redundant move to avoid Wredundant-move with Clang
Signed-off-by: Khem Raj <raj.khem@gmail.com>
2018-12-29 22:56:37 +01:00
Martin Hořeňovský
9bc15939a5 Don't use exception-related std:: functions with -fno-exceptions
This doesn't cause trouble with GCC/Clang and libstdc++, but IAR
and its stdlib apparently doesn't compile when you use `fno-exceptions`
and `std::current_exception`/`std::rethrow_exception`.

Fixes #1462
2018-12-18 20:19:39 +01:00
Martin Hořeňovský
461843b1f0 Merge pull request #1468 from JoeyGrajciar/template_product_test_case
Template product test case
2018-12-10 11:39:26 +01:00
Jozef Grajciar
5b4ffd3c93 Docs: added docs for TEMPLATE_PRODUCT_TEST_CASE 2018-12-10 08:24:08 +01:00
Jozef Grajciar
21a1cd5683 Template tests: added TEMPLATE_PRODUCT_TEST_CASE
support for generating test cases based on multiple template template
types combined with template arguments for each of the template template
types specified

e.g.
```
TEMPLATE_PRODUCT_TEST_CASE("template product","[template]",
			   (std::tuple, std::pair, std::map),
			   ((int,float),(char,double),(int,char)))
```
will effectively create 9 test cases with types:
std::tuple<int,float>
std::tuple<char,double>
std::tuple<int,char>
std::pair<int,float>
std::pair<char, double>
std::pair<int,char>
std::map<int,float>
std::map<char,double>
std::map<int,char>

Tested type is accessible in test case body as TestType
Unique name is created by appending ` - <index>` to test name
since preprocessor has some limitations in recursions

Closes #1454
2018-12-10 08:22:09 +01:00
Uilian Ries
4902cd7215 #926 Fix Conan package reference
- Package channel should be changed automatically when
  matching the stable branch pattern
- Update Bintray upload address

Signed-off-by: Uilian Ries <uilianries@gmail.com>
2018-11-28 19:55:47 +01:00
offa
18ff34788c Deprecated 'sudo: false' removed from travis config. 2018-11-26 22:51:23 +01:00
Martin Hořeňovský
d0de666362 Merge pull request #1458 from ndusart/cppcodec
Add cppcodec in opensource users
2018-11-26 21:11:51 +01:00
Martin Hořeňovský
6ccd467094 v2.5.0 2018-11-26 20:50:38 +01:00
Martin Hořeňovský
34dcd2c436 Remove remains of the old conan things from release script 2018-11-26 20:47:40 +01:00
Martin Hořeňovský
16656c4c9e Update the release process documentation 2018-11-26 20:41:14 +01:00
Nicolas Dusart
862955d657 add cppcodec in opensource users 2018-11-26 11:49:14 +01:00
Martin Hořeňovský
df019cc113 Turn "deprecations" into "deprecations and planned changes"
This captures the intent better, as some changes are indeed plain
deprecations leading to removal, but other changes can be viewed
as minor tune-ups instead.
2018-11-24 18:04:56 +01:00
Martin Hořeňovský
695e6eafc5 Merge pull request #1448 from catchorg/dev-redo-capturer-parsing
Fix CAPTURE macro for nontrivial uses
2018-11-21 21:21:03 +01:00
Martin Hořeňovský
59087f74d9 Fix CAPTURE macro for nontrivial uses
The previous implemetation was just plain broken for most of
possible uses, the new one should work (even though it is ugly
as all hell, and should be improved ASAP).

Fixes #1436
2018-11-21 16:48:09 +01:00
Daniele E. Domenichelli
557e47c3ca ParseAndAddCatchTests: Add PARSE_CATCH_TESTS_HIDDEN_TESTS_DISABLED option
If this option is enabled and PARSE_CATCH_TESTS_NO_HIDDEN_TESTS option is disabled, the test is be added, but the DISABLED property is set, therefore CTest shows it as "Not Run (Disabled)" instead of "Passed"
2018-11-21 09:22:17 +01:00
Martin Hořeňovský
62460fafe6 Merge pull request #1443 from uilianries/feature/conanio
Conan recipe Update + Conan package upload
2018-11-19 15:34:40 +01:00
Uilian Ries
ac0a83a35d Update Conan recipe
- Apply new conventions introduced on Conan 1.8
- Removed outdated settings
- Update license to follow SPDX format

Closes #926
Closes #943
2018-11-19 15:27:47 +01:00
Martin Hořeňovský
77f29c2f1c Add more deprecations 2018-11-17 21:13:56 +01:00
Martin Hořeňovský
c6a89f14c2 Add std::isnan polyfill, fixing compilation under Embarcadero
Fixes #1438
2018-11-17 20:52:18 +01:00
Martin Hořeňovský
a9d5b7193d Add note about release signing to release docs 2018-11-17 14:41:34 +01:00
Martin Hořeňovský
396e0951c8 Add ToC to "Test cases and sections" documentation 2018-11-17 11:09:15 +01:00
Martin Hořeňovský
68860ff129 Add deprecations documentation 2018-11-17 11:08:38 +01:00
Martin Hořeňovský
99b37a4c62 Merge pull request #1445 from thecppzoo/master
operator<< works from the global namespace
2018-11-17 10:36:37 +01:00
Martin Hořeňovský
1dccd26de7 Fix link in documentation 2018-11-17 10:21:46 +01:00
thecppzoo
3f3238edf0 operator<< works from the global namespace
Since https://github.com/catchorg/Catch2/pull/1405 was merged and propagated to the single include declaring a user operator<< in the global namespace makes it available to Catch2 string converters.
2018-11-16 16:45:13 -08:00
Martin Hořeňovský
450dd0562b Merge pull request #1437 from JoeyGrajciar/type_params_tests_v2
Type parametrised test cases v2
2018-11-16 21:24:19 +01:00
Martin Hořeňovský
00d4f5d3c6 Add documentation for templated tests 2018-11-16 21:21:30 +01:00
Jozef Grajciar
2d906a92cb Add support for templated tests
This adds support for templated tests and test methods via
`TEMPLATE_TEST_CASE` and `TEMPLATE_TEST_CASE_METHOD` macros. These
work mostly just like their regular counterparts*, but take an
unlimited** number of types as their last arguments.

* Unlike the plain `TEST_CASE*` macros, the `TEMPLATE*` variants
require a tag string.

** In practice there is limit of about 300 types.
2018-11-16 21:21:23 +01:00
Jozef Grajciar
489a41012e ConsoleReporter: minor formatting fix
PASSED will now appear on the same line as filename and line number,
just like the case with FAILED message formatting
2018-11-10 19:35:25 +01:00
Martin Hořeňovský
eccbffec0f Add MSVC warning 5038 (Wreorder equivalent) to CMakeLists 2018-11-05 20:07:33 +01:00
Martin Hořeňovský
c51f2edfb1 Make TestEventListenerBase register all verbosities
This is a temporarily workaround until we can nuke the current
verbosities system from the orbit and replace it with something
actually sane.

Fixes #1426
2018-11-05 20:05:17 +01:00
Martin Hořeňovský
de6bfb5c25 Remove obsolete comment 2018-11-05 20:05:17 +01:00
Antonio Borondo
87950d9cfa Fix Cute test framework URL 2018-11-05 19:38:37 +01:00
Martin Hořeňovský
d0eb9dfb9b Remove unused partial specialization for MatcherMethod<T>
No matcher actually uses it, and there is no good reason for it,
as the best it can do for user is removing a single indirection
when using the pointer inside the matcher. Given the overhead of
other code that will be running during such time, it is completely
meaningless.

This also fixes compilation for PredicateMatcher<const char*>.
2018-11-04 00:00:36 +01:00
Martin Hořeňovský
03d122a35c v2.4.2 2018-10-26 21:14:16 +02:00
Martin Hořeňovský
1d9b506e39 Add documentation for some miscellaneous and less important macros
Fixes #1367
2018-10-26 20:50:32 +02:00
Martin Hořeňovský
779e83bc20 Update Clara to v1.1.5 to fix TextFlow bugs 2018-10-26 18:48:28 +02:00
Stephane Del Pino
544c7d7cbf Add the optional variable OptionalCatchTestLauncher
This variable is set to allow the use of the nice ParseAndAddCatchTests script
in the case where a launcher is needed to execute  the script.

This is introduced to allow to launch unit tests using mpi. In this case one can
write for instance
  set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC})
before calling the ParseAndAddCatchTests function.
2018-10-25 15:51:15 +02:00
Maciej Patro
8b3c09c137 Catch's CLI now checks whether requested reporter exists
Fixes #1351
2018-10-25 15:43:30 +02:00
Maciej Patro
b7f41237b1 Remove unused parameter from listReporters() 2018-10-25 15:43:30 +02:00
MaciejPatro
1faccd601d Improve path normalization for approvalTests.py
This fixes 3 problems:

* Relative paths on Windows are now supported
* Out-of-tree (paths starting with ../) builds are now supported
* Path separator normalization no longer affects non-path components of input (problem with Compact reporter)


Fixes #1379 
Fixes #1222 
Fixes #1200 
Fixes #1194
2018-10-19 12:46:06 +02:00
Jozef Grajciar
ab98afe68b Catch::LeakDetector: added cleanup call to destructor
simple code with provided main function which just returns 0
leaks memory due to fact that singletons are not cleaned up

running valgrind on such simple application reports that 752 bytes
are still available in 11 blocks

this commit adds destructor to Catch::LeakDetector which calls
Catch::cleanUp()
2018-10-18 11:47:21 +02:00
Martin Hořeňovský
054d356332 Add STATIC_REQUIRE assertion
By default, it expands into a `static_assert` + `SUCCEED` pair, but
it can also be deferred to runtime by defining
`CATCH_CONFIG_RUNTIME_STATIC_REQUIRE`, which causes it to expand
into plain old `REQUIRE`.

Closes #1362
Closes #1356
2018-10-16 16:16:00 +02:00
Maciej Patro
0144ae9ad2 Fix catch_discover_tests() - now should correctly find tests with commas | Related to #1327 2018-10-16 16:06:31 +02:00
JoeyGrajciar
e1307016f0 Session::applyCommandLine overload on wchar_t (#1401)
* Session::applyCommandLine overload on wchar_t

This allows users on Windows to use Catch::Session::applyCommandLine
with wchar_t * arguments of application.

With this change Session::run became templated so both char and wchar_t
version have the same implementation.
2018-10-13 19:29:53 +02:00
Martin Hořeňovský
6b9ca0888a Add tests for #1404 2018-10-13 16:53:44 +02:00
Jozef Grajciar
9f8b848fe5 XmlReporter: add information about rng-seed
Xml result of reported will now contain value of rng-seed in case it
is not zero.
The value will be stored in element Randomness and it's attribute seed.

Relates to #1402
2018-10-13 16:53:44 +02:00
Martin Hořeňovský
aaaac35d92 Add tests for #1403 2018-10-13 16:53:30 +02:00
Eddie
6cede0101a Fix different operator<< overload sets used for SFINAE and insertion 2018-10-13 16:53:30 +02:00
Miguel Gaio
f1faaa9c10 Fix convert from char on ARM build
Some platforms set the signedness of char to unsigned (eg. ARM).
Convert from char should not assume the signedness of char.

Fix build issue with -Werror,-Wtautological-unsigned-zero-compare flags.

Signed-off-by: Miguel Gaio <mgaio35@gmail.com>
2018-10-13 12:56:05 +02:00
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
Axel Huebl
5347ff9e5f Refactor: override implies virtual
If not used with `final`, override implies `virtual`.
Detected via CodeFactor score.

Another reference on SO:
  https://stackoverflow.com/questions/43466863/isnt-virtual-keyword-redundant-when-override-or-final-specifiers-are-used
2018-07-12 14:27:06 +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
315 changed files with 42449 additions and 14444 deletions

94
.conan/build.py Normal file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
from cpt.packager import ConanMultiPackager
from cpt.ci_manager import CIManager
from cpt.printer import Printer
class BuilderSettings(object):
@property
def username(self):
""" Set catchorg as package's owner
"""
return os.getenv("CONAN_USERNAME", "catchorg")
@property
def login_username(self):
""" Set Bintray login username
"""
return os.getenv("CONAN_LOGIN_USERNAME", "horenmar")
@property
def upload(self):
""" Set Catch2 repository to be used on upload.
The upload server address could be customized by env var
CONAN_UPLOAD. If not defined, the method will check the branch name.
Only master or CONAN_STABLE_BRANCH_PATTERN will be accepted.
The master branch will be pushed to testing channel, because it does
not match the stable pattern. Otherwise it will upload to stable
channel.
"""
return os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/catchorg/Catch2")
@property
def upload_only_when_stable(self):
""" Force to upload when running over tag branch
"""
return os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", "True").lower() in ["true", "1", "yes"]
@property
def stable_branch_pattern(self):
""" Only upload the package the branch name is like a tag
"""
return os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+")
@property
def reference(self):
""" Read project version from branch create Conan reference
"""
return os.getenv("CONAN_REFERENCE", "Catch2/{}".format(self._version))
@property
def channel(self):
""" Default Conan package channel when not stable
"""
return os.getenv("CONAN_CHANNEL", "testing")
@property
def _version(self):
""" Get version name from cmake file
"""
pattern = re.compile(r"project\(Catch2 LANGUAGES CXX VERSION (\d+\.\d+\.\d+)\)")
version = "latest"
with open("CMakeLists.txt") as file:
for line in file:
result = pattern.search(line)
if result:
version = result.group(1)
return version
@property
def _branch(self):
""" Get branch name from CI manager
"""
printer = Printer(None)
ci_manager = CIManager(printer)
return ci_manager.get_branch()
if __name__ == "__main__":
settings = BuilderSettings()
builder = ConanMultiPackager(
reference=settings.reference,
channel=settings.channel,
upload=settings.upload,
upload_only_when_stable=settings.upload_only_when_stable,
stable_branch_pattern=settings.stable_branch_pattern,
login_username=settings.login_username,
username=settings.username,
test_folder=os.path.join(".conan", "test_package"))
builder.add()
builder.run()

View File

@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.2.0)
project(test_package CXX)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
find_package(Catch2 REQUIRED CONFIG)
add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} CONAN_PKG::Catch2)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 11)

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from conans import ConanFile, CMake
import os
class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
assert os.path.isfile(os.path.join(self.deps_cpp_info["Catch2"].rootpath, "licenses", "LICENSE.txt"))
bin_path = os.path.join("bin", "test_package")
self.run("%s -s" % bin_path, run_environment=True)

View File

@@ -0,0 +1,15 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
int Factorial( int number ) {
return number <= 1 ? 1 : Factorial( number - 1 ) * number;
}
TEST_CASE( "Factorial Tests", "[single-file]" ) {
REQUIRE( Factorial(0) == 1 );
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 );
}

13
.gitattributes vendored
View File

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

29
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,29 @@
---
name: Bug report
about: Create an issue that documents a bug
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Reproduction steps**
Steps to reproduce the bug.
<!-- Usually this means a small and self-contained piece of code that uses Catch and specifying compiler flags if relevant. -->
**Platform information:**
<!-- Fill in any extra information that might be important for your issue. -->
- OS: **Windows NT**
- Compiler+version: **GCC v2.9.5**
- Catch version: **v1.2.3**
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,14 @@
---
name: Feature request
about: Create an issue that requests a feature or other improvement
title: ''
labels: ''
assignees: ''
---
**Description**
Describe the feature/change you request and why do you want it.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,29 +0,0 @@
## Description
<!--
If your issue is a bugreport, this means describing what you did,
what did you want to happen and what actually did happen.
If your issue is a feature request, describe the feature and why do you
want it.
-->
### Steps to reproduce
<!--
This is only relevant for bug reports, but if you do have one,
please provide a minimal set of steps to reproduce the problem.
Usually this means providing a small and self-contained code using Catch
and specifying compiler flags/tools used if relevant.
-->
### Extra information
<!--
Fill in any extra information that might be important for your issue.
If your issue is a bugreport, definitely fill out at least the following.
-->
* Catch version: **v42.42.42**
* Operating System: **Joe's discount operating system**
* Compiler+version: **Hidden Dragon v1.2.3**

View File

@@ -12,7 +12,7 @@ at docs/contributing.md. It will tell you how to properly test your changes.
<!--
Describe the what and the why of your pull request. Remember that these two
are usually a bit different. As an example, if you have made various changes
to decrease the number of new strings allocated, thats what. The why probably
to decrease the number of new strings allocated, that's what. The why probably
was that you have a large set of tests and found that this speeds them up.
-->

7
.gitignore vendored
View File

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

View File

@@ -1,5 +1,16 @@
language: cpp
sudo: false
branches:
except:
- /dev-appveyor.*/
common_sources: &all_sources
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
- llvm-toolchain-trusty-3.9
- llvm-toolchain-trusty-4.0
- llvm-toolchain-trusty-5.0
- llvm-toolchain-trusty-6.0
matrix:
include:
@@ -7,221 +18,307 @@ matrix:
# 1/ Linux Clang Builds
- os: linux
compiler: clang
addons: &clang35
addons:
apt:
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test']
sources: *all_sources
packages: ['clang-3.5']
env: COMPILER='clang++-3.5' BUILD_TYPE='Release'
env: COMPILER='clang++-3.5'
- os: linux
compiler: clang
addons: *clang35
env: COMPILER='clang++-3.5' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang36
addons:
apt:
sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test']
sources: *all_sources
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
compiler: clang
addons: *clang36
env: COMPILER='clang++-3.6' BUILD_TYPE='Debug'
- os: linux
compiler: clang
addons: &clang37
addons:
apt:
sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test']
packages: ['clang-3.7']
env: COMPILER='clang++-3.7' BUILD_TYPE='Release'
sources: *all_sources
packages: ['lcov', 'clang-3.8']
env: COMPILER='clang++-3.8'
- os: linux
compiler: clang
addons: *clang37
env: COMPILER='clang++-3.7' BUILD_TYPE='Debug'
addons:
apt:
sources: *all_sources
packages: ['clang-3.9']
env: COMPILER='clang++-3.9'
- os: linux
compiler: clang
addons: &clang38
apt:
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
packages: ['clang-3.8']
env: COMPILER='clang++-3.8' BUILD_TYPE='Release'
addons:
apt:
sources: *all_sources
packages: ['clang-4.0']
env: COMPILER='clang++-4.0'
- os: linux
compiler: clang
addons: *clang38
env: COMPILER='clang++-3.8' BUILD_TYPE='Debug'
addons:
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
- os: linux
compiler: gcc
addons: &gcc48
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
sources: *all_sources
packages: ['g++-4.8']
env: COMPILER='g++-4.8' BUILD_TYPE='Release'
env: COMPILER='g++-4.8'
- os: linux
compiler: gcc
addons: *gcc48
env: COMPILER='g++-4.8' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc49
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
sources: *all_sources
packages: ['g++-4.9']
env: COMPILER='g++-4.9' BUILD_TYPE='Release'
env: COMPILER='g++-4.9'
- os: linux
compiler: gcc
addons: *gcc49
env: COMPILER='g++-4.9' BUILD_TYPE='Debug'
- os: linux
compiler: gcc
addons: &gcc5
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
sources: *all_sources
packages: ['g++-5']
env: COMPILER='g++-5' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: *gcc5
env: COMPILER='g++-5' BUILD_TYPE='Debug'
env: COMPILER='g++-5'
- os: linux
compiler: gcc
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
sources: *all_sources
packages: ['g++-6']
env: COMPILER='g++-6' BUILD_TYPE='Release'
env: COMPILER='g++-6'
- os: linux
compiler: gcc
addons: *gcc6
env: COMPILER='g++-6' BUILD_TYPE='Debug'
# 3a/ Linux C++11 GCC builds
- os: linux
compiler: gcc
addons: *gcc48
env: COMPILER='g++-4.8' BUILD_TYPE='Release' CPP11=1
addons: &gcc7
apt:
sources: *all_sources
packages: ['g++-7']
env: COMPILER='g++-7'
- os: linux
compiler: gcc
addons: *gcc48
env: COMPILER='g++-4.8' BUILD_TYPE='Debug' CPP11=1
addons: &gcc8
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
compiler: clang
addons: *clang38
env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP11=1
addons:
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
compiler: clang
addons: *clang38
env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP11=1
addons:
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
- os: linux
compiler: gcc
addons: *gcc6
env: COMPILER='g++-6' BUILD_TYPE='Release' CPP14=1
env: COMPILER='g++-6' CPP14=1
- os: linux
compiler: gcc
addons: *gcc6
env: COMPILER='g++-6' BUILD_TYPE='Debug' 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
addons: *gcc7
env: COMPILER='g++-7' CPP14=1
- os: linux
compiler: gcc
addons: *gcc8
env: COMPILER='g++-8' CPP14=1
# 5/ OSX Clang Builds
- os: osx
osx_image: xcode7.3
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug'
- os: osx
osx_image: xcode7.3
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Release'
env: COMPILER='clang++'
- os: osx
osx_image: xcode8
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug'
env: COMPILER='clang++'
- os: osx
osx_image: xcode8
osx_image: xcode9
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Release'
env: COMPILER='clang++'
- os: osx
osx_image: xcode8
osx_image: xcode9.1
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug' USE_CPP11=1
env: COMPILER='clang++'
- os: osx
osx_image: xcode8
osx_image: xcode9.1
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
osx_image: xcode8
osx_image: xcode9.1
compiler: clang
env: COMPILER='clang++' BUILD_TYPE='Debug' USE_CPP14=1
env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
- os: osx
osx_image: xcode8
# 7/ C++17 builds
- 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
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
# 8/ Conan
- language: python
python:
- "3.7"
dist: xenial
install:
- pip install conan==1.10.2 conan-package-tools
env:
- CONAN_GCC_VERSIONS=8
- CONAN_DOCKER_IMAGE=conanio/gcc8
script:
- python .conan/build.py
install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz"
CMAKE_URL="http://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
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
which cmake || brew install cmake
which cmake || brew install cmake;
fi
before_script:
- export CXX=${COMPILER}
- cd ${TRAVIS_BUILD_DIR}
- cmake -H. -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -Wdev -DUSE_CPP11=${CPP11} -DUSE_CPP14=${CPP14}
- cd Build
# Regenerate single header file, so it is tested in the examples...
- python scripts/generateSingleHeader.py
# Use Debug builds for running Valgrind and building examples
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_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} -DUSE_CPP17=${CPP17}
script:
- cd Build-Debug
- 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 dependent 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 dependent 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,33 @@
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.8.0)
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
endif()
# 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)
@@ -9,327 +36,188 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
set(HEADER_DIR ${CATCH_DIR}/include)
set(CATCH_VERSION_NUMBER 2.0.1)
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)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
endif()
#checks that the given hard-coded list contains all headers + sources in the given folder
function(CheckFileList LIST_VAR FOLDER)
set(MESSAGE " should be added to the variable ${LIST_VAR}")
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
"${FOLDER}/*.hpp"
"${FOLDER}/*.h")
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
foreach(EXTRA_ITEM ${GLOBBED_LIST})
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
endforeach()
endfunction()
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}/ToStringChrono.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_reporter.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
)
CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
# Please keep these ordered alphabetically
set(TOP_LEVEL_HEADERS
${HEADER_DIR}/catch.hpp
${HEADER_DIR}/catch_with_main.hpp
)
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
# Please keep these ordered alphabetically
set(EXTERNAL_HEADERS
${HEADER_DIR}/external/clara.hpp
)
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
# Please keep these ordered alphabetically
set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_approx.h
${HEADER_DIR}/internal/catch_assertionhandler.h
${HEADER_DIR}/internal/catch_assertioninfo.h
${HEADER_DIR}/internal/catch_assertionresult.h
${HEADER_DIR}/internal/catch_capture.hpp
${HEADER_DIR}/internal/catch_capture_matchers.h
${HEADER_DIR}/internal/catch_clara.h
${HEADER_DIR}/internal/catch_commandline.h
${HEADER_DIR}/internal/catch_common.h
${HEADER_DIR}/internal/catch_compiler_capabilities.h
${HEADER_DIR}/internal/catch_config.hpp
${HEADER_DIR}/internal/catch_console_colour.h
${HEADER_DIR}/internal/catch_context.h
${HEADER_DIR}/internal/catch_debug_console.h
${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_decomposer.h
${HEADER_DIR}/internal/catch_default_main.hpp
${HEADER_DIR}/internal/catch_enforce.h
${HEADER_DIR}/internal/catch_errno_guard.h
${HEADER_DIR}/internal/catch_exception_translator_registry.h
${HEADER_DIR}/internal/catch_external_interfaces.h
${HEADER_DIR}/internal/catch_fatal_condition.h
${HEADER_DIR}/internal/catch_impl.hpp
${HEADER_DIR}/internal/catch_interfaces_capture.h
${HEADER_DIR}/internal/catch_interfaces_config.h
${HEADER_DIR}/internal/catch_interfaces_exception.h
${HEADER_DIR}/internal/catch_interfaces_registry_hub.h
${HEADER_DIR}/internal/catch_interfaces_reporter.h
${HEADER_DIR}/internal/catch_interfaces_runner.h
${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h
${HEADER_DIR}/internal/catch_interfaces_testcase.h
${HEADER_DIR}/internal/catch_leak_detector.h
${HEADER_DIR}/internal/catch_list.h
${HEADER_DIR}/internal/catch_matchers.h
${HEADER_DIR}/internal/catch_matchers_string.h
${HEADER_DIR}/internal/catch_matchers_vector.h
${HEADER_DIR}/internal/catch_message.h
${HEADER_DIR}/internal/catch_objc.hpp
${HEADER_DIR}/internal/catch_objc_arc.hpp
${HEADER_DIR}/internal/catch_option.hpp
${HEADER_DIR}/internal/catch_platform.h
${HEADER_DIR}/internal/catch_random_number_generator.h
${HEADER_DIR}/internal/catch_reenable_warnings.h
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
${HEADER_DIR}/internal/catch_reporter_registry.h
${HEADER_DIR}/internal/catch_result_type.h
${HEADER_DIR}/internal/catch_run_context.h
${HEADER_DIR}/internal/catch_benchmark.h
${HEADER_DIR}/internal/catch_section.h
${HEADER_DIR}/internal/catch_section_info.h
${HEADER_DIR}/internal/catch_session.h
${HEADER_DIR}/internal/catch_startup_exception_registry.h
${HEADER_DIR}/internal/catch_stream.h
${HEADER_DIR}/internal/catch_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.h
${HEADER_DIR}/internal/catch_test_case_tracker.h
${HEADER_DIR}/internal/catch_test_registry.h
${HEADER_DIR}/internal/catch_test_spec.h
${HEADER_DIR}/internal/catch_test_spec_parser.h
${HEADER_DIR}/internal/catch_text.h
${HEADER_DIR}/internal/catch_timer.h
${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_totals.h
${HEADER_DIR}/internal/catch_version.h
${HEADER_DIR}/internal/catch_wildcard_pattern.h
${HEADER_DIR}/internal/catch_windows_h_proxy.h
${HEADER_DIR}/internal/catch_xmlwriter.h
)
set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_approx.cpp
${HEADER_DIR}/internal/catch_assertionhandler.cpp
${HEADER_DIR}/internal/catch_assertionresult.cpp
${HEADER_DIR}/internal/catch_benchmark.cpp
${HEADER_DIR}/internal/catch_capture_matchers.cpp
${HEADER_DIR}/internal/catch_commandline.cpp
${HEADER_DIR}/internal/catch_common.cpp
${HEADER_DIR}/internal/catch_config.cpp
${HEADER_DIR}/internal/catch_console_colour.cpp
${HEADER_DIR}/internal/catch_context.cpp
${HEADER_DIR}/internal/catch_debug_console.cpp
${HEADER_DIR}/internal/catch_debugger.cpp
${HEADER_DIR}/internal/catch_decomposer.cpp
${HEADER_DIR}/internal/catch_errno_guard.cpp
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
${HEADER_DIR}/internal/catch_fatal_condition.cpp
${HEADER_DIR}/internal/catch_interfaces_capture.cpp
${HEADER_DIR}/internal/catch_interfaces_config.cpp
${HEADER_DIR}/internal/catch_interfaces_exception.cpp
${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_runner.cpp
${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
${HEADER_DIR}/internal/catch_list.cpp
${HEADER_DIR}/internal/catch_leak_detector.cpp
${HEADER_DIR}/internal/catch_matchers.cpp
${HEADER_DIR}/internal/catch_matchers_string.cpp
${HEADER_DIR}/internal/catch_message.cpp
${HEADER_DIR}/internal/catch_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
${HEADER_DIR}/internal/catch_random_number_generator.cpp
${HEADER_DIR}/internal/catch_reporter_registry.cpp
${HEADER_DIR}/internal/catch_result_type.cpp
${HEADER_DIR}/internal/catch_run_context.cpp
${HEADER_DIR}/internal/catch_section.cpp
${HEADER_DIR}/internal/catch_section_info.cpp
${HEADER_DIR}/internal/catch_session.cpp
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
${HEADER_DIR}/internal/catch_stream.cpp
${HEADER_DIR}/internal/catch_streambuf.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}
)
# Provide some groupings for IDEs
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
# configure the executable
include_directories(${HEADER_DIR})
# 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 desired warnings
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code )
endif()
# Clang specific warning go here
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
# Actually keep these
target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX /w44061 /w44062 )
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
find_package(PythonInterp)
if (NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR "Python not found, but required for tests")
endif()
add_subdirectory(projects)
endif()
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)
# configure unit tests via CTest
enable_testing()
add_test(NAME RunTests COMMAND SelfTest)
add_test(NAME ListTests COMMAND SelfTest --list-tests)
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
# 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
)
add_test(NAME ListTags COMMAND SelfTest --list-tags)
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
target_include_directories(Catch2
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/single_include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
endif() # !NO_SELFTEST
# 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")
install(DIRECTORY "single_include/" DESTINATION "include/catch")
## Provide some pkg-config integration
# Don't bother on Windows
if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
set(PKGCONFIG_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
CACHE PATH "Path where catch.pc is installed"
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
INSTALL_DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/catch.pc.in ${CMAKE_CURRENT_BINARY_DIR}/catch.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR})
endif()
# 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()
if(CATCH_INSTALL_HELPERS)
# Install CMake scripts
install(
FILES
"contrib/ParseAndAddCatchTests.cmake"
"contrib/Catch.cmake"
"contrib/CatchAddTests.cmake"
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install debugger helpers
install(
FILES
"contrib/gdbinit"
"contrib/lldbinit"
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
)
endif()
## Provide some pkg-config integration
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}
)
# CPack/CMake started taking the package version from project version 3.12
# So we need to set the version manually for older CMake versions
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
endif()
set(CPACK_PACKAGE_CONTACT "https://github.com/catchorg/Catch2/")
include( CPack )
endif(NOT_SUBPROJECT)

View File

@@ -1,17 +1,21 @@
<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/catchorg/catch2/releases)
[![Build Status](https://travis-ci.org/philsquared/Catch.svg)](https://travis-ci.org/philsquared/Catch)
[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght)](https://ci.appveyor.com/project/philsquared/catch)
[![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/wQeSudewoh6pdgRp)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.8.0/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
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.
before moving to Catch2. You might also like to read [this blog post](https://levelofindirection.com/blog/catch2-released.html) for more details.
## What's the Catch?
@@ -30,5 +34,5 @@ This documentation comprises these three parts:
## More
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
* See [who else is using Catch2](docs/opensource-users.md#top)

View File

@@ -1,6 +1,10 @@
# version string format -- This will be overwritten later anyway
version: "{build}"
branches:
except:
- /dev-travis.+/
os:
- Visual Studio 2017
- Visual Studio 2015
@@ -15,23 +19,51 @@ environment:
- additional_flags: "/D_UNICODE /DUNICODE"
wmain: 1
coverage: 0
# Have a coverage dimension
- additional_flags: ""
wmain: 0
coverage: 1
# Have an examples dimension
- additional_flags: ""
wmain: 0
examples: 1
matrix:
exclude:
-
additional_flags: "/permissive- /std:c++latest"
os: Visual Studio 2015
-
additional_flags: "/permissive- /std:c++latest"
os: Visual Studio 2013
- os: Visual Studio 2015
additional_flags: "/permissive- /std:c++latest"
init:
- git config --global core.autocrlf input
# Set build version to git commit-hash
- ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)"
- os: Visual Studio 2015
additional_flags: "/D_UNICODE /DUNICODE"
# fetch repository as zip archive
shallow_clone: true
# Exclude unwanted coverage configurations
- coverage: 1
platform: Win32
- coverage: 1
os: Visual Studio 2015
- coverage: 1
configuration: Release
# Exclude unwanted examples configurations
- examples: 1
platform: Win32
- examples: 1
os: Visual Studio 2015
- examples: 1
configuration: Release
install:
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
# Win32 and x64 are CMake-compatible solution platform names.
# This allows us to pass %PLATFORM% to CMake -A.
@@ -47,14 +79,18 @@ configuration:
#Cmake will autodetect the compiler, but we set the arch
before_build:
- 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:
project: Build\CatchSelfTest.sln # path to Visual Studio solution or project
project: Build\Catch2.sln # path to Visual Studio solution or project
parallel: true # enable MSBuild parallel builds
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
test_script:
- cd Build
- ctest -V -j 2 -C %CONFIGURATION%
- set CTEST_OUTPUT_ON_FAILURE=1
- 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

View File

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

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,19 +1,27 @@
#!/usr/bin/env python
from conans import ConanFile
from conans import ConanFile, CMake
class CatchConan(ConanFile):
name = "Catch"
version = "2.0.1"
name = "Catch2"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared"
topics = ("conan", "catch2", "header-only", "unit-test", "tdd", "bdd")
url = "https://github.com/catchorg/Catch2"
homepage = url
license = "BSL-1.0"
exports = "LICENSE.txt"
exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*")
generators = "cmake"
exports_sources = "single_include/*"
url = "https://github.com/philsquared/Catch"
license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
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(build_folder='build')
cmake.install()
self.copy(pattern="LICENSE.txt", dst="licenses")
def package_id(self):
self.info.header_only()
self.info.header_only()

175
contrib/Catch.cmake Normal file
View File

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

106
contrib/CatchAddTests.cmake Normal file
View File

@@ -0,0 +1,106 @@
# 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()
macro(_add_catch_test_labels LINE)
# convert to list of tags
string(REPLACE "][" "]\\;[" tags ${line})
add_command(
set_tests_properties "${prefix}${test}${suffix}"
PROPERTIES
LABELS "${tags}"
)
endmacro()
macro(_add_catch_test LINE)
set(test ${line})
# use escape commas to handle properly test cases with commans inside the name
string(REPLACE "," "\\," test_name ${test})
# ...and add to script
add_command(
add_test "${prefix}${test}${suffix}"
${TEST_EXECUTOR}
"${TEST_EXECUTABLE}"
"${test_name}"
${extra_args}
)
add_command(
set_tests_properties "${prefix}${test}${suffix}"
PROPERTIES
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
${properties}
)
list(APPEND tests "${prefix}${test}${suffix}")
endmacro()
# 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-tests
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}")
set(test)
set(tags_regex "(\\[([^\\[]*)\\])+$")
# Parse output
foreach(line ${output})
# lines without leading whitespaces are catch output not tests
if(${line} MATCHES "^[ \t]+")
# strip leading spaces and tabs
string(REGEX REPLACE "^[ \t]+" "" line ${line})
if(${line} MATCHES "${tags_regex}")
_add_catch_test_labels(${line})
else()
_add_catch_test(${line})
endif()
endif()
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

@@ -39,9 +39,24 @@
# 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 #
# #
# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way #
# a test should be run. For instance to use test MPI, one can write #
# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) #
# just before calling this ParseAndAddCatchTests function #
# #
# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test #
# command. For example, to include successful tests in the output, one can write #
# set(AdditionalCatchParameters --success) #
# #
# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source #
# file in the target is set, and contains the list of the tests extracted from that target, or #
# from that file. This is useful, for example to add further labels or properties to the tests. #
# #
#==================================================================================================#
cmake_minimum_required(VERSION 2.8.8)
if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8)
message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer")
endif()
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
@@ -49,7 +64,7 @@ option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the
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(ParseAndAddCatchTests_PrintDebugMessage)
if(PARSE_CATCH_TESTS_VERBOSE)
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
endif()
@@ -60,7 +75,7 @@ endfunction()
# - full line comments (i.e. // ... )
# contents have been read into '${CppCode}'.
# !keep partial line comments
function(RemoveComments CppCode)
function(ParseAndAddCatchTests_RemoveComments CppCode)
string(ASCII 2 CMakeBeginBlockComment)
string(ASCII 3 CMakeEndBlockComment)
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
@@ -72,24 +87,29 @@ function(RemoveComments CppCode)
endfunction()
# Worker function
function(ParseFile SourceFile TestTarget)
function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
# If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file.
if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>")
ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.")
return()
endif()
# According to CMake docs EXISTS behavior is well-defined only for full paths.
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
if(NOT EXISTS ${SourceFile})
message(WARNING "Cannot find source file: ${SourceFile}")
return()
endif()
PrintDebugMessage("parsing ${SourceFile}")
ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}")
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
# Remove block and fullline comments
RemoveComments(Contents)
ParseAndAddCatchTests_RemoveComments(Contents)
# 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}")
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
set_property(
DIRECTORY
APPEND
@@ -104,7 +124,7 @@ function(ParseFile SourceFile TestTarget)
# Get test type and fixture if applicable
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
string(REPLACE "${TestType}(" "" TestFixture "${TestTypeAndFixture}")
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
# Get string parts of test definition
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
@@ -143,11 +163,13 @@ function(ParseFile SourceFile TestTarget)
endif()
string(REPLACE "]" ";" Tags "${Tags}")
string(REPLACE "[" "" Tags "${Tags}")
else()
# unset tags variable from previous loop
unset(Tags)
endif()
list(APPEND Labels ${Tags})
list(FIND Labels "!hide" IndexOfHideLabel)
set(HiddenTagFound OFF)
foreach(label ${Labels})
string(REGEX MATCH "^!hide|^\\." result ${label})
@@ -156,30 +178,48 @@ function(ParseFile SourceFile TestTarget)
break()
endif(result)
endforeach(label)
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound})
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
else()
PrintDebugMessage("Adding test \"${CTestName}\"")
ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"")
if(Labels)
PrintDebugMessage("Setting labels to ${Labels}")
ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}")
endif()
# Escape commas in the test spec
string(REPLACE "," "\\," Name ${Name})
# Add the test and set its properties
add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters})
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
LABELS "${Labels}")
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
else()
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
LABELS "${Labels}")
endif()
set_property(
TARGET ${TestTarget}
APPEND
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
set_property(
SOURCE ${SourceFile}
APPEND
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
endif()
endforeach()
endfunction()
# entry point
function(ParseAndAddCatchTests TestTarget)
PrintDebugMessage("Started parsing ${TestTarget}")
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
get_target_property(SourceFiles ${TestTarget} SOURCES)
PrintDebugMessage("Found the following sources: ${SourceFiles}")
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
foreach(SourceFile ${SourceFiles})
ParseFile(${SourceFile} ${TestTarget})
ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget})
endforeach()
PrintDebugMessage("Finished parsing ${TestTarget}")
ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}")
endfunction()

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

@@ -12,6 +12,8 @@ Writing tests:
* [Test fixtures](test-fixtures.md#top)
* [Reporters](reporters.md#top)
* [Event Listeners](event-listeners.md#top)
* [Data Generators](generators.md#top)
* [Other macros](other-macros.md#top)
Fine tuning:
* [Supplying your own main()](own-main.md#top)
@@ -20,7 +22,10 @@ Fine tuning:
Running:
* [Command line](command-line.md#top)
* [CI and Build system integration](build-systems.md#top)
Odds and ends:
* [CMake integration](cmake-integration.md#top)
* [CI and other miscellaneous pieces](ci-and-misc.md#top)
FAQ:
* [Why are my tests slow to compile?](slow-compiles.md#top)
@@ -31,3 +36,4 @@ Other:
* [Open Source Projects using Catch](opensource-users.md#top)
* [Contributing](contributing.md#top)
* [Release Notes](release-notes.md#top)
* [Deprecations and incoming changes](deprecations.md#top)

View File

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

View File

@@ -1,6 +1,13 @@
<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.
## Continuous Integration systems
@@ -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.
## Other reporters
Other reporters are not part of the single-header distribution and need to be downloaded and included separately. All reporters are stored in `include/reporters` directory in the git repository, and are named `catch_reporter_*.hpp`. For example, to use the TeamCity reporter you need to download `include/reporters/catch_reporter_teamcity.hpp` and include it after Catch itself.
Other reporters are not part of the single-header distribution and need
to be downloaded and included separately. All reporters are stored in
`single_include` directory in the git repository, and are named
`catch_reporter_*.hpp`. For example, to use the TeamCity reporter you
need to download `single_include/catch_reporter_teamcity.hpp` and include
it after Catch itself.
```
```cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "catch_reporter_teamcity.hpp"
@@ -55,90 +67,42 @@ Because of the incremental nature of Catch's test suites and ability to run spec
## 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:
```CMake
cmake_minimum_required(VERSION 3.0)
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:
* The precompiled header needs to define `CATCH_CONFIG_ALL_PARTS`
* 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...)
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)

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

@@ -0,0 +1,226 @@
<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 `CatchAddTests.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`.
Optionally, one can specify a launching command to run tests by setting the
variable `OptionalCatchTestLauncher` before calling `ParseAndAddCatchTests`. For
instance to run some tests using `MPI` and other sequentially, one can write
```cmake
set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC})
ParseAndAddCatchTests(mpi_foo)
unset(OptionalCatchTestLauncher)
ParseAndAddCatchTests(bar)
```
## 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

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

View File

@@ -13,5 +13,7 @@ fact then please let us know - either directly, via a PR or
[issue](https://github.com/philsquared/Catch/issues), or on the [forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
- Bloomberg
- [Bloomlife](https://bloomlife.com)
- NASA
- [Inscopix Inc.](https://www.inscopix.com/)
- [Makimo](https://makimo.pl/)

View File

@@ -3,13 +3,19 @@
**Contents**<br>
[main()/ implementation](#main-implementation)<br>
[Reporter / Listener interfaces](#reporter--listener-interfaces)<br>
[Prefixing Catch macros](#prefixing-catch-macros)<br>
[Terminal colour](#terminal-colour)<br>
[Console width](#console-width)<br>
[stdout](#stdout)<br>
[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```).
@@ -17,14 +23,14 @@ Nonetheless there are still some occasions where finer control is needed. For th
## main()/ implementation
CATCH_CONFIG_MAIN // Designates this as implementation file and defines main()
CATCH_CONFIG_RUNNER // Designates this as implementation file
CATCH_CONFIG_MAIN // Designates this as implementation file and defines main()
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*.
# 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.
@@ -32,16 +38,16 @@ Implied by both `CATCH_CONFIG_MAIN` and `CATCH_CONFIG_RUNNER`.
## 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```).
## Terminal colour
CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring
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_NONE // completely disables all text colouring
CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API 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'.
@@ -55,24 +61,81 @@ Typically you should place the ```#define``` before #including "catch.hpp" in yo
## 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.
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
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& cerr();
std::ostream& clog();
This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
[You can see an example of replacing these functions here.](
../examples/231-Cfg-OutputStreams.cpp)
## Fallback stringifier
By default, when Catch's stringification machinery has to stringify
a type that does not specialize `StringMaker`, does not overload `operator<<`,
is not an enumeration and is not a range, it uses `"{?}"`. This can be
overridden 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
@@ -84,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_DISABLE_STRINGIFICATION // Disable stringifying the original expression
CATCH_CONFIG_DISABLE // Disables assertions and test case registration
CATCH_CONFIG_WCHAR // Enables use of wchart_t
CATCH_CONFIG_EXPERIMENTAL_REDIRECT // Enables the new (experimental) way of capturing stdout/stderr
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
@@ -91,14 +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.
These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
`CATCH_CONFIG_WCHAR` is on by default, but can be disabled. Currently
it is only used in support for DJGPP cross-compiler.
With the exception of `CATCH_CONFIG_EXPERIMENTAL_REDIRECT`,
these toggles can be disabled by using `_NO_` form of the toggle,
e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
### `CATCH_CONFIG_FAST_COMPILE`
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:
* The `-b` (`--break`) flag no longer makes Catch break into debugger in the same stack frame as the failed test, but rather in a stack frame *below*.
* Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_FALSE`}, no longer use local try-cache block. This disables exception translation, but should not lead to false negatives.
This compile-time flag speeds up compilation of assertion macros by ~20%,
by disabling the generation of assertion-local try-catch blocks for
non-exception family of assertion macros ({`REQUIRE`,`CHECK`}{``,`_FALSE`, `_THAT`}).
This disables translation of exceptions thrown under these assertions, but
should not lead to false negatives.
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable.
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined,
in all translation units that are linked into single test binary.
### `CATCH_CONFIG_DISABLE_MATCHERS`
When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU.
@@ -127,12 +200,48 @@ On Windows Catch includes `windows.h`. To minimize global namespace clutter in t
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_ALL_STRINGMAKERS // Defines all of the above
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_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (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)

View File

@@ -1,8 +1,8 @@
<a id="top"></a>
# Contributing to Catch
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated.
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated.
Of course so are bug reports and other comments and questions.
If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to
@@ -16,7 +16,7 @@ Ongoing development is currently on _master_. At some point an integration branc
## Directory structure
_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still,
_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still,
primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under
`projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate
project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion,
@@ -37,24 +37,72 @@ as these are managed by the scripts!__
## Testing your changes
Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and
showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements),
you should still test your changes.
Obviously all changes to Catch's code should be tested. If you added new
functionality, you should add tests covering and showcasing it. Even if you have
only made changes to Catch internals (i.e. you implemented some performance
improvements), you should still test your changes.
This means 3 things
This means 2 things
* Compiling Catch's SelfTest project -- code that does not compile is evidently incorrect. Obviously, you are not expected to
have access to all compilers and platforms Catch supports, Catch's CI pipeline will compile your code using supported compilers
once you open a PR.
* Running the SelfTest binary. There should be no unexpected failures on simple run.
* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against
known good output. Catch's repository provides utility scripts `approvalTests.py` to help you with this. It needs to be passed
the SelfTest binary compiled with your changes, like so: `$ ./scripts/approvalTests.py clang-build/SelfTest`. The output should
be fairly self-explanatory.
* Compiling Catch's SelfTest project:
```
$ cd Catch2
$ cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug
$ cmake --build debug-build
```
because code that does not compile is evidently incorrect. Obviously,
you are not expected to have access to all the compilers and platforms
supported by Catch2, but you should at least smoke test your changes
on your platform. Our CI pipeline will check your PR against most of
the supported platforms, but it takes an hour to finish -- compiling
locally takes just a few minutes.
* Running the tests via CTest:
```
$ cd debug-build
$ ctest -j 2 --output-on-failure
```
If you added new tests, approval tests are very likely to fail. If they
do not, it means that your changes weren't run as part of them. This
_might_ be intentional, but usually is not.
*this document is still in-progress...*
The approval tests compare current output of the SelfTest binary in various
configurations against known good outputs. The reason it fails is,
_usually_, that you've added new tests but have not yet approved the changes
they introduce. This is done with the `scripts/approve.py` script, but
before you do so, you need to check that the introduced changes are indeed
intentional.
## Code constructs to watch out for
This section is a (sadly incomplete) listing of various constructs that
are problematic and are not always caught by our CI infrastructure.
### Naked exceptions and exceptions-related function
If you are throwing an exception, it should be done via `CATCH_ERROR`
or `CATCH_RUNTIME_ERROR` in `catch_enforce.h`. These macros will handle
the differences between compilation with or without exceptions for you.
However, some platforms (IAR) also have problems with exceptions-related
functions, such as `std::current_exceptions`. We do not have IAR in our
CI, but luckily there should not be too many reasons to use these.
However, if you do, they should be kept behind a
`CATCH_CONFIG_DISABLE_EXCEPTIONS` macro.
### Unqualified usage of functions from C's stdlib
If you are using a function from C's stdlib, please include the header
as `<cfoo>` and call the function qualified. The common knowledge that
there is no difference is wrong, QNX and VxWorks won't compile if you
include the header as `<cfoo>` and call the function unqualified.
----
_This documentation will always be in-progress as new information comes
up, but we are trying to keep it as up to date as possible._
---

93
docs/deprecations.md Normal file
View File

@@ -0,0 +1,93 @@
<a id="top"></a>
# Deprecations and incoming changes
This page documents current deprecations and upcoming planned changes
inside Catch2. The difference between these is that a deprecated feature
will be removed, while a planned change to a feature means that the
feature will behave differently, but will still be present. Obviously,
either of these is a breaking change, and thus will not happen until
at least the next major release.
## Deprecations
### `--list-*` return values
The return codes of the `--list-*` family of command line arguments
will no longer be equal to the number of tests/tags/etc found, instead
it will be 0 for success and non-zero for failure.
### `--list-test-names-only`
`--list-test-names-only` command line argument will be removed.
### `ANON_TEST_CASE`
`ANON_TEST_CASE` is scheduled for removal, as it can be fully replaced
by a `TEST_CASE` with no arguments.
### Secondary description amongst tags
Currently, the tags part of `TEST_CASE` (and others) macro can also
contain text that is not part of tags. This text is then separated into
a "description" of the test case, but the description is then never used
apart from writing it out for `--list-tests -v high`.
Because it isn't actually used nor documented, and brings complications
to Catch2's internals, description support will be removed.
## Planned changes
### Reporter verbosities
The current implementation of verbosities, where the reporter is checked
up-front whether it supports the requested verbosity, is fundamentally
misguided and will be changed. The new implementation will no longer check
whether the specified reporter supports the requested verbosity, instead
it will be up to the reporters to deal with verbosities as they see fit
(with an expectation that unsupported verbosities will be, at most,
warnings, but not errors).
### Output format of `--list-*` command line parameters
The various list operations will be piped through reporters. This means
that e.g. XML reporter will write the output as machine-parseable XML,
while the Console reporter will keep the current, human-oriented output.
### `CHECKED_IF` and `CHECKED_ELSE`
To make the `CHECKED_IF` and `CHECKED_ELSE` macros more useful, they will
be marked as "OK to fail" (`Catch::ResultDisposition::SuppressFail` flag
will be added), which means that their failure will not fail the test,
making the `else` actually useful.
### Change semantics of `[.]` and tag exclusion
Currently, given these 2 tests
```cpp
TEST_CASE("A", "[.][foo]") {}
TEST_CASE("B", "[.][bar]") {}
```
specifying `[foo]` as the testspec will run test "A" and specifying
`~[foo]` will run test "B", even though it is hidden. Also, specifying
`~[baz]` will run both tests. This behaviour is often surprising and will
be changed so that hidden tests are included in a run only if they
positively match a testspec.
### Console Colour API
The API for Catch2's console colour will be changed to take an extra
argument, the stream to which the colour code should be applied.
---
[Home](Readme.md#top)

View File

@@ -19,7 +19,7 @@ file that defines `CATCH_CONFIG_EXTERNAL_INTERFACES`.
Then register it using `CATCH_REGISTER_LISTENER`.
For example:
For example ([complete source code](../examples/210-Evt-EventListeners.cpp)):
```c++
#define CATCH_CONFIG_MAIN
@@ -29,13 +29,13 @@ struct MyListener : Catch::TestEventListenerBase {
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
virtual void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
// Perform some setup before a test case is run
}
virtual void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
// Tear-down after a test case is run
}
}
};
CATCH_REGISTER_LISTENER( MyListener )
```
@@ -44,7 +44,7 @@ _Note that you should not use any assertion macros within a Listener!_
## Events that can be hooked
The following are the methods that can be overriden in the Listener:
The following are the methods that can be overridden in the Listener:
```c++
// The whole test run, starting and ending

137
docs/generators.md Normal file
View File

@@ -0,0 +1,137 @@
<a id="top"></a>
# Data Generators
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, and their nested sections
are run once per each value in a generator.
This is best explained with an example:
```cpp
TEST_CASE("Generators") {
auto i = GENERATE(1, 2, 3);
SECTION("one") {
auto j = GENERATE( -3, -2, -1 );
REQUIRE(j < i);
}
}
```
The assertion in this test case will be run 9 times, because there
are 3 possible values for `i` (1, 2, and 3) and there are 3 possible
values for `j` (-3, -2, and -1).
There are 2 parts to generators in Catch2, the `GENERATE` macro together
with the already provided generators, and the `IGenerator<T>` interface
that allows users to implement their own generators.
## Provided generators
Catch2's provided generator functionality consists of three parts,
* `GENERATE` macro, that serves to integrate generator expression with
a test case,
* 2 fundamental generators
* `ValueGenerator<T>` -- contains only single element
* `ValuesGenerator<T>` -- contains multiple elements
* 5 generic generators that modify other generators
* `FilterGenerator<T, Predicate>` -- filters out elements from a generator
for which the predicate returns "false"
* `TakeGenerator<T>` -- takes first `n` elements from a generator
* `RepeatGenerator<T>` -- repeats output from a generator `n` times
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
on elements from a different generator
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
* 3 specific purpose generators
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
* `RandomFloatGenerator<Float>` -- generates random Floats from range
* `RangeGenerator<T>` -- generates all values inside a specific range
The generators also have associated helper functions that infer their
type, making their usage much nicer. These are
* `value(T&&)` for `ValueGenerator<T>`
* `values(std::initializer_list<T>)` for `ValuesGenerator<T>`
* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>`
* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
* `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`, deduced from `Func`)
* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>`
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
And can be used as shown in the example below to create a generator
that returns 100 odd random number:
```cpp
TEST_CASE("Generating random ints", "[example][generator]") {
SECTION("Deducing functions") {
auto i = GENERATE(take(100, filter([](int i) { return i % 2 == 1; }, random(-100, 100))));
REQUIRE(i > -100);
REQUIRE(i < 100);
REQUIRE(i % 2 == 1);
}
}
```
Apart from registering generators with Catch2, the `GENERATE` macro has
one more purpose, and that is to provide simple way of generating trivial
generators, as seen in the first example on this page, where we used it
as `auto i = GENERATE(1, 2, 3);`. This usage converted each of the three
literals into a single `ValueGenerator<int>` and then placed them all in
a special generator that concatenates other generators. It can also be
used with other generators as arguments, such as `auto i = GENERATE(0, 2,
take(100, random(300, 3000)));`. This is useful e.g. if you know that
specific inputs are problematic and want to test them separately/first.
**For safety reasons, you cannot use variables inside the `GENERATE` macro.
This is done because the generator expression _will_ outlive the outside
scope and thus capturing references is dangerous. If you need to use
variables inside the generator expression, make sure you thought through
the lifetime implications and use `GENERATE_COPY` or `GENERATE_REF`.**
You can also override the inferred type by using `as<type>` as the first
argument to the macro. This can be useful when dealing with string literals,
if you want them to come out as `std::string`:
```cpp
TEST_CASE("type conversion", "[generators]") {
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
REQUIRE(str.size() > 0);
}
```
## Generator interface
You can also implement your own generators, by deriving from the
`IGenerator<T>` interface:
```cpp
template<typename T>
struct IGenerator : GeneratorUntypedBase {
// via GeneratorUntypedBase:
// Attempts to move the generator to the next element.
// Returns true if successful (and thus has another element that can be read)
virtual bool next() = 0;
// Precondition:
// The generator is either freshly constructed or the last call to next() returned true
virtual T const& get() const = 0;
};
```
However, to be able to use your custom generator inside `GENERATE`, it
will need to be wrapped inside a `GeneratorWrapper<T>`.
`GeneratorWrapper<T>` is a value wrapper around a
`std::unique_ptr<IGenerator<T>>`.
For full example of implementing your own generator, look into Catch2's
examples, specifically
[Generators: Create your own generator](../examples/300-Gen-OwnGenerator.cpp).

View File

@@ -1,12 +1,19 @@
<a id="top"></a>
# 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
### 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
TEST_CASE( "Looped section" ) {
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
This section outlines some missing features, what is their status and their possible workarounds.
### Thread safe assertions
Because threading support in standard C++98 is limited (well, non-existent), assertion macros in Catch are not thread safe. This does not mean that you cannot use threads inside Catch's test, but that only single thread can interact with Catch's assertions and other macros.
Catch2's assertion macros are not thread safe. This does not mean that
you cannot use threads inside Catch's test, but that only single thread
can interact with Catch's assertions and other macros.
This means that this is ok
```cpp
@@ -49,8 +79,8 @@ because only one thread passes the `REQUIRE` macro and this is not
REQUIRE(cnt == 16);
```
_This limitation is highly unlikely to be lifted before Catch 2 is released._
Because C++11 provides the necessary tools to do this, we are planning
to remove this limitation in the future.
### Process isolation in a test
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
@@ -96,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)
There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error
```cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
VS 2015 has a known bug, where `declval<T>` can cause compilation error
if `T` has alignment requirements that it cannot meet.
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") {
for ( auto x : { 1 , 2, 3 } ) {
REQUIRE( x < 3.14 );
}
}
```
A workaround is to explicitly specialize `Catch::is_range` for given
type (this avoids code path that uses `declval<T>` in a SFINAE context).
### Visual Studio 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
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.
### 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++.

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

@@ -0,0 +1,48 @@
<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)
- Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp)
- Generators: [Use map to convert types in GENERATE expression](../examples/301-Gen-MapTypeConversion.cpp)
- Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp)
- Generators: [Use custom variable capture in generator expressions](../examples/311-Gen-CustomCapture.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

@@ -1,7 +1,7 @@
<a id="top"></a>
# Logging macros
Additional messages can be logged during a test case. Note that the messages are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
Additional messages can be logged during a test case. Note that the messages logged with `INFO` are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
```cpp
TEST_CASE("Foo") {
@@ -28,10 +28,64 @@ The number is 1
```
When the last `CHECK` fails in the "Bar" test case, then only one message will be printed: `Test case start`.
## Logging without local scope
`UNSCOPED_INFO` is similar to `INFO` with two key differences:
- Lifetime of an unscoped message is not tied to its own scope.
- An unscoped message can be reported by the first following assertion only, regardless of the result of that assertion.
In other words, lifetime of `UNSCOPED_INFO` is limited by the following assertion (or by the end of test case/section, whichever comes first) whereas lifetime of `INFO` is limited by its own scope.
These differences make this macro useful for reporting information from helper functions or inner scopes. An example:
```cpp
void print_some_info() {
UNSCOPED_INFO("Info from helper");
}
TEST_CASE("Baz") {
print_some_info();
for (int i = 0; i < 2; ++i) {
UNSCOPED_INFO("The number is " << i);
}
CHECK(false);
}
TEST_CASE("Qux") {
INFO("First info");
UNSCOPED_INFO("First unscoped info");
CHECK(false);
INFO("Second info");
UNSCOPED_INFO("Second unscoped info");
CHECK(false);
}
```
"Baz" test case prints:
```
Info from helper
The number is 0
The number is 1
```
With "Qux" test case, two messages will be printed when the first `CHECK` fails:
```
First info
First unscoped info
```
"First unscoped info" message will be cleared after the first `CHECK`, while "First info" message will persist until the end of the test case. Therefore, when the second `CHECK` fails, three messages will be printed:
```
First info
Second info
Second unscoped info
```
## Streaming macros
All these macros allow heterogenous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it.
All these macros allow heterogeneous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it.
E.g.:
```c++
@@ -43,7 +97,14 @@ These macros come in three forms:
**INFO(** _message expression_ **)**
The message is logged to a buffer, but only reported with the next assertion that is logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
The message is logged to a buffer, but only reported with next assertions that are logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
_Note that in Catch2 2.x.x `INFO` can be used without a trailing semicolon as there is a trailing semicolon inside macro.
This semicolon will be removed with next major version. It is highly advised to use a trailing semicolon after `INFO` macro._
**UNSCOPED_INFO(** _message expression_ **)**
Similar to `INFO`, but messages are not limited to their own scope: They are removed from the buffer after each assertion, section or test case, whichever comes first.
**WARN(** _message expression_ **)**
@@ -57,26 +118,37 @@ The message is reported and the test case fails.
AS `FAIL`, but does not abort the test
## Quickly capture a variable value
## Quickly capture value of variables or expressions
**CAPTURE(** _expression_ **)**
**CAPTURE(** _expression1_, _expression2_, ... **)**
Sometimes you just want to log the name and value of a variable. While you can easily do this with the INFO macro, above, as a convenience the CAPTURE macro handles the stringising of the variable name for you (actually it works with any expression, not just variables).
Sometimes you just want to log a value of variable, or expression. For
convenience, we provide the `CAPTURE` macro, that can take a variable,
or an expression, and prints out that variable/expression and its value
at the time of capture.
E.g.
```c++
CAPTURE( theAnswer );
e.g. `CAPTURE( theAnswer );` will log message "theAnswer := 42", while
```cpp
int a = 1, b = 2, c = 3;
CAPTURE( a, b, c, a + b, c > b, a == 1);
```
will log a total of 6 messages:
```
a := 1
b := 2
c := 3
a + b := 3
c > b := true
a == 1 := true
```
This would log something like:
You can also capture expressions that use commas inside parentheses
(e.g. function calls), brackets, or braces (e.g. initializers). To
properly capture expression that contains template parameters list
(in other words, it contains commas between angle brackets), you need
to enclose the expression inside parentheses:
`CAPTURE( (std::pair<int, int>{1, 2}) );`
<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).
---

View File

@@ -36,10 +36,41 @@ REQUIRE_THAT( str,
```
## Built in matchers
Currently Catch has some string matchers and some vector 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).
Catch currently provides some matchers, they are in the `Catch::Matchers` and `Catch` namespaces.
### 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.
### 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
It's easy to provide your own matchers to extend Catch or just to work with your own types.
@@ -61,7 +92,7 @@ public:
IntRange( int begin, int end ) : m_begin( begin ), m_end( end ) {}
// Performs the test for this matcher
virtual bool match( int const& i ) const override {
bool match( int const& i ) const override {
return i >= m_begin && i <= m_end;
}
@@ -69,7 +100,7 @@ public:
// include any provided data (the begin/ end in this case) and
// be written as if it were stating a fact (in the output it will be
// preceded by the value under test).
virtual std::string describe() const {
virtual std::string describe() const override {
std::ostringstream ss;
ss << "is between " << m_begin << " and " << m_end;
return ss.str();

View File

@@ -1,42 +1,63 @@
<a id="top"></a>
# Open Source projects using Catch
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
it's easy to just drop the header into your project and start writing tests - what's not to like?
As a result Catch is now being used in many Open Source projects, including some quite well known ones.
This page is an attempt to track those projects. Obviously it can never be complete.
This effort largely relies on the maintainers of the projects themselves updating this page and submitting a PR
(or, if you prefer contact one of the maintainers of Catch directly, use the
(or, if you prefer contact one of the maintainers of Catch directly, use the
[forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)), or raise an [issue](https://github.com/philsquared/Catch/issues) to let us know).
Of course users of those projects might want to update this page too. That's fine - as long you're confident the project maintainers won't mind.
If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
just let us know via any of the previously mentioned means - although I'm sure there won't be many who feel that way.
Listing a project here does not imply endorsement and the plan is to keep these ordered alphabetically to avoid an implication of relative importance.
## Libraries & Frameworks
### [ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp)
C++11 implementation of Approval Tests, for quick, convenient testing of legacy code.
### [Azmq](https://github.com/zeromq/azmq)
Boost Asio style bindings for ZeroMQ
Boost Asio style bindings for ZeroMQ.
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
The core part of the Chakra Javascript engine that powers Microsoft Edge
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques.
### [Clara](https://github.com/philsquared/Clara)
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
The next-generation core storage and query engine for Couchbase Lite/
The next-generation core storage and query engine for Couchbase Lite.
### [cppcodec](https://github.com/tplgy/cppcodec)
Header-only C++11 library to encode/decode base64, base64url, base32, base32hex and hex (a.k.a. base16) as specified in RFC 4648, plus Crockford's base32.
### [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)
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
### [libcluon](https://github.com/chrberger/libcluon)
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
### [MNMLSTC Core](https://github.com/mnmlstc/core)
a small and easy to use C++11 library that adds a functionality set that will be available in C++14 and later, as well as some useful additions
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/)
A small C++ library wrapper for the native C ODBC API.
@@ -45,22 +66,25 @@ A small C++ library wrapper for the native C ODBC API.
A header-only framework for benchmarking small snippets of C++ code.
### [SOCI](https://github.com/SOCI/soci)
The C++ Database Access Library
The C++ Database Access Library.
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
A polymorphic value-type for C++
A polymorphic value-type for C++.
### [Ppconsul](https://github.com/oliora/ppconsul)
A C++ client library for Consul. Consul is a distributed tool for discovering and configuring services in your infrastructure
A C++ client library for Consul. Consul is a distributed tool for discovering and configuring services in your infrastructure.
### [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)
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.
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
A thread safe header only mocking framework for C++14
A thread-safe header-only mocking framework for C++14.
### [args](https://github.com/Taywee/args)
A simple header-only C++ argument parser library.
@@ -74,13 +98,19 @@ ArangoDB is a native multi-model database with flexible data models for document
Minimal, open-source and cross-platform audio tool for live music production.
### [MAME](https://github.com/mamedev/mame)
MAME originally stood for Multiple Arcade Machine Emulator
MAME originally stood for Multiple Arcade Machine Emulator.
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
### [raspigcd](https://github.com/pantadeusz/raspigcd)
Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrolers (just RPi + Stepsticks).
### [SpECTRE](https://github.com/sxs-collaboration/spectre)
SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
### [Standardese](https://github.com/foonathan/standardese)
Standardese aims to be a nextgen Doxygen
Standardese aims to be a nextgen Doxygen.
---

150
docs/other-macros.md Normal file
View File

@@ -0,0 +1,150 @@
<a id="top"></a>
# Other macros
This page serves as a reference for macros that are not documented
elsewhere. For now, these macros are separated into 2 rough categories,
"assertion related macros" and "test case related macros".
## Assertion related macros
* `CHECKED_IF` and `CHECKED_ELSE`
`CHECKED_IF( expr )` is an `if` replacement, that also applies Catch2's
stringification machinery to the _expr_ and records the result. As with
`if`, the block after a `CHECKED_IF` is entered only if the expression
evaluates to `true`. `CHECKED_ELSE( expr )` work similarly, but the block
is entered only if the _expr_ evaluated to `false`.
Example:
```cpp
int a = ...;
int b = ...;
CHECKED_IF( a == b ) {
// This block is entered when a == b
} CHECKED_ELSE ( a == b ) {
// This block is entered when a != b
}
```
* `CHECK_NOFAIL`
`CHECK_NOFAIL( expr )` is a variant of `CHECK` that does not fail the test
case if _expr_ evaluates to `false`. This can be useful for checking some
assumption, that might be violated without the test necessarily failing.
Example output:
```
main.cpp:6:
FAILED - but was ok:
CHECK_NOFAIL( 1 == 2 )
main.cpp:7:
PASSED:
CHECK( 2 == 2 )
```
* `SUCCEED`
`SUCCEED( msg )` is mostly equivalent with `INFO( msg ); REQUIRE( true );`.
In other words, `SUCCEED` is for cases where just reaching a certain line
means that the test has been a success.
Example usage:
```cpp
TEST_CASE( "SUCCEED showcase" ) {
int I = 1;
SUCCEED( "I is " << I );
}
```
* `STATIC_REQUIRE`
`STATIC_REQUIRE( expr )` is a macro that can be used the same way as a
`static_assert`, but also registers the success with Catch2, so it is
reported as a success at runtime. The whole check can also be deferred
to the runtime, by defining `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE` before
including the Catch2 header.
Example:
```cpp
TEST_CASE("STATIC_REQUIRE showcase", "[traits]") {
STATIC_REQUIRE( std::is_void<void>::value );
STATIC_REQUIRE_FALSE( std::is_void<int>::value );
}
```
## Test case related macros
* `METHOD_AS_TEST_CASE`
`METHOD_AS_TEST_CASE( member-function-pointer, description )` lets you
register a member function of a class as a Catch2 test case. The class
will be separately instantiated for each method registered in this way.
```cpp
class TestClass {
std::string s;
public:
TestClass()
:s( "hello" )
{}
void testCase() {
REQUIRE( s == "hello" );
}
};
METHOD_AS_TEST_CASE( TestClass::testCase, "Use class's method as a test case", "[class]" )
```
* `REGISTER_TEST_CASE`
`REGISTER_TEST_CASE( function, description )` let's you register
a `function` as a test case. The function has to have `void()` signature,
the description can contain both name and tags.
Example:
```cpp
REGISTER_TEST_CASE( someFunction, "ManuallyRegistered", "[tags]" );
```
_Note that the registration still has to happen before Catch2's session
is initiated. This means that it either needs to be done in a global
constructor, or before Catch2's session is created in user's own main._
* `ANON_TEST_CASE`
`ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate
unique name. The advantage of this is that you do not have to think
of a name for the test case,`the disadvantage is that the name doesn't
necessarily remain stable across different links, and thus it might be
hard to run directly.
Example:
```cpp
ANON_TEST_CASE() {
SUCCEED("Hello from anonymous test case");
}
```
* `DYNAMIC_SECTION`
`DYNAMIC_SECTION` is a `SECTION` where the user can use `operator<<` to
create the final name for that section. This can be useful with e.g.
generators, or when creating a `SECTION` dynamically, within a loop.
Example:
```cpp
TEST_CASE( "looped SECTION tests" ) {
int a = 1;
for( int b = 0; b < 10; ++b ) {
DYNAMIC_SECTION( "b is currently: " << b ) {
CHECK( b > a );
}
}
}
```

View File

@@ -1,6 +1,12 @@
<a id="top"></a>
# 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.
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
If you still want Catch to process the command line, but you want to programatically tweak the config, you can do so in one of two ways:
If you still want Catch to process the command line, but you want to programmatically tweak the config, you can do so in one of two ways:
```c++
#define CATCH_CONFIG_RUNNER
@@ -45,7 +51,7 @@ int main( int argc, char* argv[] )
int returnCode = session.applyCommandLine( argc, argv );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
return returnCode;
// writing to session.configData() or session.Config() here
// overrides command line args
@@ -81,6 +87,7 @@ int main( int argc, char* argv[] )
int height = 0; // Some user variable you want to be able to set
// Build a new parser on top of Catch's
using namespace Catch::clara;
auto cli
= session.cli() // Get Catch's composite command line parser
| Opt( height, "height" ) // bind variable to a new option, with a hint string
@@ -93,7 +100,7 @@ int main( int argc, char* argv[] )
// Let Catch (using Clara) parse the command line
int returnCode = session.applyCommandLine( argc, argv );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
return returnCode;
// if set on the command line then 'height' is now set at this point
if( height > 0 )
@@ -105,6 +112,20 @@ int main( int argc, char* argv[] )
See the [Clara documentation](https://github.com/philsquared/Clara/blob/master/README.md) for more details.
## Version detection
Catch provides a triplet of macros providing the header's version,
* `CATCH_VERSION_MAJOR`
* `CATCH_VERSION_MINOR`
* `CATCH_VERSION_PATCH`
these macros expand into a single number, that corresponds to the appropriate
part of the version. As an example, given single header version v2.3.4,
the macros would expand into `2`, `3`, and `4` respectively.
---
[Home](Readme.md#top)

View File

@@ -1,7 +1,469 @@
<a id="top"></a>
# 2.0.1
## Breaking changes
# Release notes
**Contents**<br>
[2.8.0](#280)<br>
[2.7.2](#272)<br>
[2.7.1](#271)<br>
[2.7.0](#270)<br>
[2.6.1](#261)<br>
[2.6.0](#260)<br>
[2.5.0](#250)<br>
[2.4.2](#242)<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.8.0
### Improvements
* Templated test cases no longer check whether the provided types are unique (#1628)
* This allows you to e.g. test over `uint32_t`, `uint64_t`, and `size_t` without compilation failing
* The precision of floating point stringification can be modified by user (#1612, #1614)
* We now provide `REGISTER_ENUM` convenience macro for generating `StringMaker` specializations for enums
* See the "String conversion" documentation for details
* Added new set of macros for template test cases that enables the use of NTTPs (#1531, #1609)
* See "Test cases and sections" documentation for details
### Fixes
* `UNSCOPED_INFO` macro now has a prefixed/disabled/prefixed+disabled versions (#1611)
* Reporting errors at startup should no longer cause a segfault under certain circumstances (#1626)
### Miscellaneous
* CMake will now prevent you from attempting in-tree build (#1636, #1638)
* Previously it would break with an obscure error message during the build step
## 2.7.2
### Improvements
* Added an approximate vector matcher (#1499)
### Fixes
* Filters will no longer be shown if there were none
* Fixed compilation error when using Homebrew GCC on OS X (#1588, #1589)
* Fixed the console reporter not showing messages that start with a newline (#1455, #1470)
* Modified JUnit reporter's output so that rng seed and filters are reported according to the JUnit schema (#1598)
* Fixed some obscure warnings and static analysis passes
### Miscellaneous
* Various improvements to `ParseAndAddCatchTests` (#1559, #1601)
* When a target is parsed, it receives `ParseAndAddCatchTests_TESTS` property which summarizes found tests
* Fixed problem with tests not being found if the `OptionalCatchTestLauncher` variables is used
* Including the script will no longer forcefully modify `CMAKE_MINIMUM_REQUIRED_VERSION`
* CMake object libraries are ignored when parsing to avoid needless warnings
* `CatchAddTests` now adds test's tags to their CTest labels (#1600)
* Added basic CPack support to our build
## 2.7.1
### Improvements
* Reporters now print out the filters applied to test cases (#1550, #1585)
* Added `GENERATE_COPY` and `GENERATE_VAR` macros that can use variables inside the generator expression
* Because of the significant danger of lifetime issues, the default `GENERATE` macro still does not allow variables
* The `map` generator helper now deduces the mapped return type (#1576)
### Fixes
* Fixed ObjC++ compilation (#1571)
* Fixed test tag parsing so that `[.foo]` is now parsed as `[.][foo]`.
* Suppressed warning caused by the Windows headers defining SE codes in different manners (#1575)
## 2.7.0
### Improvements
* `TEMPLATE_PRODUCT_TEST_CASE` now uses the resulting type in the name, instead of the serial number (#1544)
* Catch2's single header is now strictly ASCII (#1542)
* Added generator for random integral/floating point types
* The types are inferred within the `random` helper
* Added back RangeGenerator (#1526)
* RangeGenerator returns elements within a certain range
* Added ChunkGenerator generic transform (#1538)
* A ChunkGenerator returns the elements from different generator in chunks of n elements
* Added `UNSCOPED_INFO` (#415, #983, #1522)
* This is a variant of `INFO` that lives until next assertion/end of the test case.
### Fixes
* All calls to C stdlib functions are now `std::` qualified (#1541)
* Code brought in from Clara was also updated.
* Running tests will no longer open the specified output file twice (#1545)
* This would cause trouble when the file was not a file, but rather a named pipe
* Fixes the CLion/Resharper integration with Catch
* Fixed `-Wunreachable-code` occurring with (old) ccache+cmake+clang combination (#1540)
* Fixed `-Wdefaulted-function-deleted` warning with Clang 8 (#1537)
* Catch2's type traits and helpers are now properly namespaced inside `Catch::` (#1548)
* Fixed std{out,err} redirection for failing test (#1514, #1525)
* Somehow, this bug has been present for well over a year before it was reported
### Contrib
* `ParseAndAddCatchTests` now properly escapes commas in the test name
## 2.6.1
### Improvements
* The JUnit reporter now also reports random seed (#1520, #1521)
### Fixes
* The TAP reporter now formats comments with test name properly (#1529)
* `CATCH_REQUIRE_THROWS`'s internals were unified with `REQUIRE_THROWS` (#1536)
* This fixes a potential `-Wunused-value` warning when used
* Fixed a potential segfault when using any of the `--list-*` options (#1533, #1534)
## 2.6.0
**With this release the data generator feature is now fully supported.**
### Improvements
* Added `TEMPLATE_PRODUCT_TEST_CASE` (#1454, #1468)
* This allows you to easily test various type combinations, see documentation for details
* The error message for `&&` and `||` inside assertions has been improved (#1273, #1480)
* The error message for chained comparisons inside assertions has been improved (#1481)
* Added `StringMaker` specialization for `std::optional` (#1510)
* The generator interface has been redone once again (#1516)
* It is no longer considered experimental and is fully supported
* The new interface supports "Input" generators
* The generator documentation has been fully updated
* We also added 2 generator examples
### Fixes
* Fixed `-Wredundant-move` on newer Clang (#1474)
* Removed unreachable mentions `std::current_exception`, `std::rethrow_exception` in no-exceptions mode (#1462)
* This should fix compilation with IAR
* Fixed missing `<type_traits>` include (#1494)
* Fixed various static analysis warnings
* Unrestored stream state in `XmlWriter` (#1489)
* Potential division by zero in `estimateClockResolution` (#1490)
* Uninitialized member in `RunContext` (#1491)
* `SourceLineInfo` move ops are now marked `noexcept`
* `CATCH_BREAK_INTO_DEBUGGER` is now always a function
* Fix double run of a test case if user asks for a specific section (#1394, #1492)
* ANSI colour code output now respects `-o` flag and writes to the file as well (#1502)
* Fixed detection of `std::variant` support for compilers other than Clang (#1511)
### Contrib
* `ParseAndAddCatchTests` has learned how to use `DISABLED` CTest property (#1452)
* `ParseAndAddCatchTests` now works when there is a whitspace before the test name (#1493)
### Miscellaneous
* We added new issue templates for reporting issues on GitHub
* `contributing.md` has been updated to reflect the current test status (#1484)
## 2.5.0
### Improvements
* Added support for templated tests via `TEMPLATE_TEST_CASE` (#1437)
### Fixes
* Fixed compilation of `PredicateMatcher<const char*>` by removing partial specialization of `MatcherMethod<T*>`
* Listeners now implicitly support any verbosity (#1426)
* Fixed compilation with Embarcadero builder by introducing `Catch::isnan` polyfill (#1438)
* Fixed `CAPTURE` asserting for non-trivial captures (#1436, #1448)
### Miscellaneous
* We should now be providing first party Conan support via https://bintray.com/catchorg/Catch2 (#1443)
* Added new section "deprecations and planned changes" to the documentation
* It contains summary of what is deprecated and might change with next major version
* From this release forward, the released headers should be pgp signed (#430)
* KeyID `E29C 46F3 B8A7 5028 6079 3B7D ECC9 C20E 314B 2360`
* or https://codingnest.com/files/horenmar-publickey.asc
## 2.4.2
### Improvements
* XmlReporter now also outputs the RNG seed that was used in a run (#1404)
* `Catch::Session::applyCommandLine` now also accepts `wchar_t` arguments.
* However, Catch2 still does not support unicode.
* Added `STATIC_REQUIRE` macro (#1356, #1362)
* Catch2's singleton's are now cleaned up even if tests are run (#1411)
* This is mostly useful as a FP prevention for users who define their own main.
* Specifying an invalid reporter via `-r` is now reported sooner (#1351, #1422)
### Fixes
* Stringification no longer assumes that `char` is signed (#1399, #1407)
* This caused a `Wtautological-compare` warning.
* SFINAE for `operator<<` no longer sees different overload set than the actual insertion (#1403)
### Contrib
* `catch_discover_tests` correctly adds tests with comma in name (#1327, #1409)
* Added a new customization point in how the tests are launched to `catch_discover_tests`
## 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 legacy reporter support
* Removed legacy generator support
@@ -31,12 +493,12 @@
* `INFINITY == Approx(INFINITY)` returns true
## Improvements
### Improvements
* 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.
* 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.
* 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.
* 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});`)
@@ -65,7 +527,7 @@
* Add `pkg-config` support to CMake install command
## Fixes
### 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
@@ -77,7 +539,7 @@
* Suppressed C4061 warning under MSVC
## Internal changes
### Internal changes
* The development version now uses .cpp files instead of header files containing implementation.
* This makes partial rebuilds much faster during development
* The expression decomposition layer has been rewritten
@@ -85,22 +547,77 @@
* New library (TextFlow) is used for formatting text to output
# Older versions
## Older versions
## 1.9.x
### 1.12.x
### 1.9.6
#### 1.12.2
##### Fixes
* Fixed missing <cassert> include
#### Improvements
#### 1.12.1
##### Fixes
* Fixed deprecation warning in `ScopedMessage::~ScopedMessage`
* All uses of `min` or `max` identifiers are now wrapped in parentheses
* This avoids problems when Windows headers define `min` and `max` macros
#### 1.12.0
##### Fixes
* Fixed compilation for strict C++98 mode (ie not gnu++98) and older compilers (#1103)
* `INFO` messages are included in the `xml` reporter output even without `-s` specified.
### 1.11.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)
* Added `--list-extra-info` cli option (#934).
* 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)
* 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)
@@ -108,35 +625,35 @@
* 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)
#### Improvements
##### Improvements
* CMake integration script now incorporates debug messages and registers tests in an improved way (#911)
* Various documentation improvements
### 1.9.4
#### 1.9.4
#### Fixes
##### Fixes
* `CATCH_FAIL` macro no longer causes compilation error without variadic macro support
* `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.
* 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
### 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)
* Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't.
#### Fixes
##### Fixes
* POSIX signals are now disabled by default under QNX (#889)
* 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.
@@ -144,22 +661,22 @@
* Catch no longer attempts to define `uint64_t` on windows (#862)
* 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
* We now provide cmake script that autoregisters Catch tests into ctest.
* See `contrib` folder.
### 1.9.1
#### 1.9.1
#### Fixes
##### Fixes
* 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.
* It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions
* This actually reverts changes made in v1.7.2
@@ -173,7 +690,7 @@
* 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
#### Fixes:
##### Fixes:
* 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`.
* 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.
@@ -182,18 +699,18 @@
* [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
* 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
* This should be more consistent with the protocol desired behaviour.
* Compact reporter now obeys `-d yes` argument (#780)
@@ -207,7 +724,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.
#### Fixes:
##### Fixes:
* 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.
* Fixed (C4265) missing virtual destructor warning in Matchers (#844)
@@ -224,21 +741,21 @@
* Regression in Objective-C bindings (Matchers) fixed (#854)
#### Other notes:
##### Other notes:
* 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).
### 1.8.1
#### 1.8.1
#### Fixes
##### Fixes
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.
* Catch provides string and vector matchers.
@@ -258,33 +775,33 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
* `Approx` now supports an optional margin of absolute error
* It has also received [new documentation](assertions.md#top).
#### Fixes
##### Fixes
* Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer.
* Fixed C4512 ("assignment operator could not be generated") warnings under VS2013.
* Cygwin compatibility fixes
* Signal handling is no longer compiled by default.
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
* Improved `-Wparentheses` supression for gcc (#674)
* When compiled with gcc 4.8 or newer, the supression is localized to assertions only
* Otherwise it is supressed for the whole TU
* Improved `-Wparentheses` suppression for gcc (#674)
* When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
* Otherwise it is suppressed for the whole TU
* Fixed test spec parser issue (with escapes in multiple names)
#### Other
##### Other
* 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:
(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)
* Revert XML output to XML 1.0
* Can provide stylesheet references by extending the XML reporter
* Added description and tags attribites to XML Reporter
* Added description and tags attributes to XML Reporter
* Tags are closed and the stream flushed more eagerly to avoid stdout interpolation
@@ -296,9 +813,9 @@ Other:
* Silenced a few more warnings in different circumstances
* Travis improvements
### 1.7.1
#### 1.7.1
#### Fixes:
##### Fixes:
* 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.
* For specifics, look into the [documentation](configuration.md#top).
@@ -308,9 +825,9 @@ Other:
* 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.
### 1.7.0
#### 1.7.0
#### Features/ Changes:
##### Features/ Changes:
* Catch now runs significantly faster for passing tests
* 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.
@@ -324,32 +841,32 @@ Other:
* 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`.
#### Fixes:
##### Fixes:
* 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.
* 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.
#### Other:
##### Other:
* Catch's CMakeLists now defines install command.
* 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
#### Fixes:
##### Fixes:
* Generators no longer leak memory (generators are still unsupported in general)
* JUnit reporter now reports UTC timestamps, instead of "tbd"
* `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros
#### Other:
##### Other:
* Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
* The use of `__COUNTER__` is supressed when Catch is parsed by CLion
* The use of `__COUNTER__` is suppressed when Catch is parsed by CLion
* This change is not active when compiling a binary
* Approval tests can now be run on Windows
* CMake will now warn if a file is present in the `include` folder but not is not enumerated as part of the project
@@ -357,28 +874,28 @@ Other:
* 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.
#### Features/ Changes:
##### Features/ Changes:
* Approx now supports `>=` and `<=`
* Can now use `\` to escape chars in test names on command line
* Standardize C++11 feature toggles
#### Fixes:
##### Fixes:
* Blue shell colour
* Missing argument to `CATCH_CHECK_THROWS`
* Don't encode extended ASCII in XML
* use `std::shuffle` on more compilers (fixes deprecation warning/error)
* Use `__COUNTER__` more consistently (where available)
#### Other:
##### Other:
* 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
---

View File

@@ -1,18 +1,18 @@
<a id="top"></a>
# How to release
When enough changes have accumulated, it is time to release new version of Catch. This document describes the proces in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
When enough changes have accumulated, it is time to release new version of Catch. This document describes the process in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
## Neccessary steps
## Necessary steps
These steps are neccessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
These steps are necessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
### Approval testing
### Testing
Catch's releases are primarily validated against output from previous release, stored in `projects/SelfTest/Baselines`. To validate current sources, build the SelfTest binary and pass it to the `approvalTests.py` script: `approvalTests.py <path/to/SelfTest>`.
There should be no differences, as Approval tests should be updated when changes to Catch are made, but if there are, then they need to be manually reviewed and either approved (using `approve.py`) or Catch requires other fixes.
All of the tests are currently run in our CI setup based on TravisCI and
AppVeyor. As long as the last commit tested green, the release can
proceed.
### Incrementing version number
@@ -21,44 +21,52 @@ Catch uses a variant of [semantic versioning](http://semver.org/), with breaking
After deciding which part of version number should be incremented, you can use one of the `*Release.py` scripts to perform the required changes to Catch.
### Generate updated single-include header
After updating version number, regenerate single-include header using `generateSingleHeader.py`.
This will take care of generating the single include header, updating
version numbers everywhere and pushing the new version to Wandbox.
### Release notes
Once a release is ready, release notes need to be written. They should summarize changes done since last release. For rough idea of expected notes see previous releases. Once written, release notes should be placed in `docs/release-notes.md`.
Once a release is ready, release notes need to be written. They should summarize changes done since last release. For rough idea of expected notes see previous releases. Once written, release notes should be added to `docs/release-notes.md`.
### Commit and push update to GitHub
After version number is incremented, single-include header is regenerated and release notes are updated, changes should be commited and pushed to GitHub.
After version number is incremented, single-include header is regenerated and release notes are updated, changes should be committed and pushed to 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 might be
dependent on a specific version of the single-include header.
## Optional steps
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
signed.
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.
#### Signing a tag
To create a signed tag, use `git tag -s <VERSION>`, where `<VERSION>`
is the version being released, e.g. `git tag -s v2.6.0`.
### vcpkg update
Use the version name as the short message and the release notes as
the body (long) message.
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.
#### Signing the headers
This will create ASCII-armored signatures for the headers that are
uploaded to the GitHub release:
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
$ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
```
### 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.
_GPG does not support signing multiple files in single invocation._

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.
Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`.
* `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands.
Use this when building as part of a TeamCity build to see results as they happen.
* `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 ([code example](../examples/207-Rpt-TeamCityReporter.cpp)).
* `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

View File

@@ -51,14 +51,15 @@ After compiling `tests-main.cpp` once, it is enough to link it with separately c
```
$ g++ tests-main.cpp -c
$ g++ tests-main.o tests-factorial.cpp -o tests && ./tests -r compact
$ g++ factorial.cpp -c
$ g++ tests-main.o factorial.o tests-factorial.cpp -o tests && ./tests -r compact
Passed 1 test case with 4 assertions.
```
Now, the next time we change the file `tests-factorial.cpp` (say we add `REQUIRE( Factorial(0) == 1)`), it is enough to recompile the tests instead of recompiling main as well:
```
$ g++ tests-main.o tests-factorial.cpp -o tests && ./tests -r compact
$ g++ tests-main.o factorial.o tests-factorial.cpp -o tests && ./tests -r compact
tests-factorial.cpp:11: failed: Factorial(0) == 1 for: 0 == 1
Failed 1 test case, failed 1 assertion.
```

View File

@@ -1,6 +1,13 @@
<a id="top"></a>
# Test cases and sections
**Contents**<br>
[Tags](#tags)<br>
[Tag aliases](#tag-aliases)<br>
[BDD-style test cases](#bdd-style-test-cases)<br>
[Type parametrised test cases](#type-parametrised-test-cases)<br>
[Signature based parametrised test cases](#signature-based-parametrised-test-cases)<br>
While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style.
Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#test-cases-and-sections).
@@ -20,10 +27,10 @@ Tags allow an arbitrary number of additional strings to be associated with a tes
As an example - given the following test cases:
TEST_CASE( "A", "[widget]" ) { /* ... */ }
TEST_CASE( "B", "[widget]" ) { /* ... */ }
TEST_CASE( "C", "[gadget]" ) { /* ... */ }
TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ }
TEST_CASE( "A", "[widget]" ) { /* ... */ }
TEST_CASE( "B", "[widget]" ) { /* ... */ }
TEST_CASE( "C", "[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.
@@ -37,7 +44,7 @@ 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.
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
@@ -55,11 +62,11 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
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:
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.
@@ -86,6 +93,155 @@ When any of these macros are used the console reporter recognises them and forma
Other than the additional prefixes and the formatting in the console reporter these macros behave exactly as ```TEST_CASE```s and ```SECTION```s. As such there is nothing enforcing the correct sequencing of these macros - that's up to the programmer!
## Type parametrised test cases
In addition to `TEST_CASE`s, Catch2 also supports test cases parametrised
by types, in the form of `TEMPLATE_TEST_CASE` and
`TEMPLATE_PRODUCT_TEST_CASE`.
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
_test name_ and _tag_ are exactly the same as they are in `TEST_CASE`,
with the difference that the tag string must be provided (however, it
can be empty). _type1_ through _typen_ is the list of types for which
this test case should run, and, inside the test code, the current type
is available as the `TestType` type.
Because of limitations of the C++ preprocessor, if you want to specify
a type with multiple template parameters, you need to enclose it in
parentheses, e.g. `std::map<int, std::string>` needs to be passed as
`(std::map<int, std::string>)`.
Example:
```cpp
TEMPLATE_TEST_CASE( "vectors can be sized and resized", "[vector][template]", int, std::string, (std::tuple<int,float>) ) {
std::vector<TestType> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
SECTION( "resizing bigger changes size and capacity" ) {
v.resize( 10 );
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "resizing smaller changes size but not capacity" ) {
v.resize( 0 );
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
SECTION( "We can use the 'swap trick' to reset the capacity" ) {
std::vector<TestType> empty;
empty.swap( v );
REQUIRE( v.capacity() == 0 );
}
}
SECTION( "reserving smaller does not change size or capacity" ) {
v.reserve( 0 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
}
}
```
* **TEMPLATE_PRODUCT_TEST_CASE(** _test name_ , _tags_, (_template-type1_, _template-type2_, ..., _template-typen_), (_template-arg1_, _template-arg2_, ..., _template-argm_) **)**
_template-type1_ through _template-typen_ is list of template template
types which should be combined with each of _template-arg1_ through
_template-argm_, resulting in _n * m_ test cases. Inside the test case,
the resulting type is available under the name of `TestType`.
To specify more than 1 type as a single _template-type_ or _template-arg_,
you must enclose the types in an additional set of parentheses, e.g.
`((int, float), (char, double))` specifies 2 template-args, each
consisting of 2 concrete types (`int`, `float` and `char`, `double`
respectively). You can also omit the outer set of parentheses if you
specify only one type as the full set of either the _template-types_,
or the _template-args_.
Example:
```cpp
template< typename T>
struct Foo {
size_t size() {
return 0;
}
};
TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]", (std::vector, Foo), (int, float)) {
TestType x;
REQUIRE(x.size() == 0);
}
```
You can also have different arities in the _template-arg_ packs:
```cpp
TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
TestType x;
REQUIRE(std::tuple_size<TestType>::value >= 1);
}
```
_While there is an upper limit on the number of types you can specify
in single `TEMPLATE_TEST_CASE` or `TEMPLATE_PRODUCT_TEST_CASE`, the limit
is very high and should not be encountered in practice._
## Signature based parametrised test cases
In addition to [type parametrised test cases](#type-parametrised-test-cases) Catch2 also supports
signature base parametrised test cases, in form of `TEMPLATE_TEST_CASE_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_SIG`.
These test cases have similar syntax like [type parametrised test cases](#type-parametrised-test-cases), with one
additional positional argument which specifies the signature.
### Signature
Signature has some strict rules for these tests cases to work properly:
* signature with multiple template parameters e.g. `typename T, size_t S` must have this format in test case declaration
`((typename T, size_t S), T, S)`
* signature with variadic template arguments e.g. `typename T, size_t S, typename...Ts` must have this format in test case declaration
`((typename T, size_t S, typename...Ts), T, S, Ts...)`
* signature with single non type template parameter e.g. `int V` must have this format in test case declaration `((int V), V)`
* signature with single type template parameter e.g. `typename T` should not be used as it is in fact `TEMPLATE_TEST_CASE`
Currently Catch2 support up to 11 template parameters in signature
### Examples
* **TEMPLATE_TEST_CASE_SIG(** _test name_ , _tags_, _signature_, _type1_, _type2_, ..., _typen_ **)**
Inside `TEMPLATE_TEST_CASE_SIG` test case you can use the names of template parameters as defined in _signature_.
```cpp
TEMPLATE_TEST_CASE_SIG("TemplateTestSig: arrays can be created from NTTP arguments", "[vector][template][nttp]",
((typename T, int V), T, V), (int,5), (float,4), (std::string,15), ((std::tuple<int, float>), 6)) {
std::array<T, V> v;
REQUIRE(v.size() > 1);
}
```
* **TEMPLATE_PRODUCT_TEST_CASE_SIG(** _test name_ , _tags_, _signature_, (_template-type1_, _template-type2_, ..., _template-typen_), (_template-arg1_, _template-arg2_, ..., _template-argm_) **)**
```cpp
template<typename T, size_t S>
struct Bar {
size_t size() { return S; }
};
TEMPLATE_PRODUCT_TEST_CASE_SIG("A Template product test case with array signature", "[template][product][nttp]", ((typename T, size_t S), T, S), (std::array, Bar), ((int, 9), (float, 42))) {
TestType x;
REQUIRE(x.size() > 0);
}
```
---
[Home](Readme.md#top)

View File

@@ -30,6 +30,87 @@ class UniqueTestsFixture {
The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter.
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD` and
`TEMPLATE_PRODUCT_TEST_CASE_METHOD` that can be used together
with templated fixtures and templated template fixtures to perform
tests for multiple different types. Unlike `TEST_CASE_METHOD`,
`TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD` do
require the tag specification to be non-empty, as it is followed by
further macro arguments.
Also note that, because of limitations of the C++ preprocessor, if you
want to specify a type with multiple template parameters, you need to
enclose it in parentheses, e.g. `std::map<int, std::string>` needs to be
passed as `(std::map<int, std::string>)`.
In the case of `TEMPLATE_PRODUCT_TEST_CASE_METHOD`, if a member of the
type list should consist of more than single type, it needs to be enclosed
in another pair of parentheses, e.g. `(std::map, std::pair)` and
`((int, float), (char, double))`.
Example:
```cpp
template< typename T >
struct Template_Fixture {
Template_Fixture(): m_a(1) {}
T m_a;
};
TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
}
template<typename T>
struct Template_Template_Fixture {
Template_Template_Fixture() {}
T m_a;
};
template<typename T>
struct Foo_class {
size_t size() {
return 0;
}
};
TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Template_Fixture, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test succeeds", "[class][template]", (Foo_class, std::vector), int) {
REQUIRE( Template_Template_Fixture<TestType>::m_a.size() == 0 );
}
```
_While there is an upper limit on the number of types you can specify
in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
the limit is very high and should not be encountered in practice._
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG` to support
fixtures using non-type template parameters. These test cases work similar to `TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
with additional positional argument for [signature](test-cases-and-sections.md#signature-based-parametrised-test-cases).
Example:
```cpp
template <int V>
struct Nttp_Fixture{
int value = V;
};
TEMPLATE_TEST_CASE_METHOD_SIG(Nttp_Fixture, "A TEMPLATE_TEST_CASE_METHOD_SIG based test run that succeeds", "[class][template][nttp]",((int V), V), 1, 3, 6) {
REQUIRE(Nttp_Fixture<V>::value > 0);
}
template< typename T, size_t V>
struct Template_Foo_2 {
size_t size() { return V; }
};
TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG based test run that succeeds", "[class][template][product][nttp]", ((typename T, size_t S), T, S),(std::array, Template_Foo_2), ((int,2), (float,6)))
{
REQUIRE(Template_Fixture_2<TestType>{}.m_a.size() >= 2);
}
```
---
[Home](Readme.md#top)

View File

@@ -1,6 +1,15 @@
<a id="top"></a>
# 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>
[Enums](#enums)<br>
[Floating point precision](#floating-point-precision)<br>
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.
@@ -8,41 +17,112 @@ Most built-in or std types are supported out of the box but there are two ways t
This is the standard way of providing string conversions in C++ - and the chances are you may already provide this for your own purposes. If you're not familiar with this idiom it involves writing a free function of the form:
```
```cpp
std::ostream& operator << ( std::ostream& os, T const& value ) {
os << convertMyTypeToString( value );
return os;
os << convertMyTypeToString( value );
return os;
}
```
(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
You should put this function in the same namespace as your type and have it declared before including Catch's header.
You should put this function in the same namespace as your type, or the global namespace, 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>`:
```
```cpp
namespace Catch {
template<>
template<>
struct StringMaker<T> {
static std::string convert( T const& value ) {
return convertMyTypeToString( value );
static std::string convert( T const& 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
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:
```
```cpp
CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
return ex.message();
return ex.message();
}
```
## Enums
Enums that already have a `<<` overload for `std::ostream` will convert to strings as expected.
If you only need to convert enums to strings for test reporting purposes you can provide a `StringMaker` specialisations as any other type.
However, as a convenience, Catch provides the `REGISTER_ENUM` helper macro that will generate the `StringMaker` specialiation for you with minimal code.
Simply provide it the (qualified) enum name, followed by all the enum values, and you're done!
E.g.
```cpp
enum class Fruits { Banana, Apple, Mango };
CATCH_REGISTER_ENUM( Fruits, Fruits::Banana, Fruits::Apple, Fruits::Mango )
TEST_CASE() {
REQUIRE( Fruits::Mango == Fruits::Apple );
}
```
... or if the enum is in a namespace:
```cpp
namespace Bikeshed {
enum class Colours { Red, Green, Blue };
}
// Important!: This macro must appear at top level scope - not inside a namespace
// You can fully qualify the names, or use a using if you prefer
CATCH_REGISTER_ENUM( Bikeshed::Colours,
Bikeshed::Colours::Red,
Bikeshed::Colours::Green,
Bikeshed::Colours::Blue )
TEST_CASE() {
REQUIRE( Bikeshed::Colours::Red == Bikeshed::Colours::Blue );
}
```
## Floating point precision
Catch provides a built-in `StringMaker` specialization for both `float`
and `double`. By default, it uses what we think is a reasonable precision,
but you can customize it by modifying the `precision` static variable
inside the `StringMaker` specialization, like so:
```cpp
Catch::StringMaker<float>::precision = 15;
const float testFloat1 = 1.12345678901234567899f;
const float testFloat2 = 1.12345678991234567899f;
REQUIRE(testFloat1 == testFloat2);
```
This assertion will fail and print out the `testFloat1` and `testFloat2`
to 15 decimal places.
---
[Home](Readme.md#top)

View File

@@ -8,24 +8,31 @@
[Test cases and sections](#test-cases-and-sections)<br>
[BDD-Style](#bdd-style)<br>
[Scaling up](#scaling-up)<br>
[Type parametrised test cases](#type-parametrised-test-cases)<br>
[Next steps](#next-steps)<br>
## Getting Catch2
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/CatchOrg/Catch2/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
Alternative ways of getting Catch2 include using your system package
manager, or installing it using [its CMake package](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?
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).
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](https://levelofindirection.com/blog/unit-testing-in-cpp-and-objective-c-just-got-ridiculously-easier-still.html).
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
_If you have installed Catch2 from system package manager, or CMake
package, you need to include the header as `#include <catch2/catch.hpp>`_
## Writing tests
Let's start with a really simple example. 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++
unsigned int Factorial( unsigned int number ) {
@@ -33,7 +40,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++
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
@@ -96,7 +103,7 @@ Of course there are still more issues to deal with. For example we'll hit proble
### What did we do here?
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on.
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take a moment to consider those before we move on.
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md#top). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md#top)).
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests.
@@ -110,37 +117,37 @@ 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>).
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++
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
SECTION( "resizing bigger changes size and capacity" ) {
v.resize( 10 );
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
SECTION( "resizing smaller changes size but not capacity" ) {
v.resize( 0 );
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
}
SECTION( "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 );
}
@@ -152,18 +159,18 @@ This works because the ```SECTION``` macro contains an if statement that calls b
So far so good - this is already an improvement on the setup/teardown approach because now we see our setup code inline and use the stack.
The power of sections really shows, however, when we need to execute a sequence of, checked, operations. Continuing the vector example, we might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing. We can do that, naturally, like so:
The power of sections really shows, however, when we need to execute a sequence of checked operations. Continuing the vector example, we might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing. We can do that, naturally, like so:
```c++
SECTION( "reserving bigger changes capacity but not size" ) {
v.reserve( 10 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
SECTION( "reserving smaller again does not change capacity" ) {
v.reserve( 7 );
REQUIRE( v.capacity() >= 10 );
}
}
@@ -175,20 +182,20 @@ 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).
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++
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 );
@@ -196,7 +203,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
}
WHEN( "the size is reduced" ) {
v.resize( 0 );
THEN( "the size changes but not capacity" ) {
REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 );
@@ -204,7 +211,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
}
WHEN( "more capacity is reserved" ) {
v.reserve( 10 );
THEN( "the capacity changes but not the size" ) {
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 );
@@ -212,7 +219,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
}
WHEN( "less capacity is reserved" ) {
v.reserve( 0 );
THEN( "neither size nor capacity are changed" ) {
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
@@ -245,11 +252,22 @@ The requirement is that the following block of code ([or equivalent](own-main.md
appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```!
In fact it is usually a good idea to put the block with the ```#define``` [in 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!
## Type parametrised test cases
Test cases in Catch2 can be also parametrised by type, via the
`TEMPLATE_TEST_CASE` and `TEMPLATE_PRODUCT_TEST_CASE` macros,
which behave in the same way the `TEST_CASE` macro, but are run for
every type or type combination.
For more details, see our documentation on [test cases and
sections](test-cases-and-sections.md#type-parametrised-test-cases).
## Next steps
This has been a brief introduction to get you up and running with Catch, and to point out some of the key differences between Catch and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests.

View File

@@ -6,7 +6,7 @@ including (but not limited to),
[Google Test](http://code.google.com/p/googletest/),
[Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html),
[CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page),
[Cute](http://r2.ifs.hsr.ch/cute),
[Cute](http://www.cute-test.com),
[many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B).
So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course.

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
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
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")
void skipTest( Catch::TestCaseInfo const& testInfo ) override {
std::cout
<< dashed_line
<< "\nEvent: skipTest:\n";
print( std::cout, 1, "- testInfo", testInfo );
}
// Test cases starting
void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
std::cout
<< dashed_line
<< "\nEvent: testCaseStarting:\n";
print( std::cout, 1, "- testInfo", testInfo );
}
// Test cases ending
void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
std::cout << "\nEvent: testCaseEnded:\n";
print( std::cout, 1, "testCaseStats", testCaseStats );
}
// Sections starting
void sectionStarting( Catch::SectionInfo const& sectionInfo ) override {
std::cout << "\nEvent: sectionStarting:\n";
print( std::cout, 1, "- sectionInfo", sectionInfo );
}
// Sections ending
void sectionEnded( Catch::SectionStats const& sectionStats ) override {
std::cout << "\nEvent: sectionEnded:\n";
print( std::cout, 1, "- sectionStats", sectionStats );
}
// Assertions before/ after
void assertionStarting( Catch::AssertionInfo const& assertionInfo ) override {
std::cout << "\nEvent: assertionStarting:\n";
print( std::cout, 1, "- assertionInfo", assertionInfo );
}
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.");
}

View File

@@ -0,0 +1,59 @@
// 300-Gen-OwnGenerator.cpp
// Shows how to define a custom generator.
// Specifically we will implement a random number generator for integers
// It will have infinite capacity and settable lower/upper bound
#include <catch2/catch.hpp>
#include <random>
// This class shows how to implement a simple generator for Catch tests
class RandomIntGenerator : public Catch::Generators::IGenerator<int> {
std::minstd_rand m_rand;
std::uniform_int_distribution<> m_dist;
int current_number;
public:
RandomIntGenerator(int low, int high):
m_rand(std::random_device{}()),
m_dist(low, high)
{
static_cast<void>(next());
}
int const& get() const override;
bool next() override {
current_number = m_dist(m_rand);
return true;
}
};
// Avoids -Wweak-vtables
int const& RandomIntGenerator::get() const {
return current_number;
}
// This helper function provides a nicer UX when instantiating the generator
// Notice that it returns an instance of GeneratorWrapper<int>, which
// is a value-wrapper around std::unique_ptr<IGenerator<int>>.
Catch::Generators::GeneratorWrapper<int> random(int low, int high) {
return Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new RandomIntGenerator(low, high)));
}
// The two sections in this test case are equivalent, but the first one
// is much more readable/nicer to use
TEST_CASE("Generating random ints", "[example][generator]") {
SECTION("Nice UX") {
auto i = GENERATE(take(100, random(-100, 100)));
REQUIRE(i >= -100);
REQUIRE(i <= 100);
}
SECTION("Creating the random generator directly") {
auto i = GENERATE(take(100, GeneratorWrapper<int>(std::unique_ptr<IGenerator<int>>(new RandomIntGenerator(-100, 100)))));
REQUIRE(i >= -100);
REQUIRE(i <= 100);
}
}
// Compiling and running this file will result in 400 successful assertions

View File

@@ -0,0 +1,54 @@
// 301-Gen-MapTypeConversion.cpp
// Shows how to use map to modify generator's return type.
// TODO
#include <catch2/catch.hpp>
#include <string>
#include <sstream>
// Returns a line from a stream. You could have it e.g. read lines from
// a file, but to avoid problems with paths in examples, we will use
// a fixed stringstream.
class LineGenerator : public Catch::Generators::IGenerator<std::string> {
std::string m_line;
std::stringstream m_stream;
public:
LineGenerator() {
m_stream.str("1\n2\n3\n4\n");
if (!next()) {
throw Catch::GeneratorException("Couldn't read a single line");
}
}
std::string const& get() const override {
return m_line;
}
bool next() override {
return !!std::getline(m_stream, m_line);
}
};
// This helper function provides a nicer UX when instantiating the generator
// Notice that it returns an instance of GeneratorWrapper<std::string>, which
// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
Catch::Generators::GeneratorWrapper<std::string> lines(std::string /* ignored for example */) {
return Catch::Generators::GeneratorWrapper<std::string>(
std::unique_ptr<Catch::Generators::IGenerator<std::string>>(
new LineGenerator()
)
);
}
TEST_CASE("filter can convert types inside the generator expression", "[example][generator]") {
auto num = GENERATE(map<int>([](std::string const& line) { return std::stoi(line); },
lines("fake-file")));
REQUIRE(num > 0);
}
// Compiling and running this file will result in 4 successful assertions

View File

@@ -0,0 +1,33 @@
// 310-Gen-VariablesInGenerator.cpp
// Shows how to use variables when creating generators.
// Note that using variables inside generators is dangerous and should
// be done only if you know what you are doing, because the generators
// _WILL_ outlive the variables -- thus they should be either captured
// by value directly, or copied by the generators during construction.
#include <catch2/catch.hpp>
TEST_CASE("Generate random doubles across different ranges",
"[generator][example][advanced]") {
// Workaround for old libstdc++
using record = std::tuple<double, double>;
// Set up 3 ranges to generate numbers from
auto r = GENERATE(table<double, double>({
record{3, 4},
record{-4, -3},
record{10, 1000}
}));
// This will not compile (intentionally), because it accesses a variable
// auto number = GENERATE(take(50, random(std::get<0>(r), std::get<1>(r))));
// GENERATE_COPY copies all variables mentioned inside the expression
// thus this will work.
auto number = GENERATE_COPY(take(50, random(std::get<0>(r), std::get<1>(r))));
REQUIRE(std::abs(number) > 0);
}
// Compiling and running this file will result in 150 successful assertions

View File

@@ -0,0 +1,41 @@
// 311-Gen-CustomCapture.cpp
// Shows how to provide custom capture list to the generator expression
// Note that using variables inside generators is dangerous and should
// be done only if you know what you are doing, because the generators
// _WILL_ outlive the variables. Also, even if you know what you are
// doing, you should probably use GENERATE_COPY or GENERATE_REF macros
// instead. However, if your use case requires having a
// per-variable custom capture list, this example shows how to achieve
// that.
#include <catch2/catch.hpp>
TEST_CASE("Generate random doubles across different ranges",
"[generator][example][advanced]") {
// Workaround for old libstdc++
using record = std::tuple<double, double>;
// Set up 3 ranges to generate numbers from
auto r1 = GENERATE(table<double, double>({
record{3, 4},
record{-4, -3},
record{10, 1000}
}));
auto r2(r1);
// This will take r1 by reference and r2 by value.
// Note that there are no advantages for doing so in this example,
// it is done only for expository purposes.
auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
[&r1, r2]{
using namespace Catch::Generators;
return makeGenerators(take(50, random(std::get<0>(r1), std::get<1>(r2))));
}
);
REQUIRE(std::abs(number) > 0);
}
// Compiling and running this file will result in 150 successful assertions

157
examples/CMakeLists.txt Normal file
View File

@@ -0,0 +1,157 @@
#
# 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
300-Gen-OwnGenerator.cpp
301-Gen-MapTypeConversion.cpp
310-Gen-VariablesInGenerators.cpp
311-Gen-CustomCapture.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
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 8
#define CATCH_VERSION_PATCH 0
#ifdef __clang__
# pragma clang system_header
#elif defined __GNUC__
@@ -19,12 +23,22 @@
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL
# define CATCH_CONFIG_ALL_PARTS
#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"
#ifdef CATCH_IMPL
@@ -34,6 +48,7 @@
# endif
#endif
#include "internal/catch_user_interfaces.h"
#include "internal/catch_tag_alias_autoregistrar.h"
#include "internal/catch_test_registry.h"
#include "internal/catch_capture.hpp"
@@ -47,6 +62,9 @@
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
#include "internal/catch_capture_matchers.h"
#endif
#include "internal/catch_generators.hpp"
#include "internal/catch_generators_generic.hpp"
#include "internal/catch_generators_specific.hpp"
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
@@ -61,6 +79,8 @@
#include "internal/catch_external_interfaces.h"
#endif
#endif // ! CATCH_CONFIG_IMPL_ONLY
#ifdef CATCH_IMPL
#include "internal/catch_impl.hpp"
#endif
@@ -69,6 +89,7 @@
#include "internal/catch_default_main.hpp"
#endif
#if !defined(CATCH_CONFIG_IMPL_ONLY)
#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
# undef CLARA_CONFIG_MAIN
@@ -82,7 +103,7 @@
#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
@@ -96,7 +117,7 @@
#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
@@ -111,28 +132,61 @@
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", 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_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
#else
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
#endif
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
#define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
#else
#define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ )
#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
#endif
// "BDD-style" convenience wrappers
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc )
#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc )
#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc )
#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else
@@ -170,19 +224,50 @@
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", 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_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
#else
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
#endif
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
#define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
#else
#define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ )
#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
#endif
#endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
@@ -191,15 +276,17 @@
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
#define WHEN( desc ) SECTION( std::string(" When: ") + desc )
#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
#define THEN( desc ) SECTION( std::string(" Then: ") + desc )
#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc )
#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
using Catch::Detail::Approx;
#else
#else // CATCH_CONFIG_DISABLE
//////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL
@@ -235,30 +322,56 @@ using Catch::Detail::Approx;
#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_INFO( msg ) (void)(0)
#define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( msg ) (void)(0)
#define CATCH_INFO( msg ) (void)(0)
#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
#define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( msg ) (void)(0)
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
#define CATCH_METHOD_AS_TEST_CASE( method, ... )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define CATCH_SECTION( ... )
#define CATCH_DYNAMIC_SECTION( ... )
#define CATCH_FAIL( ... ) (void)(0)
#define CATCH_FAIL_CHECK( ... ) (void)(0)
#define CATCH_SUCCEED( ... ) (void)(0)
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#else
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#endif
// "BDD-style" convenience wrappers
#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_GIVEN( desc )
#define CATCH_AND_GIVEN( desc )
#define CATCH_WHEN( desc )
#define CATCH_AND_WHEN( desc )
#define CATCH_THEN( desc )
#define CATCH_AND_THEN( desc )
#define CATCH_STATIC_REQUIRE( ... ) (void)(0)
#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else
@@ -295,6 +408,7 @@ using Catch::Detail::Approx;
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) (void)(0)
#define UNSCOPED_INFO( msg ) (void)(0)
#define WARN( msg ) (void)(0)
#define CAPTURE( msg ) (void)(0)
@@ -303,11 +417,35 @@ using Catch::Detail::Approx;
#define METHOD_AS_TEST_CASE( method, ... )
#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define SECTION( ... )
#define DYNAMIC_SECTION( ... )
#define FAIL( ... ) (void)(0)
#define FAIL_CHECK( ... ) (void)(0)
#define SUCCEED( ... ) (void)(0)
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#else
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#endif
#define STATIC_REQUIRE( ... ) (void)(0)
#define STATIC_REQUIRE_FALSE( ... ) (void)(0)
#endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
@@ -317,6 +455,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 GIVEN( desc )
#define AND_GIVEN( desc )
#define WHEN( desc )
#define AND_WHEN( desc )
#define THEN( desc )
@@ -327,6 +466,8 @@ using Catch::Detail::Approx;
#endif
#endif // ! CATCH_CONFIG_IMPL_ONLY
#include "internal/catch_reenable_warnings.h"
#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED

View File

@@ -1,5 +1,11 @@
// v1.0-develop.2
// See https://github.com/philsquared/Clara
// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.5
#ifndef CATCH_CLARA_HPP_INCLUDED
#define CATCH_CLARA_HPP_INCLUDED
@@ -12,14 +18,24 @@
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
#endif
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#include <optional>
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
#endif
#endif
#endif
// ----------- #included from clara_textflow.hpp -----------
// TextFlowCpp
//
// A single-header library for wrapping and laying out basic text, by Phil Nash
//
// This work is licensed under the BSD 2-Clause license.
// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This project is hosted at https://github.com/philsquared/textflowcpp
@@ -36,317 +52,329 @@
#endif
namespace Catch { namespace clara { namespace TextFlow {
namespace Catch {
namespace clara {
namespace TextFlow {
inline auto isWhitespace( char c ) -> bool {
static std::string chars = " \t\n\r";
return chars.find( c ) != std::string::npos;
}
inline auto isBreakableBefore( char c ) -> bool {
static std::string chars = "[({<|";
return chars.find( c ) != std::string::npos;
}
inline auto isBreakableAfter( char c ) -> bool {
static std::string chars = "])}>.,:;*+-=&/\\";
return chars.find( c ) != std::string::npos;
}
inline auto isWhitespace(char c) -> bool {
static std::string chars = " \t\n\r";
return chars.find(c) != std::string::npos;
}
inline auto isBreakableBefore(char c) -> bool {
static std::string chars = "[({<|";
return chars.find(c) != std::string::npos;
}
inline auto isBreakableAfter(char c) -> bool {
static std::string chars = "])}>.,:;*+-=&/\\";
return chars.find(c) != std::string::npos;
}
class Columns;
class Columns;
class Column {
std::vector<std::string> m_strings;
size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
size_t m_indent = 0;
size_t m_initialIndent = std::string::npos;
class Column {
std::vector<std::string> m_strings;
size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
size_t m_indent = 0;
size_t m_initialIndent = std::string::npos;
public:
class iterator {
friend Column;
public:
class iterator {
friend Column;
Column const& m_column;
size_t m_stringIndex = 0;
size_t m_pos = 0;
Column const& m_column;
size_t m_stringIndex = 0;
size_t m_pos = 0;
size_t m_len = 0;
size_t m_end = 0;
bool m_suffix = false;
size_t m_len = 0;
size_t m_end = 0;
bool m_suffix = false;
iterator( Column const& column, size_t stringIndex )
: m_column( column ),
m_stringIndex( stringIndex )
{}
iterator(Column const& column, size_t stringIndex)
: m_column(column),
m_stringIndex(stringIndex) {}
auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
auto isBoundary( size_t at ) const -> bool {
assert( at > 0 );
assert( at <= line().size() );
auto isBoundary(size_t at) const -> bool {
assert(at > 0);
assert(at <= line().size());
return at == line().size() ||
( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
isBreakableBefore( line()[at] ) ||
isBreakableAfter( line()[at-1] );
}
return at == line().size() ||
(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
isBreakableBefore(line()[at]) ||
isBreakableAfter(line()[at - 1]);
}
void calcLength() {
assert( m_stringIndex < m_column.m_strings.size() );
void calcLength() {
assert(m_stringIndex < m_column.m_strings.size());
m_suffix = false;
auto width = m_column.m_width-indent();
m_end = m_pos;
while( m_end < line().size() && line()[m_end] != '\n' )
++m_end;
m_suffix = false;
auto width = m_column.m_width - indent();
m_end = m_pos;
if (line()[m_pos] == '\n') {
++m_end;
}
while (m_end < line().size() && line()[m_end] != '\n')
++m_end;
if( m_end < m_pos + width ) {
m_len = m_end - m_pos;
}
else {
size_t len = width;
while (len > 0 && !isBoundary(m_pos + len))
--len;
while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
--len;
if (m_end < m_pos + width) {
m_len = m_end - m_pos;
} else {
size_t len = width;
while (len > 0 && !isBoundary(m_pos + len))
--len;
while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
--len;
if (len > 0) {
m_len = len;
} else {
m_suffix = true;
m_len = width - 1;
}
}
}
if (len > 0) {
m_len = len;
} else {
m_suffix = true;
m_len = width - 1;
}
}
}
auto indent() const -> size_t {
auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
return initial == std::string::npos ? m_column.m_indent : initial;
}
auto indent() const -> size_t {
auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
return initial == std::string::npos ? m_column.m_indent : initial;
}
auto addIndentAndSuffix(std::string const &plain) const -> std::string {
return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain);
}
auto addIndentAndSuffix(std::string const &plain) const -> std::string {
return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
}
public:
explicit iterator( Column const& column ) : m_column( column ) {
assert( m_column.m_width > m_column.m_indent );
assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
calcLength();
if( m_len == 0 )
m_stringIndex++; // Empty string
}
public:
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using pointer = value_type * ;
using reference = value_type & ;
using iterator_category = std::forward_iterator_tag;
auto operator *() const -> std::string {
assert( m_stringIndex < m_column.m_strings.size() );
assert( m_pos <= m_end );
if( m_pos + m_column.m_width < m_end )
return addIndentAndSuffix(line().substr(m_pos, m_len));
else
return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
}
explicit iterator(Column const& column) : m_column(column) {
assert(m_column.m_width > m_column.m_indent);
assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
calcLength();
if (m_len == 0)
m_stringIndex++; // Empty string
}
auto operator ++() -> iterator& {
m_pos += m_len;
if( m_pos < line().size() && line()[m_pos] == '\n' )
m_pos += 1;
else
while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
++m_pos;
auto operator *() const -> std::string {
assert(m_stringIndex < m_column.m_strings.size());
assert(m_pos <= m_end);
return addIndentAndSuffix(line().substr(m_pos, m_len));
}
if( m_pos == line().size() ) {
m_pos = 0;
++m_stringIndex;
}
if( m_stringIndex < m_column.m_strings.size() )
calcLength();
return *this;
}
auto operator ++(int) -> iterator {
iterator prev( *this );
operator++();
return prev;
}
auto operator ++() -> iterator& {
m_pos += m_len;
if (m_pos < line().size() && line()[m_pos] == '\n')
m_pos += 1;
else
while (m_pos < line().size() && isWhitespace(line()[m_pos]))
++m_pos;
auto operator ==( iterator const& other ) const -> bool {
return
m_pos == other.m_pos &&
m_stringIndex == other.m_stringIndex &&
&m_column == &other.m_column;
}
auto operator !=( iterator const& other ) const -> bool {
return !operator==( other );
}
};
using const_iterator = iterator;
if (m_pos == line().size()) {
m_pos = 0;
++m_stringIndex;
}
if (m_stringIndex < m_column.m_strings.size())
calcLength();
return *this;
}
auto operator ++(int) -> iterator {
iterator prev(*this);
operator++();
return prev;
}
explicit Column( std::string const& text ) { m_strings.push_back( text ); }
auto operator ==(iterator const& other) const -> bool {
return
m_pos == other.m_pos &&
m_stringIndex == other.m_stringIndex &&
&m_column == &other.m_column;
}
auto operator !=(iterator const& other) const -> bool {
return !operator==(other);
}
};
using const_iterator = iterator;
auto width( size_t newWidth ) -> Column& {
assert( newWidth > 0 );
m_width = newWidth;
return *this;
}
auto indent( size_t newIndent ) -> Column& {
m_indent = newIndent;
return *this;
}
auto initialIndent( size_t newIndent ) -> Column& {
m_initialIndent = newIndent;
return *this;
}
explicit Column(std::string const& text) { m_strings.push_back(text); }
auto width() const -> size_t { return m_width; }
auto begin() const -> iterator { return iterator( *this ); }
auto end() const -> iterator { return { *this, m_strings.size() }; }
auto width(size_t newWidth) -> Column& {
assert(newWidth > 0);
m_width = newWidth;
return *this;
}
auto indent(size_t newIndent) -> Column& {
m_indent = newIndent;
return *this;
}
auto initialIndent(size_t newIndent) -> Column& {
m_initialIndent = newIndent;
return *this;
}
inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) {
bool first = true;
for( auto line : col ) {
if( first )
first = false;
else
os << "\n";
os << line;
}
return os;
}
auto width() const -> size_t { return m_width; }
auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return { *this, m_strings.size() }; }
auto operator + ( Column const& other ) -> Columns;
inline friend std::ostream& operator << (std::ostream& os, Column const& col) {
bool first = true;
for (auto line : col) {
if (first)
first = false;
else
os << "\n";
os << line;
}
return os;
}
auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
auto operator + (Column const& other)->Columns;
class Spacer : public Column {
auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
public:
explicit Spacer( size_t spaceWidth ) : Column( "" ) {
width( spaceWidth );
}
};
class Spacer : public Column {
class Columns {
std::vector<Column> m_columns;
public:
explicit Spacer(size_t spaceWidth) : Column("") {
width(spaceWidth);
}
};
public:
class Columns {
std::vector<Column> m_columns;
class iterator {
friend Columns;
struct EndTag {};
public:
std::vector<Column> const& m_columns;
std::vector<Column::iterator> m_iterators;
size_t m_activeIterators;
class iterator {
friend Columns;
struct EndTag {};
iterator( Columns const& columns, EndTag )
: m_columns( columns.m_columns ),
m_activeIterators( 0 )
{
m_iterators.reserve( m_columns.size() );
std::vector<Column> const& m_columns;
std::vector<Column::iterator> m_iterators;
size_t m_activeIterators;
for( auto const& col : m_columns )
m_iterators.push_back( col.end() );
}
iterator(Columns const& columns, EndTag)
: m_columns(columns.m_columns),
m_activeIterators(0) {
m_iterators.reserve(m_columns.size());
public:
explicit iterator( Columns const& columns )
: m_columns( columns.m_columns ),
m_activeIterators( m_columns.size() )
{
m_iterators.reserve( m_columns.size() );
for (auto const& col : m_columns)
m_iterators.push_back(col.end());
}
for( auto const& col : m_columns )
m_iterators.push_back( col.begin() );
}
public:
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using pointer = value_type * ;
using reference = value_type & ;
using iterator_category = std::forward_iterator_tag;
auto operator ==( iterator const& other ) const -> bool {
return m_iterators == other.m_iterators;
}
auto operator !=( iterator const& other ) const -> bool {
return m_iterators != other.m_iterators;
}
auto operator *() const -> std::string {
std::string row, padding;
explicit iterator(Columns const& columns)
: m_columns(columns.m_columns),
m_activeIterators(m_columns.size()) {
m_iterators.reserve(m_columns.size());
for( size_t i = 0; i < m_columns.size(); ++i ) {
auto width = m_columns[i].width();
if( m_iterators[i] != m_columns[i].end() ) {
std::string col = *m_iterators[i];
row += padding + col;
if( col.size() < width )
padding = std::string( width - col.size(), ' ' );
else
padding = "";
}
else {
padding += std::string( width, ' ' );
}
}
return row;
}
auto operator ++() -> iterator& {
for( size_t i = 0; i < m_columns.size(); ++i ) {
if (m_iterators[i] != m_columns[i].end())
++m_iterators[i];
}
return *this;
}
auto operator ++(int) -> iterator {
iterator prev( *this );
operator++();
return prev;
}
};
using const_iterator = iterator;
for (auto const& col : m_columns)
m_iterators.push_back(col.begin());
}
auto begin() const -> iterator { return iterator( *this ); }
auto end() const -> iterator { return { *this, iterator::EndTag() }; }
auto operator ==(iterator const& other) const -> bool {
return m_iterators == other.m_iterators;
}
auto operator !=(iterator const& other) const -> bool {
return m_iterators != other.m_iterators;
}
auto operator *() const -> std::string {
std::string row, padding;
auto operator += ( Column const& col ) -> Columns& {
m_columns.push_back( col );
return *this;
}
auto operator + ( Column const& col ) -> Columns {
Columns combined = *this;
combined += col;
return combined;
}
for (size_t i = 0; i < m_columns.size(); ++i) {
auto width = m_columns[i].width();
if (m_iterators[i] != m_columns[i].end()) {
std::string col = *m_iterators[i];
row += padding + col;
if (col.size() < width)
padding = std::string(width - col.size(), ' ');
else
padding = "";
} else {
padding += std::string(width, ' ');
}
}
return row;
}
auto operator ++() -> iterator& {
for (size_t i = 0; i < m_columns.size(); ++i) {
if (m_iterators[i] != m_columns[i].end())
++m_iterators[i];
}
return *this;
}
auto operator ++(int) -> iterator {
iterator prev(*this);
operator++();
return prev;
}
};
using const_iterator = iterator;
inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) {
auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return { *this, iterator::EndTag() }; }
bool first = true;
for( auto line : cols ) {
if( first )
first = false;
else
os << "\n";
os << line;
}
return os;
}
auto operator += (Column const& col) -> Columns& {
m_columns.push_back(col);
return *this;
}
auto operator + (Column const& col) -> Columns {
Columns combined = *this;
combined += col;
return combined;
}
auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
inline auto Column::operator + ( Column const& other ) -> Columns {
Columns cols;
cols += *this;
cols += other;
return cols;
}
}}} // namespace Catch::clara::TextFlow
bool first = true;
for (auto line : cols) {
if (first)
first = false;
else
os << "\n";
os << line;
}
return os;
}
auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
inline auto Column::operator + (Column const& other) -> Columns {
Columns cols;
cols += *this;
cols += other;
return cols;
}
}
}
}
#endif // CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
// ----------- end of #include from clara_textflow.hpp -----------
// ........... back in clara.hpp
#include <cctype>
#include <string>
#include <memory>
#include <set>
#include <algorithm>
@@ -370,7 +398,7 @@ namespace detail {
template<typename ClassT, typename ReturnT, typename ArgT>
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
static const bool isValid = true;
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
using ReturnType = ReturnT;
};
@@ -383,11 +411,9 @@ namespace detail {
std::vector<std::string> m_args;
public:
Args( int argc, char *argv[] ) {
m_exeName = argv[0];
for( int i = 1; i < argc; ++i )
m_args.push_back( argv[i] );
}
Args( int argc, char const* const* argv )
: m_exeName(argv[0]),
m_args(argv + 1, argv + argc) {}
Args( std::initializer_list<std::string> args )
: m_exeName( *args.begin() ),
@@ -535,7 +561,7 @@ namespace detail {
return *this;
}
~ResultValueBase() {
~ResultValueBase() override {
if( m_type == Ok )
m_value.~T();
}
@@ -573,16 +599,14 @@ namespace detail {
auto errorMessage() const -> std::string { return m_errorMessage; }
protected:
virtual void enforceOk() const {
// !TBD: If no exceptions, std::terminate here or something
switch( m_type ) {
case ResultBase::LogicError:
throw std::logic_error( m_errorMessage );
case ResultBase::RuntimeError:
throw std::runtime_error( m_errorMessage );
case ResultBase::Ok:
break;
}
void enforceOk() const override {
// Errors shouldn't reach this point, but if they do
// the actual error message will be in m_errorMessage
assert( m_type != ResultBase::LogicError );
assert( m_type != ResultBase::RuntimeError );
if( m_type != ResultBase::Ok )
std::abort();
}
std::string m_errorMessage; // Only populated if resultType is an error
@@ -643,7 +667,7 @@ namespace detail {
}
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
std::string srcLC = source;
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
target = true;
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
@@ -652,47 +676,43 @@ namespace detail {
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
return ParserResult::ok( ParseResultType::Matched );
}
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
template<typename T>
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
T temp;
auto result = convertInto( source, temp );
if( result )
target = std::move(temp);
return result;
}
#endif // CLARA_CONFIG_OPTIONAL_TYPE
struct BoundRefBase {
BoundRefBase() = default;
BoundRefBase( BoundRefBase const & ) = delete;
BoundRefBase( BoundRefBase && ) = delete;
BoundRefBase &operator=( BoundRefBase const & ) = delete;
BoundRefBase &operator=( BoundRefBase && ) = delete;
struct NonCopyable {
NonCopyable() = default;
NonCopyable( NonCopyable const & ) = delete;
NonCopyable( NonCopyable && ) = delete;
NonCopyable &operator=( NonCopyable const & ) = delete;
NonCopyable &operator=( NonCopyable && ) = delete;
};
virtual ~BoundRefBase() = default;
virtual auto isFlag() const -> bool = 0;
struct BoundRef : NonCopyable {
virtual ~BoundRef() = default;
virtual auto isContainer() const -> bool { return false; }
virtual auto isFlag() const -> bool { return false; }
};
struct BoundValueRefBase : BoundRef {
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
};
struct BoundFlagRefBase : BoundRef {
virtual auto setFlag( bool flag ) -> ParserResult = 0;
};
struct BoundValueRefBase : BoundRefBase {
auto isFlag() const -> bool override { return false; }
auto setFlag( bool ) -> ParserResult override {
return ParserResult::logicError( "Flags can only be set on boolean fields" );
}
};
struct BoundFlagRefBase : BoundRefBase {
auto isFlag() const -> bool override { return true; }
auto setValue( std::string const &arg ) -> ParserResult override {
bool flag;
auto result = convertInto( arg, flag );
if( result )
setFlag( flag );
return result;
}
virtual auto isFlag() const -> bool { return true; }
};
template<typename T>
struct BoundRef : BoundValueRefBase {
struct BoundValueRef : BoundValueRefBase {
T &m_ref;
explicit BoundRef( T &ref ) : m_ref( ref ) {}
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
auto setValue( std::string const &arg ) -> ParserResult override {
return convertInto( arg, m_ref );
@@ -700,10 +720,10 @@ namespace detail {
};
template<typename T>
struct BoundRef<std::vector<T>> : BoundValueRefBase {
struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
std::vector<T> &m_ref;
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
auto isContainer() const -> bool override { return true; }
@@ -748,12 +768,12 @@ namespace detail {
template<typename ArgType, typename L>
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
ArgType temp;
ArgType temp{};
auto result = convertInto( arg, temp );
return !result
? result
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
};
}
template<typename L>
@@ -803,6 +823,9 @@ namespace detail {
public:
template<typename T>
auto operator|( T const &other ) const -> Parser;
template<typename T>
auto operator+( T const &other ) const -> Parser;
};
// Common code and state for Args and Opts
@@ -810,16 +833,16 @@ namespace detail {
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
protected:
Optionality m_optionality = Optionality::Optional;
std::shared_ptr<BoundRefBase> m_ref;
std::shared_ptr<BoundRef> m_ref;
std::string m_hint;
std::string m_description;
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
public:
template<typename T>
ParserRefImpl( T &ref, std::string const &hint )
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
m_hint( hint )
{}
@@ -860,10 +883,10 @@ namespace detail {
class ExeName : public ComposableParserImpl<ExeName> {
std::shared_ptr<std::string> m_name;
std::shared_ptr<BoundRefBase> m_ref;
std::shared_ptr<BoundValueRefBase> m_ref;
template<typename LambdaT>
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
}
@@ -871,7 +894,7 @@ namespace detail {
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
explicit ExeName( std::string &ref ) : ExeName() {
m_ref = std::make_shared<BoundRef<std::string>>( ref );
m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
}
template<typename LambdaT>
@@ -914,7 +937,10 @@ namespace detail {
if( token.type != TokenType::Argument )
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
auto result = m_ref->setValue( remainingTokens->token );
assert( !m_ref->isFlag() );
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
auto result = valueRef->setValue( remainingTokens->token );
if( !result )
return InternalParseResult( result );
else
@@ -988,19 +1014,21 @@ namespace detail {
auto const &token = *remainingTokens;
if( isMatch(token.token ) ) {
if( m_ref->isFlag() ) {
auto result = m_ref->setFlag( true );
auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
auto result = flagRef->setFlag( true );
if( !result )
return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll )
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
} else {
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
++remainingTokens;
if( !remainingTokens )
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto const &argToken = *remainingTokens;
if( argToken.type != TokenType::Argument )
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto result = m_ref->setValue( argToken.token );
auto result = valueRef->setValue( argToken.token );
if( !result )
return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll )
@@ -1077,6 +1105,12 @@ namespace detail {
return Parser( *this ) |= other;
}
// Forward deprecated interface with '+' instead of '|'
template<typename T>
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
template<typename T>
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
auto getHelpColumns() const -> std::vector<HelpColumns> {
std::vector<HelpColumns> cols;
for (auto const &o : m_options) {
@@ -1116,6 +1150,8 @@ namespace detail {
for( auto const &cols : rows )
optWidth = (std::max)(optWidth, cols.left.size() + 2);
optWidth = (std::min)(optWidth, consoleWidth/2);
for( auto const &cols : rows ) {
auto row =
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +

View File

@@ -7,6 +7,7 @@
*/
#include "catch_approx.h"
#include "catch_enforce.h"
#include <cmath>
#include <limits>
@@ -35,10 +36,17 @@ namespace Detail {
return Approx( 0 );
}
Approx Approx::operator-() const {
auto temp(*this);
temp.m_value = -temp.m_value;
return temp;
}
std::string Approx::toString() const {
std::ostringstream oss;
oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
return oss.str();
ReusableStringStream rss;
rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
return rss.str();
}
bool Approx::equalityComparisonImpl(const double other) const {
@@ -47,8 +55,31 @@ namespace Detail {
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
}
void Approx::setMargin(double newMargin) {
CATCH_ENFORCE(newMargin >= 0,
"Invalid Approx::margin: " << newMargin << '.'
<< " Approx::Margin has to be non-negative.");
m_margin = newMargin;
}
void Approx::setEpsilon(double newEpsilon) {
CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
"Invalid Approx::epsilon: " << newEpsilon << '.'
<< " Approx::epsilon has to be in [0, 1]");
m_epsilon = newEpsilon;
}
} // end namespace Detail
namespace literals {
Detail::Approx operator "" _a(long double val) {
return Detail::Approx(val);
}
Detail::Approx operator "" _a(unsigned long long val) {
return Detail::Approx(val);
}
} // end namespace literals
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
return value.toString();
}

View File

@@ -8,7 +8,6 @@
#ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
#include "catch_enforce.h"
#include "catch_tostring.h"
#include <type_traits>
@@ -19,18 +18,26 @@ namespace Detail {
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:
explicit Approx ( double value );
static Approx custom();
Approx operator-() const;
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx operator()( T const& value ) {
Approx approx( static_cast<double>(value) );
approx.epsilon( m_epsilon );
approx.margin( m_margin );
approx.scale( m_scale );
approx.m_epsilon = m_epsilon;
approx.m_margin = m_margin;
approx.m_scale = m_scale;
return approx;
}
@@ -83,20 +90,14 @@ namespace Detail {
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& epsilon( T const& newEpsilon ) {
double epsilonAsDouble = static_cast<double>(newEpsilon);
CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0,
"Invalid Approx::epsilon: " << epsilonAsDouble
<< ", Approx::epsilon has to be between 0 and 1");
m_epsilon = epsilonAsDouble;
setEpsilon(epsilonAsDouble);
return *this;
}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& margin( T const& newMargin ) {
double marginAsDouble = static_cast<double>(newMargin);
CATCH_ENFORCE(marginAsDouble >= 0,
"Invalid Approx::margin: " << marginAsDouble
<< ", Approx::Margin has to be non-negative.");
m_margin = marginAsDouble;
setMargin(marginAsDouble);
return *this;
}
@@ -114,7 +115,12 @@ namespace Detail {
double m_scale;
double m_value;
};
}
} // end namespace Detail
namespace literals {
Detail::Approx operator "" _a(long double val);
Detail::Approx operator "" _a(unsigned long long val);
} // end namespace literals
template<>
struct StringMaker<Catch::Detail::Approx> {

View File

@@ -8,21 +8,21 @@
#include "catch_assertionhandler.h"
#include "catch_assertionresult.h"
#include "catch_interfaces_capture.h"
#include "catch_interfaces_runner.h"
#include "catch_interfaces_config.h"
#include "catch_context.h"
#include "catch_debugger.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_capture_matchers.h"
#include <cassert>
#include "catch_run_context.h"
namespace Catch {
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
expr.streamReconstructedExpression( os );
return os;
namespace {
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
expr.streamReconstructedExpression( os );
return os;
}
}
LazyExpression::LazyExpression( bool isNegated )
@@ -52,95 +52,69 @@ namespace Catch {
}
AssertionHandler::AssertionHandler
( StringRef macroName,
( StringRef const& macroName,
SourceLineInfo const& lineInfo,
StringRef capturedExpression,
ResultDisposition::Flags resultDisposition )
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }
{
getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo );
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
m_resultCapture( getResultCapture() )
{}
void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
}
AssertionHandler::~AssertionHandler() {
if ( m_inExceptionGuard ) {
handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" );
getCurrentContext().getResultCapture()->exceptionEarlyReported();
}
}
void AssertionHandler::handle( ITransientExpression const& expr ) {
bool negated = isFalseTest( m_assertionInfo.resultDisposition );
bool result = expr.getResult() != negated;
handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated );
}
void AssertionHandler::handle( ResultWas::OfType resultType ) {
handle( resultType, nullptr, false );
}
void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) {
AssertionResultData data( resultType, LazyExpression( false ) );
data.message = message;
handle( data, nullptr );
}
void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) {
AssertionResultData data( resultType, LazyExpression( negated ) );
handle( data, expr );
}
void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) {
getResultCapture().assertionRun();
AssertionResult assertionResult{ m_assertionInfo, resultData };
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
getResultCapture().assertionEnded( assertionResult );
if( !assertionResult.isOk() ) {
m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak();
m_shouldThrow =
getCurrentContext().getRunner()->aborting() ||
(m_assertionInfo.resultDisposition & ResultDisposition::Normal);
}
void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
}
auto AssertionHandler::allowThrows() const -> bool {
return getCurrentContext().getConfig()->allowThrows();
}
auto AssertionHandler::shouldDebugBreak() const -> bool {
return m_shouldDebugBreak;
}
void AssertionHandler::reactWithDebugBreak() const {
if (m_shouldDebugBreak) {
///////////////////////////////////////////////////////////////////
// To inspect the state during test, you need to go one level up the callstack
// To go back to the test and change execution, jump over the reactWithoutDebugBreak() call
///////////////////////////////////////////////////////////////////
void AssertionHandler::complete() {
setCompleted();
if( m_reaction.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 go back to the test and change execution, jump over the throw, next)
CATCH_BREAK_INTO_DEBUGGER();
}
reactWithoutDebugBreak();
}
void AssertionHandler::reactWithoutDebugBreak() const {
if( m_shouldThrow )
if (m_reaction.shouldThrow) {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
throw Catch::TestFailureException();
#else
CATCH_ERROR( "Test failure requires aborting test!" );
#endif
}
}
void AssertionHandler::setCompleted() {
m_completed = true;
}
void AssertionHandler::useActiveException() {
handle( ResultWas::ThrewException, Catch::translateActiveException() );
void AssertionHandler::handleUnexpectedInflightException() {
m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
}
void AssertionHandler::setExceptionGuard() {
assert( m_inExceptionGuard == false );
m_inExceptionGuard = true;
void AssertionHandler::handleExceptionThrownAsExpected() {
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
}
void AssertionHandler::unsetExceptionGuard() {
assert( m_inExceptionGuard == true );
m_inExceptionGuard = false;
void AssertionHandler::handleExceptionNotThrownAsExpected() {
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
}
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
// 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 );
}

View File

@@ -8,17 +8,21 @@
#ifndef TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED
#define TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED
#include "catch_decomposer.h"
#include "catch_assertioninfo.h"
#include "catch_decomposer.h"
#include "catch_interfaces_capture.h"
namespace Catch {
struct TestFailureException{};
struct AssertionResultData;
struct IResultCapture;
class RunContext;
class LazyExpression {
friend class AssertionHandler;
friend struct AssertionStats;
friend class RunContext;
ITransientExpression const* m_transientExpression = nullptr;
bool m_isNegated;
@@ -32,41 +36,52 @@ namespace Catch {
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
};
struct AssertionReaction {
bool shouldDebugBreak = false;
bool shouldThrow = false;
};
class AssertionHandler {
AssertionInfo m_assertionInfo;
bool m_shouldDebugBreak = false;
bool m_shouldThrow = false;
bool m_inExceptionGuard = false;
AssertionReaction m_reaction;
bool m_completed = false;
IResultCapture& m_resultCapture;
public:
AssertionHandler
( StringRef macroName,
( StringRef const& macroName,
SourceLineInfo const& lineInfo,
StringRef capturedExpression,
ResultDisposition::Flags resultDisposition );
~AssertionHandler();
~AssertionHandler() {
if ( !m_completed ) {
m_resultCapture.handleIncomplete( m_assertionInfo );
}
}
void handle( ITransientExpression const& expr );
template<typename T>
void handle( ExprLhs<T> const& expr ) {
handle( expr.makeUnaryExpr() );
void handleExpr( ExprLhs<T> const& expr ) {
handleExpr( expr.makeUnaryExpr() );
}
void handle( ResultWas::OfType resultType );
void handle( ResultWas::OfType resultType, StringRef const& message );
void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated );
void handle( AssertionResultData const& resultData, ITransientExpression const* expr );
void handleExpr( 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;
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

View File

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

View File

@@ -47,7 +47,7 @@ namespace Catch {
std::string getExpandedExpression() const;
std::string getMessage() const;
SourceLineInfo getSourceInfo() const;
std::string getTestMacroName() const;
StringRef getTestMacroName() const;
//protected:
AssertionInfo m_info;

View File

@@ -9,9 +9,9 @@
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
#include "catch_assertionhandler.h"
#include "catch_message.h"
#include "catch_interfaces_capture.h"
#include "catch_debugger.h"
#include "catch_message.h"
#include "catch_stringref.h"
#if !defined(CATCH_CONFIG_DISABLE)
@@ -21,49 +21,34 @@
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
#endif
#if defined(CATCH_CONFIG_FAST_COMPILE)
///////////////////////////////////////////////////////////////////////////////
// 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();
#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
///////////////////////////////////////////////////////////////////////////////
// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
// macros.
// This can potentially cause false negative, if the test code catches
// the exception before it propagates back up to the runner.
#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard();
#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard();
#define INTERNAL_CATCH_TRY
#define INTERNAL_CATCH_CATCH( capturer )
#else // CATCH_CONFIG_FAST_COMPILE
///////////////////////////////////////////////////////////////////////////////
// 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(); }
#define INTERNAL_CATCH_TRY try
#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
#endif
#define INTERNAL_CATCH_REACT( handler ) handler.complete();
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
INTERNAL_CATCH_TRY { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::isTrue( false && static_cast<bool>( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
} 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 &&.
///////////////////////////////////////////////////////////////////////////////
@@ -79,84 +64,93 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
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 { \
static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
} \
catch( ... ) { \
catchAssertionHandler.useActiveException(); \
catchAssertionHandler.handleUnexpectedInflightException(); \
} \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
} while( false )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
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() ) \
try { \
static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \
catch( ... ) { \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
catchAssertionHandler.handleExceptionThrownAsExpected(); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
} while( false )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
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() ) \
try { \
static_cast<void>(expr); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \
catch( exceptionType const& ) { \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
catchAssertionHandler.handleExceptionThrownAsExpected(); \
} \
catch( ... ) { \
catchAssertionHandler.useActiveException(); \
catchAssertionHandler.handleUnexpectedInflightException(); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
} while( false )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
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 ) \
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 );
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
Catch::getResultCapture().emplaceUnscopedMessage( 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
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
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() ) \
try { \
static_cast<void>(__VA_ARGS__); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \
catch( ... ) { \
handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
catchAssertionHandler.handleThrowingCallSkipped(); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
} while( false )
#endif // CATCH_CONFIG_DISABLE

View File

@@ -13,12 +13,12 @@ namespace Catch {
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
// This is the general overload that takes a any string matcher
// There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers
// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
// the Equals matcher (so the header does not mention matchers)
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) {
std::string exceptionMessage = Catch::translateActiveException();
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
handler.handle( expr );
handler.handleExpr( expr );
}
} // namespace Catch

View File

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

View File

@@ -10,6 +10,9 @@
#include "catch_string_manip.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_interfaces_reporter.h"
#include <fstream>
#include <ctime>
@@ -20,9 +23,19 @@ namespace Catch {
using namespace clara;
auto const setWarning = [&]( std::string const& warning ) {
if( warning != "NoAssertions" )
auto warningSet = [&]() {
if( warning == "NoAssertions" )
return WarnAbout::NoAssertions;
if ( warning == "NoTests" )
return WarnAbout::NoTests;
return WarnAbout::Nothing;
}();
if (warningSet == WarnAbout::Nothing)
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
return ParserResult::ok( ParseResultType::Matched );
};
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
@@ -95,6 +108,18 @@ namespace Catch {
return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setReporter = [&]( std::string const& reporter ) {
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
auto lcReporter = toLower( reporter );
auto result = factories.find( lcReporter );
if( factories.end() != result )
config.reporterName = lcReporter;
else
return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );
return ParserResult::ok( ParseResultType::Matched );
};
auto cli
= ExeName( config.processName )
@@ -120,7 +145,7 @@ namespace Catch {
| Opt( config.outputFilename, "filename" )
["-o"]["--out"]
( "output filename" )
| Opt( config.reporterNames, "name" )
| Opt( setReporter, "name" )
["-r"]["--reporter"]
( "reporter to use (defaults to console)" )
| Opt( config.name, "name" )

View File

@@ -15,10 +15,6 @@
namespace Catch {
SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept
: file( _file ),
line( _line )
{}
bool SourceLineInfo::empty() const noexcept {
return file[0] == '\0';
}
@@ -26,7 +22,9 @@ namespace Catch {
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
}
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
// 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));
}
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
@@ -38,10 +36,6 @@ namespace Catch {
return os;
}
bool isTrue( bool value ){ return value; }
bool alwaysTrue() { return true; }
bool alwaysFalse() { return false; }
std::string StreamEndStop::operator+() const {
return std::string();
}

View File

@@ -22,6 +22,10 @@
#include <string>
#include <cstdint>
// We need a dummy global operator<< so we can bring it into Catch namespace later
struct Catch_global_namespace_dummy {};
std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
namespace Catch {
struct CaseSensitive { enum Choice {
@@ -43,12 +47,15 @@ namespace Catch {
struct SourceLineInfo {
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 && ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo& operator = ( SourceLineInfo && ) = default;
SourceLineInfo( SourceLineInfo const& other ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo( SourceLineInfo&& ) noexcept = default;
SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
bool empty() const noexcept;
bool operator == ( SourceLineInfo const& other ) const noexcept;
@@ -60,10 +67,10 @@ namespace Catch {
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals
bool isTrue( bool value );
bool alwaysTrue();
bool alwaysFalse();
// Bring in operator<< from global namespace into Catch namespace
// This is necessary because the overload of operator<< above makes
// lookup stop at namespace Catch
using ::operator<<;
// Use this in variadic streaming macros to allow
// >> +StreamEndStop

View File

@@ -14,6 +14,7 @@
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH 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
// in configuration.md, too
@@ -24,13 +25,22 @@
// Many features, at point of detection, define an _INTERNAL_ macro, so they
// can be combined, en-mass, with the _NO_ forms later.
#include "catch_platform.h"
#ifdef __cplusplus
# if __cplusplus >= 201402L
# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
# define CATCH_CPP14_OR_GREATER
# 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
#ifdef __clang__
@@ -48,17 +58,31 @@
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
_Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
_Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
_Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic pop" )
#endif // __clang__
////////////////////////////////////////////////////////////////////////////////
// Assume that non-Windows platforms support posix signals by default
#if !defined(CATCH_PLATFORM_WINDOWS)
#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
#endif
////////////////////////////////////////////////////////////////////////////////
// We know some environments not to support full POSIX signals
#if defined(__CYGWIN__) || defined(__QNX__)
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# endif
#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
#endif
#ifdef __OS400__
@@ -66,6 +90,24 @@
# define CATCH_CONFIG_COLOUR_NONE
#endif
////////////////////////////////////////////////////////////////////////////////
// Android somehow still does not support std::to_string
#if defined(__ANDROID__)
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
#endif
////////////////////////////////////////////////////////////////////////////////
// Not all Windows environments support SEH properly
#if defined(__MINGW32__)
# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
#endif
////////////////////////////////////////////////////////////////////////////////
// PS4
#if defined(__ORBIS__)
# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
#endif
////////////////////////////////////////////////////////////////////////////////
// Cygwin
#ifdef __CYGWIN__
@@ -73,13 +115,25 @@
// Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# 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__
////////////////////////////////////////////////////////////////////////////////
// Visual C++
#ifdef _MSC_VER
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
// Universal Windows platform does not support SEH
// Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@@ -88,8 +142,33 @@
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif
#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
////////////////////////////////////////////////////////////////////////////////
// DJGPP
#ifdef __DJGPP__
# define CATCH_INTERNAL_CONFIG_NO_WCHAR
#endif // __DJGPP__
////////////////////////////////////////////////////////////////////////////////
// Embarcadero C++Build
#if defined(__BORLANDC__)
#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
#endif
////////////////////////////////////////////////////////////////////////////////
// Use of __COUNTER__ is suppressed during code analysis in
@@ -101,16 +180,93 @@
#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 optional is available and usable
#if defined(__has_include)
# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
#endif // __has_include
////////////////////////////////////////////////////////////////////////////////
// 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)
# else
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
# endif // defined(__clang__) && (__clang_major__ < 8)
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
#endif // __has_include
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
# define CATCH_CONFIG_WINDOWS_SEH
#endif
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
# define CATCH_CONFIG_POSIX_SIGNALS
#endif
// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
# define CATCH_CONFIG_WCHAR
#endif
#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
# define CATCH_CONFIG_CPP11_TO_STRING
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
# define CATCH_CONFIG_CPP17_OPTIONAL
#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_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
# define CATCH_CONFIG_POLYFILL_ISNAN
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -120,7 +276,28 @@
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_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
#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#endif
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED

View File

@@ -7,7 +7,7 @@
#include "catch_config.hpp"
#include "catch_enforce.h"
#include "catch_stream.h"
#include "catch_stringref.h"
namespace Catch {
@@ -15,12 +15,13 @@ namespace Catch {
: m_data( data ),
m_stream( openStream() )
{
if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() );
TestSpecParser parser(ITagAliasRegistry::get());
if (!data.testsOrTags.empty()) {
m_hasTestFilters = true;
for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags );
m_testSpec = parser.testSpec();
}
m_testSpec = parser.testSpec();
}
std::string const& Config::getFilename() const {
@@ -33,11 +34,13 @@ namespace Catch {
bool Config::listReporters() const { return m_data.listReporters; }
std::string Config::getProcessName() const { return m_data.processName; }
std::string const& Config::getReporterName() const { return m_data.reporterName; }
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
TestSpec const& Config::testSpec() const { return m_testSpec; }
bool Config::hasTestFilters() const { return m_hasTestFilters; }
bool Config::showHelp() const { return m_data.showHelp; }
@@ -46,7 +49,8 @@ namespace Catch {
std::ostream& Config::stream() const { return m_stream->stream(); }
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
@@ -58,16 +62,7 @@ namespace Catch {
Verbosity Config::verbosity() const { return m_data.verbosity; }
IStream const* Config::openStream() {
if( m_data.outputFilename.empty() )
return new CoutStream();
else if( m_data.outputFilename[0] == '%' ) {
if( m_data.outputFilename == "%debug" )
return new DebugOutStream();
else
CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" );
}
else
return new FileStream( m_data.outputFilename );
return Catch::makeStream(m_data.outputFilename);
}
} // end namespace Catch

View File

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

View File

@@ -11,8 +11,8 @@
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wexit-time-destructors"
#endif
#include "catch_console_colour.h"
#include "catch_enforce.h"
#include "catch_errno_guard.h"
@@ -23,6 +23,8 @@
#include "catch_debugger.h"
#include "catch_windows_h_proxy.h"
#include <sstream>
namespace Catch {
namespace {
@@ -67,7 +69,7 @@ namespace {
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
}
virtual void use( Colour::Code _colourCode ) override {
void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -82,8 +84,12 @@ namespace {
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
default:
CATCH_ERROR( "Unknown colour requested" );
}
}
@@ -126,7 +132,7 @@ namespace {
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
public:
virtual void use( Colour::Code _colourCode ) override {
void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@@ -141,8 +147,10 @@ namespace {
case Colour::BrightRed: return setColour( "[1;31m" );
case Colour::BrightGreen: return setColour( "[1;32m" );
case Colour::BrightWhite: return setColour( "[1;37m" );
case Colour::BrightYellow: return setColour( "[1;33m" );
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
}
}
static IColourImpl* instance() {
@@ -152,7 +160,8 @@ namespace {
private:
void setColour( const char* _escapeCode ) {
Catch::cout() << '\033' << _escapeCode;
getCurrentContext().getConfig()->stream()
<< '\033' << _escapeCode;
}
};
@@ -161,7 +170,12 @@ namespace {
#ifdef CATCH_PLATFORM_MAC
!isDebuggerActive() &&
#endif
isatty(STDOUT_FILENO);
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
isatty(STDOUT_FILENO)
#else
false
#endif
;
}
IColourImpl* platformColourInstance() {
ErrnoGuard guard;
@@ -194,7 +208,7 @@ namespace Catch {
namespace Catch {
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour::Colour( Colour&& rhs ) noexcept {
Colour::Colour( Colour&& rhs ) noexcept {
m_moved = rhs.m_moved;
rhs.m_moved = true;
}
@@ -203,7 +217,7 @@ namespace Catch {
rhs.m_moved = true;
return *this;
}
Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) {

View File

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

View File

@@ -13,27 +13,27 @@ namespace Catch {
class Context : public IMutableContext, NonCopyable {
public: // IContext
virtual IResultCapture* getResultCapture() override {
IResultCapture* getResultCapture() override {
return m_resultCapture;
}
virtual IRunner* getRunner() override {
IRunner* getRunner() override {
return m_runner;
}
virtual IConfigPtr getConfig() const override {
IConfigPtr const& getConfig() const override {
return m_config;
}
virtual ~Context() override;
~Context() override;
public: // IMutableContext
virtual void setResultCapture( IResultCapture* resultCapture ) override {
void setResultCapture( IResultCapture* resultCapture ) override {
m_resultCapture = resultCapture;
}
virtual void setRunner( IRunner* runner ) override {
void setRunner( IRunner* runner ) override {
m_runner = runner;
}
virtual void setConfig( IConfigPtr const& config ) override {
void setConfig( IConfigPtr const& config ) override {
m_config = config;
}
@@ -45,21 +45,16 @@ namespace Catch {
IResultCapture* m_resultCapture = nullptr;
};
namespace {
Context* currentContext = nullptr;
}
IMutableContext& getCurrentMutableContext() {
if( !currentContext )
currentContext = new Context();
return *currentContext;
}
IContext& getCurrentContext() {
return getCurrentMutableContext();
IMutableContext *IMutableContext::currentContext = nullptr;
void IMutableContext::createContext()
{
currentContext = new Context();
}
void cleanUpContext() {
delete currentContext;
currentContext = nullptr;
delete IMutableContext::currentContext;
IMutableContext::currentContext = nullptr;
}
IContext::~IContext() = default;
IMutableContext::~IMutableContext() = default;

View File

@@ -15,6 +15,7 @@ namespace Catch {
struct IResultCapture;
struct IRunner;
struct IConfig;
struct IMutableContext;
using IConfigPtr = std::shared_ptr<IConfig const>;
@@ -24,7 +25,7 @@ namespace Catch {
virtual IResultCapture* getResultCapture() = 0;
virtual IRunner* getRunner() = 0;
virtual IConfigPtr getConfig() const = 0;
virtual IConfigPtr const& getConfig() const = 0;
};
struct IMutableContext : IContext
@@ -33,10 +34,26 @@ namespace Catch {
virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
virtual void setRunner( IRunner* runner ) = 0;
virtual void setConfig( IConfigPtr const& config ) = 0;
private:
static IMutableContext *currentContext;
friend IMutableContext& getCurrentMutableContext();
friend void cleanUpContext();
static void createContext();
};
IContext& getCurrentContext();
IMutableContext& getCurrentMutableContext();
inline IMutableContext& getCurrentMutableContext()
{
if( !IMutableContext::currentContext )
IMutableContext::createContext();
return *IMutableContext::currentContext;
}
inline IContext& getCurrentContext()
{
return getCurrentMutableContext();
}
void cleanUpContext();
}

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