Compare commits

...

112 Commits

Author SHA1 Message Date
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
120 changed files with 10476 additions and 6930 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 referece
"""
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 );
}

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**

1
.gitignore vendored
View File

@@ -27,3 +27,4 @@ Build
.vs .vs
cmake-build-* cmake-build-*
benchmark-dir benchmark-dir
.conan/test_package/build

View File

@@ -1,5 +1,4 @@
language: cpp language: cpp
sudo: false
branches: branches:
except: except:
@@ -237,19 +236,59 @@ matrix:
apt: apt:
sources: *all_sources sources: *all_sources
packages: ['valgrind', 'lcov', 'g++-7'] packages: ['valgrind', 'lcov', 'g++-7']
env: COMPILER='g++-7' CPP14=1 VALGRIND=1 env: COMPILER='g++-7' CPP14=1 VALGRIND=1
- os: osx - os: osx
osx_image: xcode9.1 osx_image: xcode9.1
compiler: clang compiler: clang
env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1 env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
# 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
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: install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
- | - |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz" CMAKE_URL="http://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz"
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
export PATH=${DEPS_DIR}/cmake/bin:${PATH} export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
@@ -263,9 +302,9 @@ before_script:
- python scripts/generateSingleHeader.py - python scripts/generateSingleHeader.py
# Use Debug builds for running Valgrind and building examples # Use Debug builds for running Valgrind and building examples
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE} -DCATCH_BUILD_EXTRA_TESTS=${EXTRAS} - 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 # Don't bother with release build for coverage build
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14} - cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14} -DUSE_CPP17=${CPP17}
script: script:

View File

@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON) set(NOT_SUBPROJECT ON)
endif() endif()
project(Catch2 LANGUAGES CXX VERSION 2.4.0) project(Catch2 LANGUAGES CXX VERSION 2.6.0)
# Provide path for scripts # Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")

View File

@@ -5,11 +5,11 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2) [![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/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) [![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/4wRGoJ1WzLjRM7HZ) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/85qcYBOdUKzlnpl5)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD) [![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.4.0/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.6.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released! ## Catch2 is released!

View File

@@ -3,19 +3,15 @@ from conans import ConanFile, CMake
class CatchConan(ConanFile): class CatchConan(ConanFile):
name = "Catch" name = "Catch2"
version = "2.4.0"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared" topics = ("conan", "catch2", "header-only", "unit-test", "tdd", "bdd")
generators = "cmake"
# Only needed until conan 1.5 is released
settings = "compiler", "arch"
exports_sources = "single_include/*", "CMakeLists.txt", "CMake/catch2.pc.in", "LICENSE.txt"
url = "https://github.com/catchorg/Catch2" url = "https://github.com/catchorg/Catch2"
license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt" homepage = url
license = "BSL-1.0"
def build(self): exports = "LICENSE.txt"
pass exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*")
generators = "cmake"
def package(self): def package(self):
cmake = CMake(self) cmake = CMake(self)

View File

@@ -51,12 +51,14 @@ string(REPLACE "\n" ";" output "${output}")
# Parse output # Parse output
foreach(line ${output}) foreach(line ${output})
set(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 # ...and add to script
add_command(add_test add_command(add_test
"${prefix}${test}${suffix}" "${prefix}${test}${suffix}"
${TEST_EXECUTOR} ${TEST_EXECUTOR}
"${TEST_EXECUTABLE}" "${TEST_EXECUTABLE}"
"${test}" "${test_name}"
${extra_args} ${extra_args}
) )
add_command(set_tests_properties add_command(set_tests_properties

View File

@@ -39,6 +39,11 @@
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) # # 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 # # -- 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 #
# #
#==================================================================================================# #==================================================================================================#
cmake_minimum_required(VERSION 2.8.8) cmake_minimum_required(VERSION 2.8.8)
@@ -104,7 +109,7 @@ function(ParseFile SourceFile TestTarget)
# Get test type and fixture if applicable # 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)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}") 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 # Get string parts of test definition
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}") string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
@@ -159,7 +164,7 @@ function(ParseFile SourceFile TestTarget)
break() break()
endif(result) endif(result)
endforeach(label) endforeach(label)
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound}) if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label") PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
else() else()
PrintDebugMessage("Adding test \"${CTestName}\"") PrintDebugMessage("Adding test \"${CTestName}\"")
@@ -168,11 +173,18 @@ function(ParseFile SourceFile TestTarget)
endif() endif()
# Add the test and set its properties # Add the test and set its properties
add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters}) add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} ${TestTarget} ${Name} ${AdditionalCatchParameters})
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" # Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
LABELS "${Labels}") if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
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()
endif() endif()
endforeach() endforeach()
endfunction() endfunction()

View File

@@ -13,6 +13,7 @@ Writing tests:
* [Reporters](reporters.md#top) * [Reporters](reporters.md#top)
* [Event Listeners](event-listeners.md#top) * [Event Listeners](event-listeners.md#top)
* [Data Generators](generators.md#top) * [Data Generators](generators.md#top)
* [Other macros](other-macros.md#top)
Fine tuning: Fine tuning:
* [Supplying your own main()](own-main.md#top) * [Supplying your own main()](own-main.md#top)
@@ -35,3 +36,4 @@ Other:
* [Open Source Projects using Catch](opensource-users.md#top) * [Open Source Projects using Catch](opensource-users.md#top)
* [Contributing](contributing.md#top) * [Contributing](contributing.md#top)
* [Release Notes](release-notes.md#top) * [Release Notes](release-notes.md#top)
* [Deprecations and incoming changes](deprecations.md#top)

View File

@@ -71,7 +71,7 @@ REQUIRE( performComputation() == 2.1_a );
`Approx` is constructed with defaults that should cover most simple cases. `Approx` is constructed with defaults that should cover most simple cases.
For the more complex cases, `Approx` provides 3 customization points: For the more complex cases, `Approx` provides 3 customization points:
* __epsilon__ - epsilon serves to set the percentage by which a result * __epsilon__ - epsilon serves to set the coefficient by which a result
can differ from `Approx`'s value before it is rejected. can differ from `Approx`'s value before it is rejected.
_By default set to `std::numeric_limits<float>::epsilon()*100`._ _By default set to `std::numeric_limits<float>::epsilon()*100`._
* __margin__ - margin serves to set the the absolute value by which * __margin__ - margin serves to set the the absolute value by which

View File

@@ -1,6 +1,12 @@
<a id="top"></a> <a id="top"></a>
# CI and other odd pieces # 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 This page talks about how Catch integrates with Continuous Integration
Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both. Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.

View File

@@ -1,6 +1,12 @@
<a id="top"></a> <a id="top"></a>
# CMake integration # 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 Because we use CMake to build Catch2, we also provide a couple of
integration points for our users. integration points for our users.
@@ -47,7 +53,7 @@ to your CMake module path.
`Catch.cmake` provides function `catch_discover_tests` to get tests from `Catch.cmake` provides function `catch_discover_tests` to get tests from
a target. This function works by running the resulting executable with a target. This function works by running the resulting executable with
`--list-test-names-only` flag, and then parsing the output to find all `--list-test-names-only` flag, and then parsing the output to find all
existing tests. existing tests.
#### Usage #### Usage
```cmake ```cmake
@@ -166,6 +172,16 @@ step will be re-ran when the test files change, letting new tests be
automatically discovered. Defaults to `OFF`. 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 ## CMake project options
Catch2's CMake project also provides some options for other projects Catch2's CMake project also provides some options for other projects
@@ -184,6 +200,27 @@ included in the installation. Defaults to `ON`.
* `BUILD_TESTING` -- When `ON` and the project is not used as a subproject, * `BUILD_TESTING` -- When `ON` and the project is not used as a subproject,
Catch2's test binary will be built. Defaults to `ON`. 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) [Home](Readme.md#top)

View File

@@ -24,7 +24,7 @@
[Usage](#usage)<br> [Usage](#usage)<br>
[Specify the section to run](#specify-the-section-to-run)<br> [Specify the section to run](#specify-the-section-to-run)<br>
[Filenames as tags](#filenames-as-tags)<br> [Filenames as tags](#filenames-as-tags)<br>
[Override output colouring](#use-colour)<br> [Override output colouring](#override-output-colouring)<br>
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available. Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
Click one of the followings links to take you straight to that option - or scroll on to browse the available options. Click one of the followings links to take you straight to that option - or scroll on to browse the available options.

View File

@@ -13,5 +13,6 @@ 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). [issue](https://github.com/philsquared/Catch/issues), or on the [forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
- Bloomberg - Bloomberg
- [Bloomlife](https://bloomlife.com)
- NASA - NASA
- [Inscopix Inc.](https://www.inscopix.com/) - [Inscopix Inc.](https://www.inscopix.com/)

View File

@@ -3,15 +3,19 @@
**Contents**<br> **Contents**<br>
[main()/ implementation](#main-implementation)<br> [main()/ implementation](#main-implementation)<br>
[Reporter / Listener interfaces](#reporter--listener-interfaces)<br>
[Prefixing Catch macros](#prefixing-catch-macros)<br> [Prefixing Catch macros](#prefixing-catch-macros)<br>
[Terminal colour](#terminal-colour)<br> [Terminal colour](#terminal-colour)<br>
[Console width](#console-width)<br> [Console width](#console-width)<br>
[stdout](#stdout)<br> [stdout](#stdout)<br>
[Fallback stringifier](#fallback-stringifier)<br> [Fallback stringifier](#fallback-stringifier)<br>
[Default reporter](#default-reporter)<br> [Default reporter](#default-reporter)<br>
[C++11 toggles](#c11-toggles)<br>
[C++17 toggles](#c17-toggles)<br>
[Other toggles](#other-toggles)<br> [Other toggles](#other-toggles)<br>
[Windows header clutter](#windows-header-clutter)<br> [Windows header clutter](#windows-header-clutter)<br>
[Enabling stringification](#enabling-stringification)<br> [Enabling stringification](#enabling-stringification)<br>
[Disabling exceptions](#disabling-exceptions)<br>
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
@@ -24,7 +28,7 @@ Nonetheless there are still some occasions where finer control is needed. For th
Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*. Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*.
# Reporter / Listener interfaces ## Reporter / Listener interfaces
CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in necessary headers for Reporter/Listener implementation CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in necessary headers for Reporter/Listener implementation
@@ -123,6 +127,8 @@ Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
## C++17 toggles ## C++17 toggles
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception 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 Catch contains basic compiler/standard detection and attempts to use
some C++17 features whenever appropriate. This automatic detection some C++17 features whenever appropriate. This automatic detection
@@ -194,10 +200,12 @@ 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: 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_PAIR_STRINGMAKER // Provide StringMaker specialization for std::pair
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple 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_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_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 ## Disabling exceptions

View File

@@ -1,8 +1,8 @@
<a id="top"></a> <a id="top"></a>
# Contributing to Catch # 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 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. 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. 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 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 ## 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 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 `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, project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion,
@@ -37,20 +37,42 @@ as these are managed by the scripts!__
## Testing your changes ## Testing your changes
Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and Obviously all changes to Catch's code should be tested. If you added new
showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements), functionality, you should add tests covering and showcasing it. Even if you have
you should still test your changes. 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 * Compiling Catch's SelfTest project:
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. $ cd Catch2
* Running the SelfTest binary. There should be no unexpected failures on simple run. $ cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug
* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against $ cmake --build debug-build
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 because code that does not compile is evidently incorrect. Obviously,
be fairly self-explanatory. 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.
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.

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

@@ -1,50 +1,125 @@
<a id="top"></a> <a id="top"></a>
# Data Generators # Data Generators
_Generators are currently considered an experimental feature and their
API can change between versions freely._
Data generators (also known as _data driven/parametrized test cases_) Data generators (also known as _data driven/parametrized test cases_)
let you reuse the same set of assertions across different input values. let you reuse the same set of assertions across different input values.
In Catch2, this means that they respect the ordering and nesting In Catch2, this means that they respect the ordering and nesting
of the `TEST_CASE` and `SECTION` macros. of the `TEST_CASE` and `SECTION` macros, and their nested sections
are run once per each value in a generator.
How does combining generators and test cases work might be better
explained by an example:
This is best explained with an example:
```cpp ```cpp
TEST_CASE("Generators") { TEST_CASE("Generators") {
auto i = GENERATE( range(1, 11) ); auto i = GENERATE(1, 2, 3);
SECTION("one") {
SECTION( "Some section" ) { auto j = GENERATE( -3, -2, -1 );
auto j = GENERATE( range( 11, 21 ) ); REQUIRE(j < i);
REQUIRE(i < j);
} }
} }
``` ```
the assertion will be checked 100 times, because there are 10 possible The assertion in this test case will be run 9 times, because there
values for `i` (1, 2, ..., 10) and for each of them, there are 10 possible are 3 possible values for `i` (1, 2, and 3) and there are 3 possible
values for `j` (11, 12, ..., 20). 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
* 4 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
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, T, Func>` (map `T` to `T`)
* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
And can be used as shown in the example below to create a generator
that returns 100 odd random number:
You can also combine multiple generators by concatenation:
```cpp ```cpp
static int square(int x) { return x * x; } TEST_CASE("Generating random ints", "[example][generator]") {
TEST_CASE("Generators 2") { SECTION("Deducing functions") {
auto i = GENERATE(0, 1, -1, range(-20, -10), range(10, 20)); auto i = GENERATE(take(100, filter([](int i) { return i % 2 == 1; }, random(-100, 100))));
CAPTURE(i); REQUIRE(i > -100);
REQUIRE(square(i) >= 0); REQUIRE(i < 100);
REQUIRE(i % 2 == 1);
}
} }
``` ```
This will call `square` with arguments `0`, `1`, `-1`, `-20`, ..., `-11`, _Note that `random` is currently not a part of the first-party generators_.
`10`, ..., `19`.
----------
Because of the experimental nature of the current Generator implementation, Apart from registering generators with Catch2, the `GENERATE` macro has
we won't list all of the first-party generators in Catch2. Instead you one more purpose, and that is to provide simple way of generating trivial
should look at our current usage tests in generators, as seen in the first example on this page, where we used it
[projects/SelfTest/UsageTests/Generators.tests.cpp](/projects/SelfTest/UsageTests/Generators.tests.cpp). as `auto i = GENERATE(1, 2, 3);`. This usage converted each of the three
For implementing your own generators, you can look at their implementation in literals into a single `ValueGenerator<int>` and then placed them all in
[include/internal/catch_generators.hpp](/include/internal/catch_generators.hpp). 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.**
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> <a id="top"></a>
# Known limitations # Known limitations
Catch has some known limitations, that we are not planning to change. Some of these are caused by our desire to support C++98 compilers, some of these are caused by our desire to keep Catch crossplatform, some exist because their priority is seen as low compared to the development effort they would need and some other yet are compiler/runtime bugs. Over time, some limitations of Catch2 emerged. Some of these are due
to implementation details that cannot be easily changed, some of these
are due to lack of development resources on our part, and some of these
are due to plain old 3rd party bugs.
## Implementation limits ## Implementation limits
### Sections nested in loops ### Sections nested in loops
If you are using `SECTION`s inside loops, you have to create them with different name per loop's iteration. The recommended way to do so is to incorporate the loop's counter into section's name, like so If you are using `SECTION`s inside loops, you have to create them with
different name per loop's iteration. The recommended way to do so is to
incorporate the loop's counter into section's name, like so:
```cpp ```cpp
TEST_CASE( "Looped section" ) { TEST_CASE( "Looped section" ) {
for (char i = '0'; i < '5'; ++i) { for (char i = '0'; i < '5'; ++i) {
@@ -17,6 +24,27 @@ TEST_CASE( "Looped section" ) {
} }
``` ```
or with a `DYNAMIC_SECTION` macro (that was made for exactly this purpose):
```cpp
TEST_CASE( "Looped section" ) {
for (char i = '0'; i < '5'; ++i) {
DYNAMIC_SECTION( "Looped section " << i) {
SUCCEED( "Everything is OK" );
}
}
}
```
### Tests might be run again if last section fails
If the last section in a test fails, it might be run again. This is because
Catch2 discovers `SECTION`s dynamically, as they are about to run, and
if the last section in test case is aborted during execution (e.g. via
the `REQUIRE` family of macros), Catch2 does not know that there are no
more sections in that test case and must run the test case again.
## Features ## Features
This section outlines some missing features, what is their status and their possible workarounds. This section outlines some missing features, what is their status and their possible workarounds.
@@ -137,3 +165,14 @@ If you are seeing a problem like this, i.e. a weird test paths that trigger only
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. 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++`. 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++.

View File

@@ -3,14 +3,20 @@
## Already available ## Already available
- Catch main: [Catch-provided main](../examples/000-CatchMain.cpp)
- Test Case: [Single-file](../examples/010-TestCase.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) - 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) - Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)
- Fixture: [Sections](../examples/100-Fix-Section.cpp) - Fixture: [Sections](../examples/100-Fix-Section.cpp)
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp) - Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.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) - Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp) - Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
- Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp)
- Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp)
## Planned ## Planned
@@ -27,7 +33,10 @@
- Logging: [FAIL, FAIL_CHECK - Issue message and force failure/continue](../examples/170-Log-Fail.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) - Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp) - Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
- Report: [Reporter](../examples/200-Rpt-UserDefinedReporter.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: [Provide your own main()](../examples/220-Cfg-OwnMain.cpp)
- Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp) - Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
- Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp) - Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)

View File

@@ -45,6 +45,9 @@ These macros come in three forms:
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 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.
_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._
**WARN(** _message expression_ **)** **WARN(** _message expression_ **)**
The message is always reported but does not fail the test. The message is always reported but does not fail the test.
@@ -57,20 +60,37 @@ The message is reported and the test case fails.
AS `FAIL`, but does not abort the test 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. e.g. `CAPTURE( theAnswer );` will log message "theAnswer := 42", while
```c++ ```cpp
CAPTURE( theAnswer ); 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>
--- ---

View File

@@ -32,6 +32,9 @@ A, single-header-only, type-safe, command line parser - which also prints format
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core) ### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
The next-generation core storage and query engine for Couchbase Lite The next-generation core storage and query engine for Couchbase Lite
### [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) ### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
A High-performance Cluster Computing Engine A High-performance Cluster Computing Engine

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 neccessarily 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
neccessarily 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> <a id="top"></a>
# Supplying main() yourself # Supplying main() yourself
**Contents**<br>
[Let Catch take full control of args and config](#let-catch-take-full-control-of-args-and-config)<br>
[Amending the config](#amending-the-config)<br>
[Adding your own command line options](#adding-your-own-command-line-options)<br>
[Version detection](#version-detection)<br>
The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line. The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line.
This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file. This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file.

View File

@@ -1,12 +1,136 @@
<a id="top"></a> <a id="top"></a>
# 2.4.0 # Release notes
**Contents**<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.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 **This release brings two new experimental features, generator support
and a `-fno-exceptions` support. Being experimental means that they and a `-fno-exceptions` support. Being experimental means that they
will not be subject to the usual stability guarantees provided by semver.** will not be subject to the usual stability guarantees provided by semver.**
## Improvements ### Improvements
* Various small runtime performance improvements * Various small runtime performance improvements
* `CAPTURE` macro is now variadic * `CAPTURE` macro is now variadic
* Added `AND_GIVEN` macro (#1360) * Added `AND_GIVEN` macro (#1360)
@@ -16,11 +140,11 @@ will not be subject to the usual stability guarantees provided by semver.**
* Doing so limits the functionality somewhat * Doing so limits the functionality somewhat
* Look [into the documentation](configuration.md#disablingexceptions) for details * Look [into the documentation](configuration.md#disablingexceptions) for details
## Fixes ### Fixes
* Suppressed `-Wnon-virtual-dtor` warnings in Matchers (#1357) * Suppressed `-Wnon-virtual-dtor` warnings in Matchers (#1357)
* Suppressed `-Wunreachable-code` warnings in floating point matchers (#1350) * Suppressed `-Wunreachable-code` warnings in floating point matchers (#1350)
## CMake ### CMake
* It is now possible to override which Python is used to run Catch's tests (#1365) * 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 now provides infrastructure for adding tests that check compile-time configuration
* Catch no longer tries to install itself when used as a subproject (#1373) * Catch no longer tries to install itself when used as a subproject (#1373)
@@ -29,7 +153,7 @@ will not be subject to the usual stability guarantees provided by semver.**
* This fixes conan installation of Catch * This fixes conan installation of Catch
# 2.3.0 ## 2.3.0
**This release changes the include paths provided by our CMake and **This release changes the include paths provided by our CMake and
pkg-config integration. The proper include path for the single-header pkg-config integration. The proper include path for the single-header
@@ -40,7 +164,7 @@ than `single_include/catch.hpp`.**
## Fixes ### Fixes
* Fixed Objective-C++ build * Fixed Objective-C++ build
* `-Wunused-variable` suppression no longer leaks from Catch's header under Clang * `-Wunused-variable` suppression no longer leaks from Catch's header under Clang
* Implementation of the experimental new output capture can now be disabled (#1335) * Implementation of the experimental new output capture can now be disabled (#1335)
@@ -48,7 +172,7 @@ than `single_include/catch.hpp`.**
* The JUnit and XML reporters will no longer skip over successful tests when running without `-s` (#1264, #1267, #1310) * The JUnit and XML reporters will no longer skip over successful tests when running without `-s` (#1264, #1267, #1310)
* See improvements for more details * See improvements for more details
## Improvements ### Improvements
* pkg-config and CMake integration has been rewritten * pkg-config and CMake integration has been rewritten
* If you use them, the new include path is `#include <catch2/catch.hpp>` * If you use them, the new include path is `#include <catch2/catch.hpp>`
* CMake installation now also installs scripts from `contrib/` * CMake installation now also installs scripts from `contrib/`
@@ -60,12 +184,12 @@ than `single_include/catch.hpp`.**
* This means that you can do `DYNAMIC_SECTION("For X := " << x)`. * This means that you can do `DYNAMIC_SECTION("For X := " << x)`.
# 2.2.3 ## 2.2.3
**To fix some of the bugs, some behavior had to change in potentially breaking manner.** **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.** **This means that even though this is a patch release, it might not be a drop-in replacement.**
## Fixes ### Fixes
* Listeners are now called before reporter * Listeners are now called before reporter
* This was always documented to be the case, now it actually works that way * This was always documented to be the case, now it actually works that way
* Catch's commandline will no longer accept multiple reporters * Catch's commandline will no longer accept multiple reporters
@@ -84,23 +208,23 @@ than `single_include/catch.hpp`.**
* **This has potential to be a breaking change** * **This has potential to be a breaking change**
* Fixed compilation error when a type has an `operator<<` with templated lhs (#1285, #1306) * Fixed compilation error when a type has an `operator<<` with templated lhs (#1285, #1306)
## Improvements ### Improvements
* Added a new, experimental, output capture (#1243) * Added a new, experimental, output capture (#1243)
* This capture can also redirect output written via C apis, e.g. `printf` * 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 * To opt-in, define `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` in the implementation file
* Added a new fallback stringifier for classes derived from `std::exception` * Added a new fallback stringifier for classes derived from `std::exception`
* Both `StringMaker` specialization and `operator<<` overload are given priority * Both `StringMaker` specialization and `operator<<` overload are given priority
## Miscellaneous ### Miscellaneous
* `contrib/` now contains dbg scripts that skip over Catch's internals (#904, #1283) * `contrib/` now contains dbg scripts that skip over Catch's internals (#904, #1283)
* `gdbinit` for gdb `lldbinit` for lldb * `gdbinit` for gdb `lldbinit` for lldb
* `CatchAddTests.cmake` no longer strips whitespace from tests (#1265, #1281) * `CatchAddTests.cmake` no longer strips whitespace from tests (#1265, #1281)
* Online documentation now describes `--use-colour` option (#1263) * Online documentation now describes `--use-colour` option (#1263)
# 2.2.2 ## 2.2.2
## Fixes ### Fixes
* Fixed bug in `WithinAbs::match()` failing spuriously (#1228) * Fixed bug in `WithinAbs::match()` failing spuriously (#1228)
* Fixed clang-tidy diagnostic about virtual call in destructor (#1226) * Fixed clang-tidy diagnostic about virtual call in destructor (#1226)
* Reduced the number of GCC warnings suppression leaking out of the header (#1090, #1091) * Reduced the number of GCC warnings suppression leaking out of the header (#1090, #1091)
@@ -109,7 +233,7 @@ than `single_include/catch.hpp`.**
* On platforms where `std::chrono::high_resolution_clock`'s resolution is low, the calibration would appear stuck * 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) * Fixed compilation error when stringifying static arrays of `unsigned char`s (#1238)
## Improvements ### Improvements
* XML encoder now hex-encodes invalid UTF-8 sequences (#1207) * XML encoder now hex-encodes invalid UTF-8 sequences (#1207)
* This affects xml and junit reporters * 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. * 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.
@@ -118,29 +242,29 @@ than `single_include/catch.hpp`.**
* Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236) * 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) * See [documentation for details](https://github.com/catchorg/Catch2/blob/master/docs/matchers.md)
## Others ### Others
* Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239) * Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239)
* The plans to standardize on `#include <catch2/catch.hpp>` are still in effect * The plans to standardize on `#include <catch2/catch.hpp>` are still in effect
# 2.2.1 ## 2.2.1
## Fixes ### Fixes
* Fixed compilation error when compiling Catch2 with `std=c++17` against libc++ (#1214) * 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 * Clara (Catch2's CLI parsing library) used `std::optional` without including it explicitly
* Fixed Catch2 return code always being 0 (#1215) * Fixed Catch2 return code always being 0 (#1215)
* In the words of STL, "We feel superbad about letting this in" * In the words of STL, "We feel superbad about letting this in"
# 2.2.0 ## 2.2.0
## Fixes ### Fixes
* Hidden tests are not listed by default when listing tests (#1175) * Hidden tests are not listed by default when listing tests (#1175)
* This makes `catch_discover_tests` CMake script work better * This makes `catch_discover_tests` CMake script work better
* Fixed regression that meant `<windows.h>` could potentially not be included properly (#1197) * Fixed regression that meant `<windows.h>` could potentially not be included properly (#1197)
* Fixed installing `Catch2ConfigVersion.cmake` when Catch2 is a subproject. * Fixed installing `Catch2ConfigVersion.cmake` when Catch2 is a subproject.
## Improvements ### Improvements
* Added an option to warn (+ exit with error) when no tests were ran (#1158) * Added an option to warn (+ exit with error) when no tests were ran (#1158)
* Use as `-w NoTests` * Use as `-w NoTests`
* Added provisional support for Emscripten (#1114) * Added provisional support for Emscripten (#1114)
@@ -152,38 +276,38 @@ than `single_include/catch.hpp`.**
* Added support for DJGPP DOS crosscompiler (#1206) * Added support for DJGPP DOS crosscompiler (#1206)
# 2.1.2 ## 2.1.2
## Fixes ### Fixes
* Fixed compilation error with `-fno-rtti` (#1165) * Fixed compilation error with `-fno-rtti` (#1165)
* Fixed NoAssertion warnings * Fixed NoAssertion warnings
* `operator<<` is used before range-based stringification (#1172) * `operator<<` is used before range-based stringification (#1172)
* Fixed `-Wpedantic` warnings (extra semicolons and binary literals) (#1173) * Fixed `-Wpedantic` warnings (extra semicolons and binary literals) (#1173)
## Improvements ### Improvements
* Added `CATCH_VERSION_{MAJOR,MINOR,PATCH}` macros (#1131) * Added `CATCH_VERSION_{MAJOR,MINOR,PATCH}` macros (#1131)
* Added `BrightYellow` colour for use in reporters (#979) * Added `BrightYellow` colour for use in reporters (#979)
* It is also used by ConsoleReporter for reconstructed expressions * It is also used by ConsoleReporter for reconstructed expressions
## Other changes ### Other changes
* Catch is now exported as a CMake package and linkable target (#1170) * Catch is now exported as a CMake package and linkable target (#1170)
# 2.1.1 ## 2.1.1
## Improvements ### Improvements
* Static arrays are now properly stringified like ranges across MSVC/GCC/Clang * Static arrays are now properly stringified like ranges across MSVC/GCC/Clang
* Embedded newer version of Clara -- v1.1.1 * Embedded newer version of Clara -- v1.1.1
* This should fix some warnings dragged in from Clara * This should fix some warnings dragged in from Clara
* MSVC's CLR exceptions are supported * MSVC's CLR exceptions are supported
## Fixes ### Fixes
* Fixed compilation when comparison operators do not return bool (#1147) * Fixed compilation when comparison operators do not return bool (#1147)
* Fixed CLR exceptions blowing up the executable during translation (#1138) * Fixed CLR exceptions blowing up the executable during translation (#1138)
## Other changes ### Other changes
* Many CMake changes * Many CMake changes
* `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead. * `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead.
* Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes * Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes
@@ -191,9 +315,9 @@ than `single_include/catch.hpp`.**
# 2.1.0 ## 2.1.0
## Improvements ### Improvements
* Various performance improvements * Various performance improvements
* On top of the performance regression fixes * On top of the performance regression fixes
* Experimental support for PCH was added (#1061) * Experimental support for PCH was added (#1061)
@@ -203,7 +327,7 @@ than `single_include/catch.hpp`.**
* Bugs in g++ 4.x and 5.x mean that some of them have to be left in * Bugs in g++ 4.x and 5.x mean that some of them have to be left in
## Fixes ### Fixes
* Fixed performance regression from Catch classic * Fixed performance regression from Catch classic
* One of the performance improvement patches for Catch classic was not applied to Catch2 * One of the performance improvement patches for Catch classic was not applied to Catch2
* Fixed platform detection for iOS (#1084) * Fixed platform detection for iOS (#1084)
@@ -216,7 +340,7 @@ than `single_include/catch.hpp`.**
* Fixed `std::uncaught_exception` deprecation warning (#1124) * Fixed `std::uncaught_exception` deprecation warning (#1124)
## New features ### New features
* New Matchers * New Matchers
* Regex matcher for strings, `Matches`. * Regex matcher for strings, `Matches`.
* Set-equal matcher for vectors, `UnorderedEquals` * Set-equal matcher for vectors, `UnorderedEquals`
@@ -225,15 +349,15 @@ than `single_include/catch.hpp`.**
* Containers are objects that respond to ADL `begin(T)` and `end(T)`. * Containers are objects that respond to ADL `begin(T)` and `end(T)`.
## Other changes ### Other changes
* Reporters will now be versioned in the `single_include` folder to ensure their compatibility with the last released version * Reporters will now be versioned in the `single_include` folder to ensure their compatibility with the last released version
# 2.0.1 ## 2.0.1
## Breaking changes ### Breaking changes
* Removed C++98 support * Removed C++98 support
* Removed legacy reporter support * Removed legacy reporter support
* Removed legacy generator support * Removed legacy generator support
@@ -263,7 +387,7 @@ than `single_include/catch.hpp`.**
* `INFINITY == Approx(INFINITY)` returns true * `INFINITY == Approx(INFINITY)` returns true
## Improvements ### Improvements
* Reporters and Listeners can be defined in files different from the main file * Reporters and Listeners can be defined in files different from the main file
* The file has to define `CATCH_CONFIG_EXTERNAL_INTERFACES` before including catch.hpp. * The file has to define `CATCH_CONFIG_EXTERNAL_INTERFACES` before including catch.hpp.
* Errors that happen during set up before main are now caught and properly reported once main is entered * Errors that happen during set up before main are now caught and properly reported once main is entered
@@ -297,7 +421,7 @@ than `single_include/catch.hpp`.**
* Add `pkg-config` support to CMake install command * Add `pkg-config` support to CMake install command
## Fixes ### Fixes
* Don't use console colour if running in XCode * Don't use console colour if running in XCode
* Explicit constructor in reporter base class * Explicit constructor in reporter base class
* Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings * Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings
@@ -309,7 +433,7 @@ than `single_include/catch.hpp`.**
* Suppressed C4061 warning under MSVC * Suppressed C4061 warning under MSVC
## Internal changes ### Internal changes
* The development version now uses .cpp files instead of header files containing implementation. * The development version now uses .cpp files instead of header files containing implementation.
* This makes partial rebuilds much faster during development * This makes partial rebuilds much faster during development
* The expression decomposition layer has been rewritten * The expression decomposition layer has been rewritten
@@ -317,13 +441,33 @@ than `single_include/catch.hpp`.**
* New library (TextFlow) is used for formatting text to output * New library (TextFlow) is used for formatting text to output
# Older versions ## Older versions
## 1.11.x ### 1.12.x
### 1.11.0 #### 1.12.2
##### Fixes
* Fixed missing <cassert> include
#### Fixes #### 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) * 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` * Previously the parentheses were missing and `x != y` would be expanded as `!x != x`
* `Approx::Margin` is now inclusive (#952) * `Approx::Margin` is now inclusive (#952)
@@ -331,7 +475,7 @@ than `single_include/catch.hpp`.**
* This means that `REQUIRE( 0.25f == Approx( 0.0f ).margin( 0.25f ) )` passes, instead of fails * This means that `REQUIRE( 0.25f == Approx( 0.0f ).margin( 0.25f ) )` passes, instead of fails
* `RandomNumberGenerator::result_type` is now unsigned (#1050) * `RandomNumberGenerator::result_type` is now unsigned (#1050)
#### Improvements ##### Improvements
* `__JETBRAINS_IDE__` macro handling is now CLion version specific (#1017) * `__JETBRAINS_IDE__` macro handling is now CLion version specific (#1017)
* When CLion 2017.3 or newer is detected, `__COUNTER__` is used instead of * When CLion 2017.3 or newer is detected, `__COUNTER__` is used instead of
* TeamCity reporter now explicitly flushes output stream after each report (#1057) * TeamCity reporter now explicitly flushes output stream after each report (#1057)
@@ -339,35 +483,35 @@ than `single_include/catch.hpp`.**
* `ParseAndAddCatchTests` now can add test files as dependency to CMake configuration * `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 * This means you do not have to manually rerun CMake configuration step to detect new tests
## 1.10.x ### 1.10.x
### 1.10.0 #### 1.10.0
#### Fixes ##### Fixes
* Evaluation layer has been rewritten (backported from Catch 2) * Evaluation layer has been rewritten (backported from Catch 2)
* The new layer is much simpler and fixes some issues (#981) * The new layer is much simpler and fixes some issues (#981)
* Implemented workaround for VS 2017 raw string literal stringification bug (#995) * Implemented workaround for VS 2017 raw string literal stringification bug (#995)
* Fixed interaction between `[!shouldfail]` and `[!mayfail]` tags and sections * Fixed interaction between `[!shouldfail]` and `[!mayfail]` tags and sections
* Previously sections with failing assertions would be marked as failed, not failed-but-ok * Previously sections with failing assertions would be marked as failed, not failed-but-ok
#### Improvements ##### Improvements
* Added [libidentify](https://github.com/janwilmans/LibIdentify) support * Added [libidentify](https://github.com/janwilmans/LibIdentify) support
* Added "wait-for-keypress" option * Added "wait-for-keypress" option
## 1.9.x ### 1.9.x
### 1.9.6 #### 1.9.6
#### Improvements ##### Improvements
* Catch's runtime overhead has been significantly decreased (#937, #939) * Catch's runtime overhead has been significantly decreased (#937, #939)
* Added `--list-extra-info` cli option (#934). * Added `--list-extra-info` cli option (#934).
* It lists all tests together with extra information, ie filename, line number and description. * It lists all tests together with extra information, ie filename, line number and description.
### 1.9.5 #### 1.9.5
#### Fixes ##### Fixes
* Truthy expressions are now reconstructed properly, not as booleans (#914) * Truthy expressions are now reconstructed properly, not as booleans (#914)
* Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871) * Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871)
* Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855) * Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855)
@@ -375,35 +519,35 @@ than `single_include/catch.hpp`.**
* Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`. * Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`.
* Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927) * Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927)
#### Improvements ##### Improvements
* CMake integration script now incorporates debug messages and registers tests in an improved way (#911) * CMake integration script now incorporates debug messages and registers tests in an improved way (#911)
* Various documentation improvements * Various documentation improvements
### 1.9.4 #### 1.9.4
#### Fixes ##### Fixes
* `CATCH_FAIL` macro no longer causes compilation error without variadic macro support * `CATCH_FAIL` macro no longer causes compilation error without variadic macro support
* `INFO` messages are no longer cleared after being reported once * `INFO` messages are no longer cleared after being reported once
#### Improvements and minor changes ##### Improvements and minor changes
* Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined. * Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined.
* Note that Catch still officially supports only ASCII * Note that Catch still officially supports only ASCII
### 1.9.3 #### 1.9.3
#### Fixes ##### Fixes
* Completed the fix for (lack of) uint64_t in earlier Visual Studios * Completed the fix for (lack of) uint64_t in earlier Visual Studios
### 1.9.2 #### 1.9.2
#### Improvements and minor changes ##### Improvements and minor changes
* All of `Approx`'s member functions now accept strong typedefs in C++11 mode (#888) * All of `Approx`'s member functions now accept strong typedefs in C++11 mode (#888)
* Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't. * Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't.
#### Fixes ##### Fixes
* POSIX signals are now disabled by default under QNX (#889) * POSIX signals are now disabled by default under QNX (#889)
* QNX does not support current enough (2001) POSIX specification * QNX does not support current enough (2001) POSIX specification
* JUnit no longer counts exceptions as failures if given test case is marked as ok to fail. * JUnit no longer counts exceptions as failures if given test case is marked as ok to fail.
@@ -411,22 +555,22 @@ than `single_include/catch.hpp`.**
* Catch no longer attempts to define `uint64_t` on windows (#862) * Catch no longer attempts to define `uint64_t` on windows (#862)
* This was causing trouble when compiled under Cygwin * This was causing trouble when compiled under Cygwin
#### Other ##### Other
* Catch is now compiled under MSVC 2017 using `std:c++latest` (C++17 mode) in CI * Catch is now compiled under MSVC 2017 using `std:c++latest` (C++17 mode) in CI
* We now provide cmake script that autoregisters Catch tests into ctest. * We now provide cmake script that autoregisters Catch tests into ctest.
* See `contrib` folder. * See `contrib` folder.
### 1.9.1 #### 1.9.1
#### Fixes ##### Fixes
* Unexpected exceptions are no longer ignored by default (#885, #887) * Unexpected exceptions are no longer ignored by default (#885, #887)
### 1.9.0 #### 1.9.0
#### Improvements and minor changes ##### Improvements and minor changes
* Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference. * Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference.
* It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions * It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions
* This actually reverts changes made in v1.7.2 * This actually reverts changes made in v1.7.2
@@ -440,7 +584,7 @@ than `single_include/catch.hpp`.**
* When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`. * When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`.
* Captured messages are now printed on unexpected exceptions * Captured messages are now printed on unexpected exceptions
#### Fixes: ##### Fixes:
* Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals * Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals
* GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`. * GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`.
* This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work. * This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work.
@@ -449,18 +593,18 @@ than `single_include/catch.hpp`.**
* [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check) * [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check)
#### Other notes: ##### Other notes:
* We have added VS 2017 to our CI * We have added VS 2017 to our CI
* Work on Catch 2 should start soon * Work on Catch 2 should start soon
## 1.8.x ### 1.8.x
### 1.8.2 #### 1.8.2
#### Improvements and minor changes ##### Improvements and minor changes
* TAP reporter now behaves as if `-s` was always set * TAP reporter now behaves as if `-s` was always set
* This should be more consistent with the protocol desired behaviour. * This should be more consistent with the protocol desired behaviour.
* Compact reporter now obeys `-d yes` argument (#780) * Compact reporter now obeys `-d yes` argument (#780)
@@ -474,7 +618,7 @@ than `single_include/catch.hpp`.**
* Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion. * Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion.
#### Fixes: ##### Fixes:
* Catch no longer attempts to reconstruct expression that led to a fatal error (#810) * Catch no longer attempts to reconstruct expression that led to a fatal error (#810)
* This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition. * This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition.
* Fixed (C4265) missing virtual destructor warning in Matchers (#844) * Fixed (C4265) missing virtual destructor warning in Matchers (#844)
@@ -491,21 +635,21 @@ than `single_include/catch.hpp`.**
* Regression in Objective-C bindings (Matchers) fixed (#854) * Regression in Objective-C bindings (Matchers) fixed (#854)
#### Other notes: ##### Other notes:
* We have added VS 2013 and 2015 to our CI * We have added VS 2013 and 2015 to our CI
* Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser). * Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser).
### 1.8.1 #### 1.8.1
#### Fixes ##### Fixes
Cygwin issue with `gettimeofday` - `#define` was not early enough Cygwin issue with `gettimeofday` - `#define` was not early enough
### 1.8.0 #### 1.8.0
#### New features/ minor changes ##### New features/ minor changes
* Matchers have new, simpler (and documented) interface. * Matchers have new, simpler (and documented) interface.
* Catch provides string and vector matchers. * Catch provides string and vector matchers.
@@ -525,7 +669,7 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
* `Approx` now supports an optional margin of absolute error * `Approx` now supports an optional margin of absolute error
* It has also received [new documentation](assertions.md#top). * It has also received [new documentation](assertions.md#top).
#### Fixes ##### Fixes
* Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer. * Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer.
* Fixed C4512 ("assignment operator could not be generated") warnings under VS2013. * Fixed C4512 ("assignment operator could not be generated") warnings under VS2013.
* Cygwin compatibility fixes * Cygwin compatibility fixes
@@ -536,15 +680,15 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
* Otherwise it is supressed for the whole TU * Otherwise it is supressed for the whole TU
* Fixed test spec parser issue (with escapes in multiple names) * Fixed test spec parser issue (with escapes in multiple names)
#### Other ##### Other
* Various documentation fixes and improvements * Various documentation fixes and improvements
## 1.7.x ### 1.7.x
### 1.7.2 #### 1.7.2
#### Fixes and minor improvements ##### Fixes and minor improvements
Xml: Xml:
(technically the first two are breaking changes but are also fixes and arguably break few if any people) (technically the first two are breaking changes but are also fixes and arguably break few if any people)
@@ -563,9 +707,9 @@ Other:
* Silenced a few more warnings in different circumstances * Silenced a few more warnings in different circumstances
* Travis improvements * Travis improvements
### 1.7.1 #### 1.7.1
#### Fixes: ##### Fixes:
* Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`. * Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`.
* Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC. * Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC.
* For specifics, look into the [documentation](configuration.md#top). * For specifics, look into the [documentation](configuration.md#top).
@@ -575,9 +719,9 @@ Other:
* Fixed possible infinite recursion in Windows SEH. * Fixed possible infinite recursion in Windows SEH.
* Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators. * Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators.
### 1.7.0 #### 1.7.0
#### Features/ Changes: ##### Features/ Changes:
* Catch now runs significantly faster for passing tests * Catch now runs significantly faster for passing tests
* Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s. * Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s.
* Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s. * Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s.
@@ -591,30 +735,30 @@ Other:
* Certain characters (space, tab, etc) are now pretty printed. * Certain characters (space, tab, etc) are now pretty printed.
* This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`. * This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`.
#### Fixes: ##### Fixes:
* Text formatting no longer attempts to access out-of-bounds characters under certain conditions. * Text formatting no longer attempts to access out-of-bounds characters under certain conditions.
* THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast. * THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast.
* Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined. * Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined.
* Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro. * Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro.
#### Other: ##### Other:
* Catch's CMakeLists now defines install command. * Catch's CMakeLists now defines install command.
* Catch's CMakeLists now generates projects with warnings enabled. * Catch's CMakeLists now generates projects with warnings enabled.
## 1.6.x ### 1.6.x
### 1.6.1 #### 1.6.1
#### Features/ Changes: ##### Features/ Changes:
* Catch now supports breaking into debugger on Linux * Catch now supports breaking into debugger on Linux
#### Fixes: ##### Fixes:
* Generators no longer leak memory (generators are still unsupported in general) * Generators no longer leak memory (generators are still unsupported in general)
* JUnit reporter now reports UTC timestamps, instead of "tbd" * JUnit reporter now reports UTC timestamps, instead of "tbd"
* `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros * `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros
#### Other: ##### Other:
* Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro. * Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
* The use of `__COUNTER__` is supressed when Catch is parsed by CLion * The use of `__COUNTER__` is supressed when Catch is parsed by CLion
* This change is not active when compiling a binary * This change is not active when compiling a binary
@@ -624,28 +768,28 @@ Other:
* This can be disabled if needed, see [documentation](configuration.md#top) for details. * This can be disabled if needed, see [documentation](configuration.md#top) for details.
### 1.6.0 #### 1.6.0
#### Cmake/ projects: ##### Cmake/ projects:
* Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects. * Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects.
#### Features/ Changes: ##### Features/ Changes:
* Approx now supports `>=` and `<=` * Approx now supports `>=` and `<=`
* Can now use `\` to escape chars in test names on command line * Can now use `\` to escape chars in test names on command line
* Standardize C++11 feature toggles * Standardize C++11 feature toggles
#### Fixes: ##### Fixes:
* Blue shell colour * Blue shell colour
* Missing argument to `CATCH_CHECK_THROWS` * Missing argument to `CATCH_CHECK_THROWS`
* Don't encode extended ASCII in XML * Don't encode extended ASCII in XML
* use `std::shuffle` on more compilers (fixes deprecation warning/error) * use `std::shuffle` on more compilers (fixes deprecation warning/error)
* Use `__COUNTER__` more consistently (where available) * Use `__COUNTER__` more consistently (where available)
#### Other: ##### Other:
* Tweaks and changes to scripts - particularly for Approval test - to make them more portable * Tweaks and changes to scripts - particularly for Approval test - to make them more portable
# Even Older versions ## Even Older versions
Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
--- ---

View File

@@ -8,11 +8,11 @@ When enough changes have accumulated, it is time to release new version of Catch
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. 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>`. 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
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. proceed.
### Incrementing version number ### Incrementing version number
@@ -27,7 +27,7 @@ version numbers everywhere and pushing the new version to Wandbox.
### Release notes ### 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 ### Commit and push update to GitHub
@@ -43,11 +43,8 @@ description should contain the release notes for the current release.
Single header version of `catch.hpp` *needs* to be attached as a binary, Single header version of `catch.hpp` *needs* to be attached as a binary,
as that is where the official download link links to. Preferably as that is where the official download link links to. Preferably
it should use linux line endings. All non-bundled reporters (Automake, it should use linux line endings. All non-bundled reporters (Automake,
TAP, TeamCity) should also be attached as binaries, as they are dependent TAP, TeamCity) should also be attached as binaries, as they might be
on a specific version of the single-include header. dependent on a specific version of the single-include header.
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
## Optional steps signed.
Because Catch's [vcpkg](https://github.com/Microsoft/vcpkg) port updates
itself automagically, there are no optional steps at this time.

View File

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

View File

@@ -1,6 +1,12 @@
<a id="top"></a> <a id="top"></a>
# Test cases and sections # 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>
While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style. 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). 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).
@@ -86,6 +92,105 @@ 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! 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._
--- ---
[Home](Readme.md#top) [Home](Readme.md#top)

View File

@@ -30,6 +30,60 @@ 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. 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._
--- ---
[Home](Readme.md#top) [Home](Readme.md#top)

View File

@@ -1,6 +1,12 @@
<a id="top"></a> <a id="top"></a>
# String conversions # String conversions
**Contents**<br>
[operator << overload for std::ostream](#operator--overload-for-stdostream)<br>
[Catch::StringMaker specialisation](#catchstringmaker-specialisation)<br>
[Catch::is_range specialisation](#catchis_range-specialisation)<br>
[Exceptions](#exceptions)<br>
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
@@ -17,9 +23,9 @@ std::ostream& operator << ( std::ostream& os, T const& value ) {
(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function). (where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
You should put this function in the same namespace as your type and 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>`: 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>`:
``` ```
@@ -33,7 +39,7 @@ namespace Catch {
} }
``` ```
## Catch::is_range<T> specialisation ## Catch::is_range specialisation
As a fallback, Catch attempts to detect if the type can be iterated 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 (`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 as a range. For certain types this can lead to infinite recursion, so

View File

@@ -8,6 +8,7 @@
[Test cases and sections](#test-cases-and-sections)<br> [Test cases and sections](#test-cases-and-sections)<br>
[BDD-Style](#bdd-style)<br> [BDD-Style](#bdd-style)<br>
[Scaling up](#scaling-up)<br> [Scaling up](#scaling-up)<br>
[Type parametrised test cases](#type-parametrised-test-cases)<br>
[Next steps](#next-steps)<br> [Next steps](#next-steps)<br>
## Getting Catch2 ## Getting Catch2
@@ -15,14 +16,14 @@
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. The 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 Alternative ways of getting Catch2 include using your system package
manager, or installing it using its CMake 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. The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
## Where to put it? ## Where to put it?
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](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html).
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary. The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
@@ -31,7 +32,7 @@ package, you need to include the header as `#include <catch2/catch.hpp>`_
## Writing tests ## Writing tests
Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now). Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now).
```c++ ```c++
unsigned int Factorial( unsigned int number ) { unsigned int Factorial( unsigned int number ) {
@@ -122,31 +123,31 @@ Catch takes a different approach (to both NUnit and xUnit) that is a more natura
TEST_CASE( "vectors can be sized and resized", "[vector]" ) { TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
std::vector<int> v( 5 ); std::vector<int> v( 5 );
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 ); REQUIRE( v.capacity() >= 5 );
SECTION( "resizing bigger changes size and capacity" ) { SECTION( "resizing bigger changes size and capacity" ) {
v.resize( 10 ); v.resize( 10 );
REQUIRE( v.size() == 10 ); REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
} }
SECTION( "resizing smaller changes size but not capacity" ) { SECTION( "resizing smaller changes size but not capacity" ) {
v.resize( 0 ); v.resize( 0 );
REQUIRE( v.size() == 0 ); REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 ); REQUIRE( v.capacity() >= 5 );
} }
SECTION( "reserving bigger changes capacity but not size" ) { SECTION( "reserving bigger changes capacity but not size" ) {
v.reserve( 10 ); v.reserve( 10 );
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
} }
SECTION( "reserving smaller does not change size or capacity" ) { SECTION( "reserving smaller does not change size or capacity" ) {
v.reserve( 0 ); v.reserve( 0 );
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 ); REQUIRE( v.capacity() >= 5 );
} }
@@ -163,13 +164,13 @@ The power of sections really shows, however, when we need to execute a sequence
```c++ ```c++
SECTION( "reserving bigger changes capacity but not size" ) { SECTION( "reserving bigger changes capacity but not size" ) {
v.reserve( 10 ); v.reserve( 10 );
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
SECTION( "reserving smaller again does not change capacity" ) { SECTION( "reserving smaller again does not change capacity" ) {
v.reserve( 7 ); v.reserve( 7 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
} }
} }
@@ -188,13 +189,13 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
GIVEN( "A vector with some items" ) { GIVEN( "A vector with some items" ) {
std::vector<int> v( 5 ); std::vector<int> v( 5 );
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 ); REQUIRE( v.capacity() >= 5 );
WHEN( "the size is increased" ) { WHEN( "the size is increased" ) {
v.resize( 10 ); v.resize( 10 );
THEN( "the size and capacity change" ) { THEN( "the size and capacity change" ) {
REQUIRE( v.size() == 10 ); REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
@@ -202,7 +203,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
} }
WHEN( "the size is reduced" ) { WHEN( "the size is reduced" ) {
v.resize( 0 ); v.resize( 0 );
THEN( "the size changes but not capacity" ) { THEN( "the size changes but not capacity" ) {
REQUIRE( v.size() == 0 ); REQUIRE( v.size() == 0 );
REQUIRE( v.capacity() >= 5 ); REQUIRE( v.capacity() >= 5 );
@@ -210,7 +211,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
} }
WHEN( "more capacity is reserved" ) { WHEN( "more capacity is reserved" ) {
v.reserve( 10 ); v.reserve( 10 );
THEN( "the capacity changes but not the size" ) { THEN( "the capacity changes but not the size" ) {
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
@@ -218,7 +219,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
} }
WHEN( "less capacity is reserved" ) { WHEN( "less capacity is reserved" ) {
v.reserve( 0 ); v.reserve( 0 );
THEN( "neither size nor capacity are changed" ) { THEN( "neither size nor capacity are changed" ) {
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 ); REQUIRE( v.capacity() >= 5 );
@@ -256,6 +257,17 @@ In fact it is usually a good idea to put the block with the ```#define``` [in it
Do not write your tests in header files! 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 ## 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. 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/), [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), [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), [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). [many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B).
So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course. So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course.

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

@@ -387,16 +387,16 @@ TEST_CASE( "2: Testcase with sections", "[tag-A][tag-B]" ) {
REQUIRE( i == 42 ); REQUIRE( i == 42 );
SECTION("Section 1") { SECTION("Section 1") {
INFO("Section 1") INFO("Section 1");
i = 7; i = 7;
SECTION("Section 1.1") { SECTION("Section 1.1") {
INFO("Section 1.1") INFO("Section 1.1");
REQUIRE( i == 42 ); REQUIRE( i == 42 );
} }
} }
SECTION("Section 2") { SECTION("Section 2") {
INFO("Section 2") INFO("Section 2");
REQUIRE( i == 42 ); REQUIRE( i == 42 );
} }
WARN("At end of test case"); WARN("At end of test case");

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,72 @@
// 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>
#include <random>
// Lets start by implementing a parametrizable double generator
class RandomDoubleGenerator : public Catch::Generators::IGenerator<double> {
std::minstd_rand m_rand;
std::uniform_real_distribution<> m_dist;
double current_number;
public:
RandomDoubleGenerator(double low, double high):
m_rand(std::random_device{}()),
m_dist(low, high)
{
static_cast<void>(next());
}
double const& get() const override;
bool next() override {
current_number = m_dist(m_rand);
return true;
}
};
// Avoids -Wweak-vtables
double const& RandomDoubleGenerator::get() const {
return current_number;
}
// Also provide a nice shortcut for creating the generator
Catch::Generators::GeneratorWrapper<double> random(double low, double high) {
return Catch::Generators::GeneratorWrapper<double>(std::unique_ptr<Catch::Generators::IGenerator<double>>(new RandomDoubleGenerator(low, high)));
}
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(r.first, r.second)));
// We have to manually register the generators instead
// Notice that we are using value capture in the lambda, to avoid lifetime issues
auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
[=]{
using namespace Catch::Generators;
return makeGenerators(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

@@ -8,10 +8,13 @@ cmake_minimum_required( VERSION 3.0 )
project( CatchExamples CXX ) project( CatchExamples CXX )
message( STATUS "Examples included" )
# define folders used: # define folders used:
set( EXAMPLES_DIR ${CATCH_DIR}/examples ) set( EXAMPLES_DIR ${CATCH_DIR}/examples )
set( HEADER_DIR ${CATCH_DIR}/single_include ) set( HEADER_DIR ${CATCH_DIR}/single_include )
set( REPORTER_HEADER_DIR ${CATCH_DIR}/include/reporters )
# single-file sources: # single-file sources:
@@ -41,6 +44,28 @@ set( SOURCES_IDIOMATIC_TESTS
110-Fix-ClassFixture.cpp 110-Fix-ClassFixture.cpp
120-Bdd-ScenarioGivenWhenThen.cpp 120-Bdd-ScenarioGivenWhenThen.cpp
210-Evt-EventListeners.cpp 210-Evt-EventListeners.cpp
300-Gen-OwnGenerator.cpp
310-Gen-VariablesInGenerators.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: # check if all sources are listed, warn if not:
@@ -50,6 +75,8 @@ set( SOURCES_ALL
${SOURCES_SINGLE_FILE} ${SOURCES_SINGLE_FILE}
${SOURCES_IDIOMATIC_MAIN} ${SOURCES_IDIOMATIC_MAIN}
${SOURCES_IDIOMATIC_TESTS} ${SOURCES_IDIOMATIC_TESTS}
${SOURCES_REPORTERS_MAIN}
${SOURCES_REPORTERS_TESTS}
) )
foreach( name ${SOURCES_ALL} ) foreach( name ${SOURCES_ALL} )
@@ -62,16 +89,31 @@ CheckFileList( SOURCES_ALL_PATH ${EXAMPLES_DIR} )
string( REPLACE ".cpp" "" BASENAMES_SINGLE_FILE "${SOURCES_SINGLE_FILE}" ) string( REPLACE ".cpp" "" BASENAMES_SINGLE_FILE "${SOURCES_SINGLE_FILE}" )
string( REPLACE ".cpp" "" BASENAMES_IDIOMATIC_TESTS "${SOURCES_IDIOMATIC_TESTS}" ) 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_SINGLE_FILE ${BASENAMES_SINGLE_FILE} )
set( TARGETS_IDIOMATIC_TESTS ${BASENAMES_IDIOMATIC_TESTS} ) set( TARGETS_IDIOMATIC_TESTS ${BASENAMES_IDIOMATIC_TESTS} )
set( TARGETS_ALL ${TARGETS_SINGLE_FILE} ${TARGETS_IDIOMATIC_TESTS} 020-TestCase CatchMain ) 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: # define program targets:
add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch2/catch.hpp ) 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 )
add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.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} ) foreach( name ${TARGETS_SINGLE_FILE} )
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch2/catch.hpp ) add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch2/catch.hpp )
@@ -81,8 +123,18 @@ foreach( name ${TARGETS_IDIOMATIC_TESTS} )
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp ) add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp )
endforeach() 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} ) foreach( name ${TARGETS_ALL} )
target_include_directories( ${name} PRIVATE ${HEADER_DIR} ) target_include_directories( ${name} PRIVATE ${HEADER_DIR} ${CATCH_DIR} )
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11) set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS OFF) set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS OFF)
@@ -100,3 +152,4 @@ foreach( name ${TARGETS_ALL} )
target_compile_options( ${name} PRIVATE /W4 /w44265 /WX ) target_compile_options( ${name} PRIVATE /W4 /w44265 /WX )
endif() endif()
endforeach() endforeach()

View File

@@ -10,7 +10,7 @@
#define TWOBLUECUBES_CATCH_HPP_INCLUDED #define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 4 #define CATCH_VERSION_MINOR 6
#define CATCH_VERSION_PATCH 0 #define CATCH_VERSION_PATCH 0
#ifdef __clang__ #ifdef __clang__
@@ -145,6 +145,28 @@
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #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_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( 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_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( 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_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( 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 // "BDD-style" convenience wrappers
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
@@ -205,6 +227,27 @@
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #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_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
#else
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( 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_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( 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 #endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
@@ -275,6 +318,18 @@ using Catch::Detail::Approx;
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #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(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( 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(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#endif
// "BDD-style" convenience wrappers // "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( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
@@ -285,6 +340,9 @@ using Catch::Detail::Approx;
#define CATCH_THEN( desc ) #define CATCH_THEN( desc )
#define CATCH_AND_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 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else #else
@@ -335,6 +393,21 @@ using Catch::Detail::Approx;
#define SUCCEED( ... ) (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____ )) #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(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#else
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
#endif
#define STATIC_REQUIRE( ... ) (void)(0)
#define STATIC_REQUIRE_FALSE( ... ) (void)(0)
#endif #endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )

View File

@@ -5,7 +5,7 @@
// //
// See https://github.com/philsquared/Clara for more details // See https://github.com/philsquared/Clara for more details
// Clara v1.1.4 // Clara v1.1.5
#ifndef CATCH_CLARA_HPP_INCLUDED #ifndef CATCH_CLARA_HPP_INCLUDED
#define CATCH_CLARA_HPP_INCLUDED #define CATCH_CLARA_HPP_INCLUDED
@@ -34,8 +34,8 @@
// //
// A single-header library for wrapping and laying out basic text, by Phil Nash // A single-header library for wrapping and laying out basic text, by Phil Nash
// //
// This work is licensed under the BSD 2-Clause license. // Distributed under the Boost Software License, Version 1.0. (See accompanying
// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
// This project is hosted at https://github.com/philsquared/textflowcpp // This project is hosted at https://github.com/philsquared/textflowcpp
@@ -52,317 +52,326 @@
#endif #endif
namespace Catch { namespace clara { namespace TextFlow { namespace Catch {
namespace clara {
namespace TextFlow {
inline auto isWhitespace( char c ) -> bool { inline auto isWhitespace(char c) -> bool {
static std::string chars = " \t\n\r"; static std::string chars = " \t\n\r";
return chars.find( c ) != std::string::npos; return chars.find(c) != std::string::npos;
} }
inline auto isBreakableBefore( char c ) -> bool { inline auto isBreakableBefore(char c) -> bool {
static std::string chars = "[({<|"; static std::string chars = "[({<|";
return chars.find( c ) != std::string::npos; return chars.find(c) != std::string::npos;
} }
inline auto isBreakableAfter( char c ) -> bool { inline auto isBreakableAfter(char c) -> bool {
static std::string chars = "])}>.,:;*+-=&/\\"; static std::string chars = "])}>.,:;*+-=&/\\";
return chars.find( c ) != std::string::npos; return chars.find(c) != std::string::npos;
} }
class Columns; class Columns;
class Column { class Column {
std::vector<std::string> m_strings; std::vector<std::string> m_strings;
size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
size_t m_indent = 0; size_t m_indent = 0;
size_t m_initialIndent = std::string::npos; size_t m_initialIndent = std::string::npos;
public: public:
class iterator { class iterator {
friend Column; friend Column;
Column const& m_column; Column const& m_column;
size_t m_stringIndex = 0; size_t m_stringIndex = 0;
size_t m_pos = 0; size_t m_pos = 0;
size_t m_len = 0; size_t m_len = 0;
size_t m_end = 0; size_t m_end = 0;
bool m_suffix = false; bool m_suffix = false;
iterator( Column const& column, size_t stringIndex ) iterator(Column const& column, size_t stringIndex)
: m_column( column ), : m_column(column),
m_stringIndex( stringIndex ) 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 { auto isBoundary(size_t at) const -> bool {
assert( at > 0 ); assert(at > 0);
assert( at <= line().size() ); assert(at <= line().size());
return at == line().size() || return at == line().size() ||
( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
isBreakableBefore( line()[at] ) || isBreakableBefore(line()[at]) ||
isBreakableAfter( line()[at-1] ); isBreakableAfter(line()[at - 1]);
} }
void calcLength() { void calcLength() {
assert( m_stringIndex < m_column.m_strings.size() ); assert(m_stringIndex < m_column.m_strings.size());
m_suffix = false; m_suffix = false;
auto width = m_column.m_width-indent(); auto width = m_column.m_width - indent();
m_end = m_pos; m_end = m_pos;
while( m_end < line().size() && line()[m_end] != '\n' ) while (m_end < line().size() && line()[m_end] != '\n')
++m_end; ++m_end;
if( m_end < m_pos + width ) { if (m_end < m_pos + width) {
m_len = m_end - m_pos; m_len = m_end - m_pos;
} } else {
else { size_t len = width;
size_t len = width; while (len > 0 && !isBoundary(m_pos + len))
while (len > 0 && !isBoundary(m_pos + len)) --len;
--len; while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) --len;
--len;
if (len > 0) { if (len > 0) {
m_len = len; m_len = len;
} else { } else {
m_suffix = true; m_suffix = true;
m_len = width - 1; m_len = width - 1;
} }
} }
} }
auto indent() const -> size_t { auto indent() const -> size_t {
auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; 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; return initial == std::string::npos ? m_column.m_indent : initial;
} }
auto addIndentAndSuffix(std::string const &plain) const -> std::string { auto addIndentAndSuffix(std::string const &plain) const -> std::string {
return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
} }
public: public:
explicit iterator( Column const& column ) : m_column( column ) { using difference_type = std::ptrdiff_t;
assert( m_column.m_width > m_column.m_indent ); using value_type = std::string;
assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); using pointer = value_type * ;
calcLength(); using reference = value_type & ;
if( m_len == 0 ) using iterator_category = std::forward_iterator_tag;
m_stringIndex++; // Empty string
}
auto operator *() const -> std::string { explicit iterator(Column const& column) : m_column(column) {
assert( m_stringIndex < m_column.m_strings.size() ); assert(m_column.m_width > m_column.m_indent);
assert( m_pos <= m_end ); assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
if( m_pos + m_column.m_width < m_end ) calcLength();
return addIndentAndSuffix(line().substr(m_pos, m_len)); if (m_len == 0)
else m_stringIndex++; // Empty string
return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); }
}
auto operator ++() -> iterator& { auto operator *() const -> std::string {
m_pos += m_len; assert(m_stringIndex < m_column.m_strings.size());
if( m_pos < line().size() && line()[m_pos] == '\n' ) assert(m_pos <= m_end);
m_pos += 1; return addIndentAndSuffix(line().substr(m_pos, m_len));
else }
while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
++m_pos;
if( m_pos == line().size() ) { auto operator ++() -> iterator& {
m_pos = 0; m_pos += m_len;
++m_stringIndex; if (m_pos < line().size() && line()[m_pos] == '\n')
} m_pos += 1;
if( m_stringIndex < m_column.m_strings.size() ) else
calcLength(); while (m_pos < line().size() && isWhitespace(line()[m_pos]))
return *this; ++m_pos;
}
auto operator ++(int) -> iterator {
iterator prev( *this );
operator++();
return prev;
}
auto operator ==( iterator const& other ) const -> bool { if (m_pos == line().size()) {
return m_pos = 0;
m_pos == other.m_pos && ++m_stringIndex;
m_stringIndex == other.m_stringIndex && }
&m_column == &other.m_column; if (m_stringIndex < m_column.m_strings.size())
} calcLength();
auto operator !=( iterator const& other ) const -> bool { return *this;
return !operator==( other ); }
} auto operator ++(int) -> iterator {
}; iterator prev(*this);
using const_iterator = iterator; 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& { explicit Column(std::string const& text) { m_strings.push_back(text); }
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;
}
auto width() const -> size_t { return m_width; } auto width(size_t newWidth) -> Column& {
auto begin() const -> iterator { return iterator( *this ); } assert(newWidth > 0);
auto end() const -> iterator { return { *this, m_strings.size() }; } 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 ) { auto width() const -> size_t { return m_width; }
bool first = true; auto begin() const -> iterator { return iterator(*this); }
for( auto line : col ) { auto end() const -> iterator { return { *this, m_strings.size() }; }
if( first )
first = false;
else
os << "\n";
os << line;
}
return os;
}
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 { auto operator + (Column const& other)->Columns;
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
class Spacer : public Column { auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
public: class Spacer : public Column {
explicit Spacer( size_t spaceWidth ) : Column( "" ) {
width( spaceWidth );
}
};
class Columns { public:
std::vector<Column> m_columns; explicit Spacer(size_t spaceWidth) : Column("") {
width(spaceWidth);
}
};
public: class Columns {
std::vector<Column> m_columns;
class iterator { public:
friend Columns;
struct EndTag {};
std::vector<Column> const& m_columns; class iterator {
std::vector<Column::iterator> m_iterators; friend Columns;
size_t m_activeIterators; struct EndTag {};
iterator( Columns const& columns, EndTag ) std::vector<Column> const& m_columns;
: m_columns( columns.m_columns ), std::vector<Column::iterator> m_iterators;
m_activeIterators( 0 ) size_t m_activeIterators;
{
m_iterators.reserve( m_columns.size() );
for( auto const& col : m_columns ) iterator(Columns const& columns, EndTag)
m_iterators.push_back( col.end() ); : m_columns(columns.m_columns),
} m_activeIterators(0) {
m_iterators.reserve(m_columns.size());
public: for (auto const& col : m_columns)
explicit iterator( Columns const& columns ) m_iterators.push_back(col.end());
: m_columns( columns.m_columns ), }
m_activeIterators( m_columns.size() )
{
m_iterators.reserve( m_columns.size() );
for( auto const& col : m_columns ) public:
m_iterators.push_back( col.begin() ); 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 { explicit iterator(Columns const& columns)
return m_iterators == other.m_iterators; : m_columns(columns.m_columns),
} m_activeIterators(m_columns.size()) {
auto operator !=( iterator const& other ) const -> bool { m_iterators.reserve(m_columns.size());
return m_iterators != other.m_iterators;
}
auto operator *() const -> std::string {
std::string row, padding;
for( size_t i = 0; i < m_columns.size(); ++i ) { for (auto const& col : m_columns)
auto width = m_columns[i].width(); m_iterators.push_back(col.begin());
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;
auto begin() const -> iterator { return iterator( *this ); } auto operator ==(iterator const& other) const -> bool {
auto end() const -> iterator { return { *this, iterator::EndTag() }; } 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& { for (size_t i = 0; i < m_columns.size(); ++i) {
m_columns.push_back( col ); auto width = m_columns[i].width();
return *this; if (m_iterators[i] != m_columns[i].end()) {
} std::string col = *m_iterators[i];
auto operator + ( Column const& col ) -> Columns { row += padding + col;
Columns combined = *this; if (col.size() < width)
combined += col; padding = std::string(width - col.size(), ' ');
return combined; 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; auto operator += (Column const& col) -> Columns& {
for( auto line : cols ) { m_columns.push_back(col);
if( first ) return *this;
first = false; }
else auto operator + (Column const& col) -> Columns {
os << "\n"; Columns combined = *this;
os << line; combined += col;
} return combined;
return os; }
}
auto toString() const -> std::string { inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
inline auto Column::operator + ( Column const& other ) -> Columns { bool first = true;
Columns cols; for (auto line : cols) {
cols += *this; if (first)
cols += other; first = false;
return cols; else
} os << "\n";
}}} // namespace Catch::clara::TextFlow 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 #endif // CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
// ----------- end of #include from clara_textflow.hpp ----------- // ----------- end of #include from clara_textflow.hpp -----------
// ........... back in clara.hpp // ........... back in clara.hpp
#include <string>
#include <memory> #include <memory>
#include <set> #include <set>
#include <algorithm> #include <algorithm>

View File

@@ -10,6 +10,9 @@
#include "catch_string_manip.h" #include "catch_string_manip.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_interfaces_reporter.h"
#include <fstream> #include <fstream>
#include <ctime> #include <ctime>
@@ -105,6 +108,18 @@ namespace Catch {
return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
return ParserResult::ok( ParseResultType::Matched ); 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 auto cli
= ExeName( config.processName ) = ExeName( config.processName )
@@ -130,7 +145,7 @@ namespace Catch {
| Opt( config.outputFilename, "filename" ) | Opt( config.outputFilename, "filename" )
["-o"]["--out"] ["-o"]["--out"]
( "output filename" ) ( "output filename" )
| Opt( config.reporterName, "name" ) | Opt( setReporter, "name" )
["-r"]["--reporter"] ["-r"]["--reporter"]
( "reporter to use (defaults to console)" ) ( "reporter to use (defaults to console)" )
| Opt( config.name, "name" ) | Opt( config.name, "name" )

View File

@@ -22,6 +22,10 @@
#include <string> #include <string>
#include <cstdint> #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 { namespace Catch {
struct CaseSensitive { enum Choice { struct CaseSensitive { enum Choice {
@@ -48,10 +52,10 @@ namespace Catch {
line( _line ) line( _line )
{} {}
SourceLineInfo( SourceLineInfo const& other ) = default; SourceLineInfo( SourceLineInfo const& other ) = default;
SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo( SourceLineInfo&& ) noexcept = default;
SourceLineInfo& operator = ( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
bool empty() const noexcept; bool empty() const noexcept;
bool operator == ( SourceLineInfo const& other ) const noexcept; bool operator == ( SourceLineInfo const& other ) const noexcept;
@@ -63,6 +67,11 @@ namespace Catch {
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// 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 // Use this in variadic streaming macros to allow
// >> +StreamEndStop // >> +StreamEndStop
// as well as // as well as

View File

@@ -29,11 +29,11 @@
#ifdef __cplusplus #ifdef __cplusplus
# if __cplusplus >= 201402L # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
# define CATCH_CPP14_OR_GREATER # define CATCH_CPP14_OR_GREATER
# endif # endif
# if __cplusplus >= 201703L # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
# define CATCH_CPP17_OR_GREATER # define CATCH_CPP17_OR_GREATER
# endif # endif
@@ -109,7 +109,14 @@
// Required for some versions of Cygwin to declare gettimeofday // Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# define _BSD_SOURCE # define _BSD_SOURCE
// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
# endif
#endif // __CYGWIN__ #endif // __CYGWIN__
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -129,6 +136,13 @@
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif # 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 #endif // _MSC_VER
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -143,6 +157,12 @@
# define CATCH_INTERNAL_CONFIG_NO_WCHAR # define CATCH_INTERNAL_CONFIG_NO_WCHAR
#endif // __DJGPP__ #endif // __DJGPP__
////////////////////////////////////////////////////////////////////////////////
// Embarcadero C++Build
#if defined(__BORLANDC__)
#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Use of __COUNTER__ is suppressed during code analysis in // Use of __COUNTER__ is suppressed during code analysis in
@@ -154,6 +174,43 @@
#define CATCH_INTERNAL_CONFIG_COUNTER #define CATCH_INTERNAL_CONFIG_COUNTER
#endif #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) #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER # define CATCH_CONFIG_COUNTER
#endif #endif
@@ -173,10 +230,22 @@
# define CATCH_CONFIG_CPP11_TO_STRING # define CATCH_CONFIG_CPP11_TO_STRING
#endif #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) #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 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif #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) #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
#endif #endif
@@ -189,6 +258,10 @@
# define CATCH_CONFIG_DISABLE_EXCEPTIONS # define CATCH_CONFIG_DISABLE_EXCEPTIONS
#endif #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) #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
@@ -212,6 +285,9 @@
#define CATCH_CATCH_ANON(type) catch (type) #define CATCH_CATCH_ANON(type) catch (type)
#endif #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 #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED

View File

@@ -160,7 +160,8 @@ namespace {
private: private:
void setColour( const char* _escapeCode ) { void setColour( const char* _escapeCode ) {
Catch::cout() << '\033' << _escapeCode; getCurrentContext().getConfig()->stream()
<< '\033' << _escapeCode;
} }
}; };

View File

@@ -38,12 +38,9 @@ namespace Catch {
#endif #endif
#ifdef CATCH_TRAP #ifdef CATCH_TRAP
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
#else #else
namespace Catch { #define CATCH_BREAK_INTO_DEBUGGER() []{}()
inline void doNothing() {}
}
#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
#endif #endif
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED #endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED

View File

@@ -10,6 +10,7 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include "catch_stringref.h" #include "catch_stringref.h"
#include "catch_meta.hpp"
#include <iosfwd> #include <iosfwd>
@@ -19,6 +20,7 @@
#pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4018) // more "signed/unsigned mismatch"
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
#pragma warning(disable:4180) // qualifier applied to function type has no meaning #pragma warning(disable:4180) // qualifier applied to function type has no meaning
#pragma warning(disable:4800) // Forcing result to true or false
#endif #endif
namespace Catch { namespace Catch {
@@ -62,6 +64,62 @@ namespace Catch {
m_op( op ), m_op( op ),
m_rhs( rhs ) m_rhs( rhs )
{} {}
template<typename T>
auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename T>
auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<T>::value,
"chained comparisons are not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
}; };
template<typename LhsT> template<typename LhsT>
@@ -74,7 +132,7 @@ namespace Catch {
public: public:
explicit UnaryExpr( LhsT lhs ) explicit UnaryExpr( LhsT lhs )
: ITransientExpression{ false, lhs ? true : false }, : ITransientExpression{ false, static_cast<bool>(lhs) },
m_lhs( lhs ) m_lhs( lhs )
{} {}
}; };
@@ -143,6 +201,20 @@ namespace Catch {
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
} }
template<typename RhsT>
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<RhsT>::value,
"operator&& is not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
template<typename RhsT>
auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
static_assert(always_false<RhsT>::value,
"operator|| is not supported inside assertions, "
"wrap the expression inside parentheses, or decompose it");
}
auto makeUnaryExpr() const -> UnaryExpr<LhsT> { auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
return UnaryExpr<LhsT>{ m_lhs }; return UnaryExpr<LhsT>{ m_lhs };
} }

View File

@@ -67,17 +67,23 @@ namespace Catch {
} }
} }
std::string ExceptionTranslatorRegistry::tryTranslators() const {
if (m_translators.empty()) {
std::rethrow_exception(std::current_exception());
} else {
return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
}
}
#else // ^^ Exceptions are enabled // Exceptions are disabled vv #else // ^^ Exceptions are enabled // Exceptions are disabled vv
std::string ExceptionTranslatorRegistry::translateActiveException() const { std::string ExceptionTranslatorRegistry::translateActiveException() const {
CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
} }
std::string ExceptionTranslatorRegistry::tryTranslators() const {
CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
}
#endif #endif
std::string ExceptionTranslatorRegistry::tryTranslators() const {
if( m_translators.empty() )
std::rethrow_exception(std::current_exception());
else
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
}
} }

View File

@@ -16,35 +16,17 @@ namespace Catch {
IGeneratorTracker::~IGeneratorTracker() {} IGeneratorTracker::~IGeneratorTracker() {}
const char* GeneratorException::what() const noexcept {
return m_msg;
}
namespace Generators { namespace Generators {
GeneratorBase::~GeneratorBase() {} GeneratorUntypedBase::~GeneratorUntypedBase() {}
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ) {
assert( selectionSize <= sourceSize );
std::vector<size_t> indices;
indices.reserve( selectionSize );
std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
std::set<size_t> seen;
// !TBD: improve this algorithm
while( indices.size() < selectionSize ) {
auto index = uid( rng() );
if( seen.insert( index ).second )
indices.push_back( index );
}
return indices;
}
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
return getResultCapture().acquireGeneratorTracker( lineInfo ); return getResultCapture().acquireGeneratorTracker( lineInfo );
} }
template<>
auto all<int>() -> Generator<int> {
return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
}
} // namespace Generators } // namespace Generators
} // namespace Catch } // namespace Catch

View File

@@ -16,8 +16,21 @@
#include <cassert> #include <cassert>
#include <utility> #include <utility>
#include <exception>
namespace Catch { namespace Catch {
class GeneratorException : public std::exception {
const char* const m_msg = "";
public:
GeneratorException(const char* msg):
m_msg(msg)
{}
const char* what() const noexcept override final;
};
namespace Generators { namespace Generators {
// !TBD move this into its own location? // !TBD move this into its own location?
@@ -29,202 +42,312 @@ namespace Generators {
} }
template<typename T> template<typename T>
struct IGenerator { struct IGenerator : GeneratorUntypedBase {
virtual ~IGenerator() {} virtual ~IGenerator() = default;
virtual auto get( size_t index ) const -> T = 0;
// Returns the current element of the generator
//
// \Precondition The generator is either freshly constructed,
// or the last call to `next()` returned true
virtual T const& get() const = 0;
using type = T;
}; };
template<typename T> template<typename T>
class SingleValueGenerator : public IGenerator<T> { class SingleValueGenerator final : public IGenerator<T> {
T m_value; T m_value;
public: public:
SingleValueGenerator( T const& value ) : m_value( value ) {} SingleValueGenerator(T const& value) : m_value( value ) {}
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
auto get( size_t ) const -> T override { T const& get() const override {
return m_value; return m_value;
} }
bool next() override {
return false;
}
}; };
template<typename T> template<typename T>
class FixedValuesGenerator : public IGenerator<T> { class FixedValuesGenerator final : public IGenerator<T> {
std::vector<T> m_values; std::vector<T> m_values;
size_t m_idx = 0;
public: public:
FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
auto get( size_t index ) const -> T override { T const& get() const override {
return m_values[index]; return m_values[m_idx];
}
bool next() override {
++m_idx;
return m_idx < m_values.size();
} }
}; };
template<typename T> template <typename T>
class RangeGenerator : public IGenerator<T> { class GeneratorWrapper final {
T const m_first;
T const m_last;
public:
RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) {
assert( m_last > m_first );
}
auto get( size_t index ) const -> T override {
// ToDo:: introduce a safe cast to catch potential overflows
return static_cast<T>(m_first+index);
}
};
template<typename T>
struct NullGenerator : IGenerator<T> {
auto get( size_t ) const -> T override {
CATCH_INTERNAL_ERROR("A Null Generator is always empty");
}
};
template<typename T>
class Generator {
std::unique_ptr<IGenerator<T>> m_generator; std::unique_ptr<IGenerator<T>> m_generator;
size_t m_size;
public: public:
Generator( size_t size, std::unique_ptr<IGenerator<T>> generator ) GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
: m_generator( std::move( generator ) ), m_generator(std::move(generator))
m_size( size )
{} {}
T const& get() const {
auto size() const -> size_t { return m_size; } return m_generator->get();
auto operator[]( size_t index ) const -> T { }
assert( index < m_size ); bool next() {
return m_generator->get( index ); return m_generator->next();
} }
}; };
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ); template <typename T>
GeneratorWrapper<T> value(T&& value) {
return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
}
template <typename T>
GeneratorWrapper<T> values(std::initializer_list<T> values) {
return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
}
template<typename T> template<typename T>
class GeneratorRandomiser : public IGenerator<T> { class Generators : public IGenerator<T> {
Generator<T> m_baseGenerator; std::vector<GeneratorWrapper<T>> m_generators;
size_t m_current = 0;
std::vector<size_t> m_indices; void populate(GeneratorWrapper<T>&& generator) {
public: m_generators.emplace_back(std::move(generator));
GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems )
: m_baseGenerator( std::move( baseGenerator ) ),
m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
{}
auto get( size_t index ) const -> T override {
return m_baseGenerator[m_indices[index]];
} }
}; void populate(T&& val) {
m_generators.emplace_back(value(std::move(val)));
template<typename T>
struct RequiresASpecialisationFor;
template<typename T>
auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); }
template<>
auto all<int>() -> Generator<int>;
template<typename T>
auto range( T const& first, T const& last ) -> Generator<T> {
return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) );
}
template<typename T>
auto random( T const& first, T const& last ) -> Generator<T> {
auto gen = range( first, last );
auto size = gen.size();
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
}
template<typename T>
auto random( size_t size ) -> Generator<T> {
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
}
template<typename T>
auto values( std::initializer_list<T> values ) -> Generator<T> {
return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) );
}
template<typename T>
auto value( T const& val ) -> Generator<T> {
return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
}
template<typename T>
auto as() -> Generator<T> {
return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
}
template<typename... Ts>
auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> {
return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
}
template<typename T>
struct Generators : GeneratorBase {
std::vector<Generator<T>> m_generators;
using type = T;
Generators() : GeneratorBase( 0 ) {}
void populate( T&& val ) {
m_size += 1;
m_generators.emplace_back( value( std::move( val ) ) );
} }
template<typename U> template<typename U>
void populate( U&& val ) { void populate(U&& val) {
populate( T( std::move( val ) ) ); populate(T(std::move(val)));
} }
void populate( Generator<T>&& generator ) {
m_size += generator.size();
m_generators.emplace_back( std::move( generator ) );
}
template<typename U, typename... Gs> template<typename U, typename... Gs>
void populate( U&& valueOrGenerator, Gs... moreGenerators ) { void populate(U&& valueOrGenerator, Gs... moreGenerators) {
populate( std::forward<U>( valueOrGenerator ) ); populate(std::forward<U>(valueOrGenerator));
populate( std::forward<Gs>( moreGenerators )... ); populate(std::forward<Gs>(moreGenerators)...);
} }
auto operator[]( size_t index ) const -> T { public:
size_t sizes = 0; template <typename... Gs>
for( auto const& gen : m_generators ) { Generators(Gs... moreGenerators) {
auto localIndex = index-sizes; m_generators.reserve(sizeof...(Gs));
sizes += gen.size(); populate(std::forward<Gs>(moreGenerators)...);
if( index < sizes ) }
return gen[localIndex];
T const& get() const override {
return m_generators[m_current].get();
}
bool next() override {
if (m_current >= m_generators.size()) {
return false;
} }
CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')'); const bool current_status = m_generators[m_current].next();
if (!current_status) {
++m_current;
}
return m_current < m_generators.size();
} }
}; };
template<typename... Ts>
GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
return values<std::tuple<Ts...>>( tuples );
}
// Tag type to signal that a generator sequence should convert arguments to a specific type
template <typename T>
struct as {};
template<typename T, typename... Gs> template<typename T, typename... Gs>
auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> { auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
Generators<T> generators; return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
generators.m_generators.reserve( 1+sizeof...(Gs) );
generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
return generators;
} }
template<typename T> template<typename T>
auto makeGenerators( Generator<T>&& generator ) -> Generators<T> { auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
Generators<T> generators; return Generators<T>(std::move(generator));
generators.populate( std::move( generator ) );
return generators;
} }
template<typename T, typename... Gs> template<typename T, typename... Gs>
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> { auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
} }
template<typename T, typename U, typename... Gs> template<typename T, typename U, typename... Gs>
auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators<T> { auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
} }
template <typename T>
class TakeGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
size_t m_returned = 0;
size_t m_target;
public:
TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
m_generator(std::move(generator)),
m_target(target)
{
assert(target != 0 && "Empty generators are not allowed");
}
T const& get() const override {
return m_generator.get();
}
bool next() override {
++m_returned;
if (m_returned >= m_target) {
return false;
}
const auto success = m_generator.next();
// If the underlying generator does not contain enough values
// then we cut short as well
if (!success) {
m_returned = m_target;
}
return success;
}
};
template <typename T>
GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
}
template <typename T, typename Predicate>
class FilterGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
Predicate m_predicate;
public:
template <typename P = Predicate>
FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
m_generator(std::move(generator)),
m_predicate(std::forward<P>(pred))
{
if (!m_predicate(m_generator.get())) {
// It might happen that there are no values that pass the
// filter. In that case we throw an exception.
auto has_initial_value = next();
if (!has_initial_value) {
Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
}
}
}
T const& get() const override {
return m_generator.get();
}
bool next() override {
bool success = m_generator.next();
if (!success) {
return false;
}
while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
return success;
}
};
template <typename T, typename Predicate>
GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
}
template <typename T>
class RepeatGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
mutable std::vector<T> m_returned;
size_t m_target_repeats;
size_t m_current_repeat = 0;
size_t m_repeat_index = 0;
public:
RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
m_generator(std::move(generator)),
m_target_repeats(repeats)
{
assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
}
T const& get() const override {
if (m_current_repeat == 0) {
m_returned.push_back(m_generator.get());
return m_returned.back();
}
return m_returned[m_repeat_index];
}
bool next() override {
// There are 2 basic cases:
// 1) We are still reading the generator
// 2) We are reading our own cache
// In the first case, we need to poke the underlying generator.
// If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
if (m_current_repeat == 0) {
const auto success = m_generator.next();
if (!success) {
++m_current_repeat;
}
return m_current_repeat < m_target_repeats;
}
// In the second case, we need to move indices forward and check that we haven't run up against the end
++m_repeat_index;
if (m_repeat_index == m_returned.size()) {
m_repeat_index = 0;
++m_current_repeat;
}
return m_current_repeat < m_target_repeats;
}
};
template <typename T>
GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
}
template <typename T, typename U, typename Func>
class MapGenerator : public IGenerator<T> {
// TBD: provide static assert for mapping function, for friendly error message
GeneratorWrapper<U> m_generator;
Func m_function;
// To avoid returning dangling reference, we have to save the values
T m_cache;
public:
template <typename F2 = Func>
MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
m_generator(std::move(generator)),
m_function(std::forward<F2>(function)),
m_cache(m_function(m_generator.get()))
{}
T const& get() const override {
return m_cache;
}
bool next() override {
const auto success = m_generator.next();
if (success) {
m_cache = m_function(m_generator.get());
}
return success;
}
};
template <typename T, typename U, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
);
}
template <typename T, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
);
}
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
@@ -232,15 +355,16 @@ namespace Generators {
// Note: The type after -> is weird, because VS2015 cannot parse // Note: The type after -> is weird, because VS2015 cannot parse
// the expression used in the typedef inside, when it is in // the expression used in the typedef inside, when it is in
// return type. Yeah, ¯\_(ツ)_/¯ // return type. Yeah, ¯\_(ツ)_/¯
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) { auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
using UnderlyingType = typename decltype(generatorExpression())::type; using UnderlyingType = typename decltype(generatorExpression())::type;
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
if( !tracker.hasGenerator() ) if (!tracker.hasGenerator()) {
tracker.setGenerator( pf::make_unique<Generators<UnderlyingType>>( generatorExpression() ) ); tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
}
auto const& generator = static_cast<Generators<UnderlyingType> const&>( *tracker.getGenerator() ); auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
return generator[tracker.getIndex()]; return generator.get();
} }
} // namespace Generators } // namespace Generators

View File

@@ -13,16 +13,17 @@
namespace Catch { namespace Catch {
namespace Generators { namespace Generators {
class GeneratorBase { class GeneratorUntypedBase {
protected:
size_t m_size = 0;
public: public:
GeneratorBase( size_t size ) : m_size( size ) {} GeneratorUntypedBase() = default;
virtual ~GeneratorBase(); virtual ~GeneratorUntypedBase();
auto size() const -> size_t { return m_size; } // Attempts to move the generator to the next element
//
// Returns true iff the move succeeded (and a valid element
// can be retrieved).
virtual bool next() = 0;
}; };
using GeneratorBasePtr = std::unique_ptr<GeneratorBase>; using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
} // namespace Generators } // namespace Generators
@@ -31,7 +32,6 @@ namespace Catch {
virtual auto hasGenerator() const -> bool = 0; virtual auto hasGenerator() const -> bool = 0;
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
virtual auto getIndex() const -> std::size_t = 0;
}; };
} // namespace Catch } // namespace Catch

View File

@@ -9,7 +9,6 @@
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
#include <vector> #include <vector>
#include <memory>
namespace Catch { namespace Catch {
@@ -20,8 +19,6 @@ namespace Catch {
virtual ~ITestInvoker(); virtual ~ITestInvoker();
}; };
using ITestCasePtr = std::shared_ptr<ITestInvoker>;
class TestCase; class TestCase;
struct IConfig; struct IConfig;

View File

@@ -6,6 +6,7 @@
*/ */
#include "catch_leak_detector.h" #include "catch_leak_detector.h"
#include "catch_interfaces_registry_hub.h"
#ifdef CATCH_CONFIG_WINDOWS_CRTDBG #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
@@ -30,3 +31,7 @@ namespace Catch {
Catch::LeakDetector::LeakDetector() {} Catch::LeakDetector::LeakDetector() {}
#endif #endif
Catch::LeakDetector::~LeakDetector() {
Catch::cleanUp();
}

View File

@@ -11,6 +11,7 @@ namespace Catch {
struct LeakDetector { struct LeakDetector {
LeakDetector(); LeakDetector();
~LeakDetector();
}; };
} }

View File

@@ -124,7 +124,7 @@ namespace Catch {
return tagCounts.size(); return tagCounts.size();
} }
std::size_t listReporters( Config const& /*config*/ ) { std::size_t listReporters() {
Catch::cout() << "Available reporters:\n"; Catch::cout() << "Available reporters:\n";
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
std::size_t maxNameLen = 0; std::size_t maxNameLen = 0;
@@ -155,7 +155,7 @@ namespace Catch {
if( config.listTags() ) if( config.listTags() )
listedCount = listedCount.valueOr(0) + listTags( config ); listedCount = listedCount.valueOr(0) + listTags( config );
if( config.listReporters() ) if( config.listReporters() )
listedCount = listedCount.valueOr(0) + listReporters( config ); listedCount = listedCount.valueOr(0) + listReporters();
return listedCount; return listedCount;
} }

View File

@@ -29,7 +29,7 @@ namespace Catch {
std::size_t listTags( Config const& config ); std::size_t listTags( Config const& config );
std::size_t listReporters( Config const& /*config*/ ); std::size_t listReporters();
Option<std::size_t> list( Config const& config ); Option<std::size_t> list( Config const& config );

View File

@@ -43,10 +43,6 @@ namespace Matchers {
struct MatcherMethod { struct MatcherMethod {
virtual bool match( ObjectT const& arg ) const = 0; virtual bool match( ObjectT const& arg ) const = 0;
}; };
template<typename PtrT>
struct MatcherMethod<PtrT*> {
virtual bool match( PtrT* arg ) const = 0;
};
#ifdef __clang__ #ifdef __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop

View File

@@ -7,6 +7,7 @@
#include "catch_matchers_floating.h" #include "catch_matchers_floating.h"
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_polyfills.hpp"
#include "catch_to_string.hpp" #include "catch_to_string.hpp"
#include "catch_tostring.h" #include "catch_tostring.h"
@@ -57,7 +58,7 @@ template <typename FP>
bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) { bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
// Comparison with NaN should always be false. // Comparison with NaN should always be false.
// This way we can rule it out before getting into the ugly details // This way we can rule it out before getting into the ugly details
if (std::isnan(lhs) || std::isnan(rhs)) { if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
return false; return false;
} }

View File

@@ -124,7 +124,7 @@ namespace Matchers {
auto lfirst = m_target.begin(), llast = m_target.end(); auto lfirst = m_target.begin(), llast = m_target.end();
auto rfirst = vec.begin(), rlast = vec.end(); auto rfirst = vec.begin(), rlast = vec.end();
// Cut common prefix to optimize checking of permuted parts // Cut common prefix to optimize checking of permuted parts
while (lfirst != llast && *lfirst != *rfirst) { while (lfirst != llast && *lfirst == *rfirst) {
++lfirst; ++rfirst; ++lfirst; ++rfirst;
} }
if (lfirst == llast) { if (lfirst == llast) {

View File

@@ -11,6 +11,7 @@
#include "catch_uncaught_exceptions.h" #include "catch_uncaught_exceptions.h"
#include <cassert> #include <cassert>
#include <stack>
namespace Catch { namespace Catch {
@@ -60,19 +61,48 @@ namespace Catch {
Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
auto start = std::string::npos; auto trimmed = [&] (size_t start, size_t end) {
for( size_t pos = 0; pos <= names.size(); ++pos ) { while (names[start] == ',' || isspace(names[start])) {
++start;
}
while (names[end] == ',' || isspace(names[end])) {
--end;
}
return names.substr(start, end - start + 1);
};
size_t start = 0;
std::stack<char> openings;
for (size_t pos = 0; pos < names.size(); ++pos) {
char c = names[pos]; char c = names[pos];
if( pos == names.size() || c == ' ' || c == '\t' || c == ',' || c == ']' ) { switch (c) {
if( start != std::string::npos ) { case '[':
m_messages.push_back( MessageInfo( macroName, lineInfo, resultType ) ); case '{':
m_messages.back().message = names.substr( start, pos-start) + " := "; case '(':
start = std::string::npos; // It is basically impossible to disambiguate between
// comparison and start of template args in this context
// case '<':
openings.push(c);
break;
case ']':
case '}':
case ')':
// case '>':
openings.pop();
break;
case ',':
if (start != pos && openings.size() == 0) {
m_messages.emplace_back(macroName, lineInfo, resultType);
m_messages.back().message = trimmed(start, pos);
m_messages.back().message += " := ";
start = pos;
} }
} }
else if( c != '[' && c != ']' && start == std::string::npos )
start = pos;
} }
assert(openings.size() == 0 && "Mismatched openings");
m_messages.emplace_back(macroName, lineInfo, resultType);
m_messages.back().message = trimmed(start, names.size() - 1);
m_messages.back().message += " := ";
} }
Capturer::~Capturer() { Capturer::~Capturer() {
if ( !uncaught_exceptions() ){ if ( !uncaught_exceptions() ){
@@ -82,7 +112,7 @@ namespace Catch {
} }
} }
void Capturer::captureValue( size_t index, StringRef value ) { void Capturer::captureValue( size_t index, std::string const& value ) {
assert( index < m_messages.size() ); assert( index < m_messages.size() );
m_messages[index].message += value; m_messages[index].message += value;
m_resultCapture.pushScopedMessage( m_messages[index] ); m_resultCapture.pushScopedMessage( m_messages[index] );

View File

@@ -77,16 +77,16 @@ namespace Catch {
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
~Capturer(); ~Capturer();
void captureValue( size_t index, StringRef value ); void captureValue( size_t index, std::string const& value );
template<typename T> template<typename T>
void captureValues( size_t index, T&& value ) { void captureValues( size_t index, T const& value ) {
captureValue( index, Catch::Detail::stringify( value ) ); captureValue( index, Catch::Detail::stringify( value ) );
} }
template<typename T, typename... Ts> template<typename T, typename... Ts>
void captureValues( size_t index, T&& value, Ts&&... values ) { void captureValues( size_t index, T const& value, Ts const&... values ) {
captureValues( index, value ); captureValue( index, Catch::Detail::stringify(value) );
captureValues( index+1, values... ); captureValues( index+1, values... );
} }
}; };

View File

@@ -0,0 +1,81 @@
/*
* Created by Jozef on 02/12/2018.
* Copyright 2018 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_META_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_META_HPP_INCLUDED
#include <type_traits>
template< typename... >
struct TypeList{};
template< typename... >
struct append;
template< template<typename...> class L1
, typename...E1
, template<typename...> class L2
, typename...E2
>
struct append< L1<E1...>, L2<E2...> >
{
using type = L1<E1..., E2...>;
};
template< template<typename...> class L1
, typename...E1
, template<typename...> class L2
, typename...E2
, typename...Rest
>
struct append< L1<E1...>, L2<E2...>, Rest...>
{
using type = typename append< L1<E1..., E2...>, Rest... >::type;
};
template< template<typename...> class
, typename...
>
struct rewrap;
template< template<typename...> class Container
, template<typename...> class List
, typename...elems
>
struct rewrap<Container, List<elems...>>
{
using type = TypeList< Container< elems... > >;
};
template< template<typename...> class Container
, template<typename...> class List
, class...Elems
, typename...Elements>
struct rewrap<Container, List<Elems...>, Elements...>
{
using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;
};
template< template<typename...> class...Containers >
struct combine
{
template< typename...Types >
struct with_types
{
template< template <typename...> class Final >
struct into
{
using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;
};
};
};
template<typename T>
struct always_false : std::false_type {};
#endif // TWOBLUECUBES_CATCH_META_HPP_INCLUDED

View File

@@ -0,0 +1,31 @@
/*
* Created by Martin on 17/11/2017.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch_polyfills.hpp"
#include <cmath>
namespace Catch {
#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
bool isnan(float f) {
return std::isnan(f);
}
bool isnan(double d) {
return std::isnan(d);
}
#else
// For now we only use this for embarcadero
bool isnan(float f) {
return std::_isnan(f);
}
bool isnan(double d) {
return std::_isnan(d);
}
#endif
} // end namespace Catch

View File

@@ -0,0 +1,15 @@
/*
* Created by Martin on 17/11/2017.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_POLYFILLS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_POLYFILLS_HPP_INCLUDED
namespace Catch {
bool isnan(float f);
bool isnan(double d);
}
#endif // TWOBLUECUBES_CATCH_POLYFILLS_HPP_INCLUDED

View File

@@ -0,0 +1,79 @@
/*
* Created by Jozef on 12/11/2018.
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED
#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
// MSVC needs more evaluations
#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
#else
#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
#endif
#define CATCH_REC_END(...)
#define CATCH_REC_OUT
#define CATCH_EMPTY()
#define CATCH_DEFER(id) id CATCH_EMPTY()
#define CATCH_REC_GET_END2() 0, CATCH_REC_END
#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
// and passes userdata as the first parameter to each invocation,
// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
#else
// MSVC is adding extra space and needs more calls to properly remove ()
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
#endif
#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)>
#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
#endif // TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED

View File

@@ -14,7 +14,6 @@ namespace Catch {
namespace Generators { namespace Generators {
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
size_t m_index = static_cast<size_t>( -1 );
GeneratorBasePtr m_generator; GeneratorBasePtr m_generator;
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
@@ -28,7 +27,7 @@ namespace Catch {
ITracker& currentTracker = ctx.currentTracker(); ITracker& currentTracker = ctx.currentTracker();
if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
assert( childTracker ); assert( childTracker );
assert( childTracker->isIndexTracker() ); assert( childTracker->isGeneratorTracker() );
tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
} }
else { else {
@@ -37,28 +36,24 @@ namespace Catch {
} }
if( !ctx.completedCycle() && !tracker->isComplete() ) { if( !ctx.completedCycle() && !tracker->isComplete() ) {
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
tracker->moveNext();
tracker->open(); tracker->open();
} }
return *tracker; return *tracker;
} }
void moveNext() {
m_index++;
m_children.clear();
}
// TrackerBase interface // TrackerBase interface
bool isIndexTracker() const override { return true; } bool isGeneratorTracker() const override { return true; }
auto hasGenerator() const -> bool override { auto hasGenerator() const -> bool override {
return !!m_generator; return !!m_generator;
} }
void close() override { void close() override {
TrackerBase::close(); TrackerBase::close();
if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 ) // Generator interface only finds out if it has another item on atual move
if (m_runState == CompletedSuccessfully && m_generator->next()) {
m_children.clear();
m_runState = Executing; m_runState = Executing;
}
} }
// IGeneratorTracker interface // IGeneratorTracker interface
@@ -68,9 +63,6 @@ namespace Catch {
void setGenerator( GeneratorBasePtr&& generator ) override { void setGenerator( GeneratorBasePtr&& generator ) override {
m_generator = std::move( generator ); m_generator = std::move( generator );
} }
auto getIndex() const -> size_t override {
return m_index;
}
}; };
GeneratorTracker::~GeneratorTracker() {} GeneratorTracker::~GeneratorTracker() {}
} }
@@ -313,7 +305,7 @@ namespace Catch {
} }
bool RunContext::aborting() const { bool RunContext::aborting() const {
return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter()); return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
} }
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {

View File

@@ -128,7 +128,7 @@ namespace Catch {
TestRunInfo m_runInfo; TestRunInfo m_runInfo;
IMutableContext& m_context; IMutableContext& m_context;
TestCase const* m_activeTestCase = nullptr; TestCase const* m_activeTestCase = nullptr;
ITracker* m_testCaseTracker; ITracker* m_testCaseTracker = nullptr;
Option<AssertionResult> m_lastResult; Option<AssertionResult> m_lastResult;
IConfigPtr m_config; IConfigPtr m_config;

View File

@@ -42,20 +42,23 @@ namespace Catch {
return createReporter(config->getReporterName(), config); return createReporter(config->getReporterName(), config);
} }
auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter); // On older platforms, returning std::unique_ptr<ListeningReporter>
// when the return type is std::unique_ptr<IStreamingReporter>
// doesn't compile without a std::move call. However, this causes
// a warning on newer platforms. Thus, we have to work around
// it a bit and downcast the pointer manually.
auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
auto& multi = static_cast<ListeningReporter&>(*ret);
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
for (auto const& listener : listeners) { for (auto const& listener : listeners) {
multi->addListener(listener->create(Catch::ReporterConfig(config))); multi.addListener(listener->create(Catch::ReporterConfig(config)));
} }
multi->addReporter(createReporter(config->getReporterName(), config)); multi.addReporter(createReporter(config->getReporterName(), config));
return std::move(multi); return ret;
} }
Catch::Totals runTests(std::shared_ptr<Config> const& config) { Catch::Totals runTests(std::shared_ptr<Config> const& config) {
// FixMe: Add listeners in order first, then add reporters.
auto reporter = makeReporter(config); auto reporter = makeReporter(config);
RunContext context(config, std::move(reporter)); RunContext context(config, std::move(reporter));
@@ -185,22 +188,8 @@ namespace Catch {
return 0; return 0;
} }
void Session::useConfigData( ConfigData const& configData ) {
m_configData = configData;
m_config.reset();
}
int Session::run( int argc, char* argv[] ) {
if( m_startupExceptions )
return 1;
int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 )
returnCode = run();
return returnCode;
}
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int Session::run( int argc, wchar_t* const argv[] ) { int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
char **utf8Argv = new char *[ argc ]; char **utf8Argv = new char *[ argc ];
@@ -212,7 +201,7 @@ namespace Catch {
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
} }
int returnCode = run( argc, utf8Argv ); int returnCode = applyCommandLine( argc, utf8Argv );
for ( int i = 0; i < argc; ++i ) for ( int i = 0; i < argc; ++i )
delete [] utf8Argv[ i ]; delete [] utf8Argv[ i ];
@@ -222,6 +211,12 @@ namespace Catch {
return returnCode; return returnCode;
} }
#endif #endif
void Session::useConfigData( ConfigData const& configData ) {
m_configData = configData;
m_config.reset();
}
int Session::run() { int Session::run() {
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before starting" << std::endl; Catch::cout() << "...waiting for enter/ return before starting" << std::endl;

View File

@@ -26,13 +26,22 @@ namespace Catch {
void libIdentify(); void libIdentify();
int applyCommandLine( int argc, char const * const * argv ); int applyCommandLine( int argc, char const * const * argv );
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int applyCommandLine( int argc, wchar_t const * const * argv );
#endif
void useConfigData( ConfigData const& configData ); void useConfigData( ConfigData const& configData );
int run( int argc, char* argv[] ); template<typename CharT>
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) int run(int argc, CharT const * const argv[]) {
int run( int argc, wchar_t* const argv[] ); if (m_startupExceptions)
#endif return 1;
int returnCode = applyCommandLine(argc, argv);
if (returnCode == 0)
returnCode = run();
return returnCode;
}
int run(); int run();
clara::Parser const& cli() const; clara::Parser const& cli() const;

View File

@@ -13,8 +13,6 @@
namespace Catch { namespace Catch {
class StringData;
/// A non-owning string class (similar to the forthcoming std::string_view) /// A non-owning string class (similar to the forthcoming std::string_view)
/// Note that, because a StringRef may be a substring of another string, /// Note that, because a StringRef may be a substring of another string,
/// it may not be null terminated. c_str() must return a null terminated /// it may not be null terminated. c_str() must return a null terminated

View File

@@ -16,10 +16,11 @@
# pragma clang diagnostic ignored "-Wcovered-switch-default" # pragma clang diagnostic ignored "-Wcovered-switch-default"
# endif # endif
#elif defined __GNUC__ #elif defined __GNUC__
// GCC likes to warn on REQUIREs, and we cannot suppress them // Because REQUIREs trigger GCC's -Wparentheses, and because still
// locally because g++'s support for _Pragma is lacking in older, // supported version of g++ have only buggy support for _Pragmas,
// still supported, versions // Wparentheses have to be suppressed globally.
# pragma GCC diagnostic ignored "-Wparentheses" # pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic ignored "-Wpadded" # pragma GCC diagnostic ignored "-Wpadded"

View File

@@ -121,7 +121,7 @@ namespace TestCaseTracking {
} }
bool TrackerBase::isSectionTracker() const { return false; } bool TrackerBase::isSectionTracker() const { return false; }
bool TrackerBase::isIndexTracker() const { return false; } bool TrackerBase::isGeneratorTracker() const { return false; }
void TrackerBase::open() { void TrackerBase::open() {
m_runState = Executing; m_runState = Executing;
@@ -190,6 +190,17 @@ namespace TestCaseTracking {
} }
} }
bool SectionTracker::isComplete() const {
bool complete = true;
if ((m_filters.empty() || m_filters[0] == "") ||
std::find(m_filters.begin(), m_filters.end(),
m_nameAndLocation.name) != m_filters.end())
complete = TrackerBase::isComplete();
return complete;
}
bool SectionTracker::isSectionTracker() const { return true; } bool SectionTracker::isSectionTracker() const { return true; }
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
@@ -227,55 +238,11 @@ namespace TestCaseTracking {
m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
} }
IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
: TrackerBase( nameAndLocation, ctx, parent ),
m_size( size )
{}
bool IndexTracker::isIndexTracker() const { return true; }
IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
std::shared_ptr<IndexTracker> tracker;
ITracker& currentTracker = ctx.currentTracker();
if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
assert( childTracker );
assert( childTracker->isIndexTracker() );
tracker = std::static_pointer_cast<IndexTracker>( childTracker );
}
else {
tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, &currentTracker, size );
currentTracker.addChild( tracker );
}
if( !ctx.completedCycle() && !tracker->isComplete() ) {
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
tracker->moveNext();
tracker->open();
}
return *tracker;
}
int IndexTracker::index() const { return m_index; }
void IndexTracker::moveNext() {
m_index++;
m_children.clear();
}
void IndexTracker::close() {
TrackerBase::close();
if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
m_runState = Executing;
}
} // namespace TestCaseTracking } // namespace TestCaseTracking
using TestCaseTracking::ITracker; using TestCaseTracking::ITracker;
using TestCaseTracking::TrackerContext; using TestCaseTracking::TrackerContext;
using TestCaseTracking::SectionTracker; using TestCaseTracking::SectionTracker;
using TestCaseTracking::IndexTracker;
} // namespace Catch } // namespace Catch

View File

@@ -54,7 +54,7 @@ namespace TestCaseTracking {
// Debug/ checking // Debug/ checking
virtual bool isSectionTracker() const = 0; virtual bool isSectionTracker() const = 0;
virtual bool isIndexTracker() const = 0; virtual bool isGeneratorTracker() const = 0;
}; };
class TrackerContext { class TrackerContext {
@@ -120,7 +120,7 @@ namespace TestCaseTracking {
void openChild() override; void openChild() override;
bool isSectionTracker() const override; bool isSectionTracker() const override;
bool isIndexTracker() const override; bool isGeneratorTracker() const override;
void open(); void open();
@@ -140,6 +140,8 @@ namespace TestCaseTracking {
bool isSectionTracker() const override; bool isSectionTracker() const override;
bool isComplete() const override;
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
void tryOpen(); void tryOpen();
@@ -148,28 +150,11 @@ namespace TestCaseTracking {
void addNextFilters( std::vector<std::string> const& filters ); void addNextFilters( std::vector<std::string> const& filters );
}; };
class IndexTracker : public TrackerBase {
int m_size;
int m_index = -1;
public:
IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size );
bool isIndexTracker() const override;
void close() override;
static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size );
int index() const;
void moveNext();
};
} // namespace TestCaseTracking } // namespace TestCaseTracking
using TestCaseTracking::ITracker; using TestCaseTracking::ITracker;
using TestCaseTracking::TrackerContext; using TestCaseTracking::TrackerContext;
using TestCaseTracking::SectionTracker; using TestCaseTracking::SectionTracker;
using TestCaseTracking::IndexTracker;
} // namespace Catch } // namespace Catch

View File

@@ -12,6 +12,9 @@
#include "catch_interfaces_testcase.h" #include "catch_interfaces_testcase.h"
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#include "catch_stringref.h" #include "catch_stringref.h"
#include "catch_type_traits.hpp"
#include "catch_preprocessor.hpp"
#include "catch_meta.hpp"
namespace Catch { namespace Catch {
@@ -47,22 +50,28 @@ struct AutoReg : NonCopyable {
} // end namespace Catch } // end namespace Catch
#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
#if defined(CATCH_CONFIG_DISABLE) #if defined(CATCH_CONFIG_DISABLE)
#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
static void TestName() static void TestName()
#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
namespace{ \ namespace{ \
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
void test(); \ void test(); \
}; \ }; \
} \ } \
void TestName::test() void TestName::test()
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... ) \
template<typename TestType> \
static void TestName()
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
namespace{ \
template<typename TestType> \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
void test(); \
}; \
} \
template<typename TestType> \
void TestName::test()
#endif #endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -85,7 +94,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ \ namespace{ \
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
void test(); \ void test(); \
}; \ }; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
@@ -101,5 +110,142 @@ struct AutoReg : NonCopyable {
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
template<typename TestType> \
static void TestFunc();\
namespace {\
template<typename...Types> \
struct TestName{\
template<typename...Ts> \
TestName(Ts...names){\
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
using expander = int[];\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
}\
};\
INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \
}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
template<typename TestType> \
static void TestFunc()
#if defined(CATCH_CPP17_OR_GREATER)
#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case");
#else
#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case");
#endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ )
#else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
#endif
#define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\
return 0;\
}();
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
template<typename TestType> static void TestFuncName(); \
namespace { \
template<typename... Types> \
struct TestName { \
TestName() { \
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \
int index = 0; \
using expander = int[]; \
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + Catch::StringMaker<int>::convert(index++), Tags } ), 0)... };/* NOLINT */ \
} \
}; \
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
using TestInit = combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \
::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \
TestInit(); \
return 0; \
}(); \
} \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
template<typename TestType> \
static void TestFuncName()
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__)
#else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
#endif
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ \
template<typename TestType> \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
void test();\
};\
template<typename...Types> \
struct TestNameClass{\
template<typename...Ts> \
TestNameClass(Ts...names){\
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
using expander = int[];\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
}\
};\
INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\
}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
template<typename TestType> \
void TestName<TestType>::test()
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ )
#else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
#endif
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
template<typename TestType> \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
void test();\
};\
namespace {\
template<typename...Types>\
struct TestNameClass{\
TestNameClass(){\
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
int index = 0;\
using expander = int[];\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + Catch::StringMaker<int>::convert(index++), Tags } ), 0)... };/* NOLINT */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
using TestInit = combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\
::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\
TestInit();\
return 0;\
}(); \
}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
template<typename TestType> \
void TestName<TestType>::test()
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ )
#else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) )
#endif
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED

View File

@@ -40,7 +40,7 @@ namespace Catch {
// is terrible and we should move on. // is terrible and we should move on.
// TBD: How to signal that the measured resolution is probably wrong? // TBD: How to signal that the measured resolution is probably wrong?
if (ticks > startTime + 3 * nanosecondsInSecond) { if (ticks > startTime + 3 * nanosecondsInSecond) {
return sum / i; return sum / ( i + 1u );
} }
} }

View File

@@ -20,6 +20,7 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include "catch_interfaces_config.h" #include "catch_interfaces_config.h"
#include "catch_context.h" #include "catch_context.h"
#include "catch_polyfills.hpp"
#include <cmath> #include <cmath>
#include <iomanip> #include <iomanip>
@@ -68,7 +69,7 @@ namespace Detail {
template<typename T> template<typename T>
std::string fpToString( T value, int precision ) { std::string fpToString( T value, int precision ) {
if (std::isnan(value)) { if (Catch::isnan(value)) {
return "nan"; return "nan";
} }
@@ -116,14 +117,9 @@ std::string StringMaker<std::string>::convert(const std::string& str) {
return s; return s;
} }
#ifdef CATCH_CONFIG_WCHAR #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { std::string StringMaker<std::string_view>::convert(std::string_view str) {
std::string s; return ::Catch::Detail::stringify(std::string{ str });
s.reserve(wstr.size());
for (auto c : wstr) {
s += (c <= 0xff) ? static_cast<char>(c) : '?';
}
return ::Catch::Detail::stringify(s);
} }
#endif #endif
@@ -141,7 +137,23 @@ std::string StringMaker<char*>::convert(char* str) {
return{ "{null string}" }; return{ "{null string}" };
} }
} }
#ifdef CATCH_CONFIG_WCHAR #ifdef CATCH_CONFIG_WCHAR
std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
std::string s;
s.reserve(wstr.size());
for (auto c : wstr) {
s += (c <= 0xff) ? static_cast<char>(c) : '?';
}
return ::Catch::Detail::stringify(s);
}
# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
return StringMaker<std::wstring>::convert(std::wstring(str));
}
# endif
std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
if (str) { if (str) {
return ::Catch::Detail::stringify(std::wstring{ str }); return ::Catch::Detail::stringify(std::wstring{ str });
@@ -194,7 +206,7 @@ std::string StringMaker<bool>::convert(bool b) {
return b ? "true" : "false"; return b ? "true" : "false";
} }
std::string StringMaker<char>::convert(char value) { std::string StringMaker<signed char>::convert(signed char value) {
if (value == '\r') { if (value == '\r') {
return "'\\r'"; return "'\\r'";
} else if (value == '\f') { } else if (value == '\f') {
@@ -211,8 +223,8 @@ std::string StringMaker<char>::convert(char value) {
return chstr; return chstr;
} }
} }
std::string StringMaker<signed char>::convert(signed char c) { std::string StringMaker<char>::convert(char c) {
return ::Catch::Detail::stringify(static_cast<char>(c)); return ::Catch::Detail::stringify(static_cast<signed char>(c));
} }
std::string StringMaker<unsigned char>::convert(unsigned char c) { std::string StringMaker<unsigned char>::convert(unsigned char c) {
return ::Catch::Detail::stringify(static_cast<char>(c)); return ::Catch::Detail::stringify(static_cast<char>(c));

View File

@@ -16,6 +16,10 @@
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#include "catch_stream.h" #include "catch_stream.h"
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
#include <string_view>
#endif
#ifdef __OBJC__ #ifdef __OBJC__
#include "catch_objc_arc.hpp" #include "catch_objc_arc.hpp"
#endif #endif
@@ -25,15 +29,7 @@
#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
#endif #endif
// 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 { namespace Catch {
// Bring in operator<< from global namespace into Catch namespace
using ::operator<<;
namespace Detail { namespace Detail {
extern const std::string unprintableString; extern const std::string unprintableString;
@@ -152,10 +148,11 @@ namespace Catch {
struct StringMaker<std::string> { struct StringMaker<std::string> {
static std::string convert(const std::string& str); static std::string convert(const std::string& str);
}; };
#ifdef CATCH_CONFIG_WCHAR
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
template<> template<>
struct StringMaker<std::wstring> { struct StringMaker<std::string_view> {
static std::string convert(const std::wstring& wstr); static std::string convert(std::string_view str);
}; };
#endif #endif
@@ -169,6 +166,18 @@ namespace Catch {
}; };
#ifdef CATCH_CONFIG_WCHAR #ifdef CATCH_CONFIG_WCHAR
template<>
struct StringMaker<std::wstring> {
static std::string convert(const std::wstring& wstr);
};
# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
template<>
struct StringMaker<std::wstring_view> {
static std::string convert(std::wstring_view str);
};
# endif
template<> template<>
struct StringMaker<wchar_t const *> { struct StringMaker<wchar_t const *> {
static std::string convert(wchar_t const * str); static std::string convert(wchar_t const * str);
@@ -337,7 +346,9 @@ namespace Catch {
#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
#endif #endif
// Separate std::pair specialization // Separate std::pair specialization
@@ -359,6 +370,24 @@ namespace Catch {
} }
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
#include <optional>
namespace Catch {
template<typename T>
struct StringMaker<std::optional<T> > {
static std::string convert(const std::optional<T>& optional) {
ReusableStringStream rss;
if (optional.has_value()) {
rss << ::Catch::Detail::stringify(*optional);
} else {
rss << "{ }";
}
return rss.str();
}
};
}
#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
// Separate std::tuple specialization // Separate std::tuple specialization
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
#include <tuple> #include <tuple>
@@ -401,6 +430,34 @@ namespace Catch {
} }
#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
#include <variant>
namespace Catch {
template<>
struct StringMaker<std::monostate> {
static std::string convert(const std::monostate&) {
return "{ }";
}
};
template<typename... Elements>
struct StringMaker<std::variant<Elements...>> {
static std::string convert(const std::variant<Elements...>& variant) {
if (variant.valueless_by_exception()) {
return "{valueless variant}";
} else {
return std::visit(
[](const auto& value) {
return ::Catch::Detail::stringify(value);
},
variant
);
}
}
};
}
#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
namespace Catch { namespace Catch {
struct not_this_one {}; // Tag type for detecting which begin/ end are being selected struct not_this_one {}; // Tag type for detecting which begin/ end are being selected

View File

@@ -0,0 +1,40 @@
/*
* Created by Jozef on 12/11/2018.
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
#include <type_traits>
namespace Catch{
#ifdef CATCH_CPP17_OR_GREATER
template <typename...>
inline constexpr auto is_unique = std::true_type{};
template <typename T, typename... Rest>
inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
>{};
#else
template <typename...>
struct is_unique : std::true_type{};
template <typename T0, typename T1, typename... Rest>
struct is_unique<T0, T1, Rest...> : std::integral_constant
<bool,
!std::is_same<T0, T1>::value
&& is_unique<T0, Rest...>::value
&& is_unique<T1, Rest...>::value
>{};
#endif
}
#endif // TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED

View File

@@ -37,7 +37,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 4, 0, "", 0 ); static Version version( 2, 6, 0, "", 0 );
return version; return version;
} }

View File

@@ -44,9 +44,11 @@ namespace {
} }
void hexEscapeChar(std::ostream& os, unsigned char c) { void hexEscapeChar(std::ostream& os, unsigned char c) {
std::ios_base::fmtflags f(os.flags());
os << "\\x" os << "\\x"
<< std::uppercase << std::hex << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>(c); << static_cast<int>(c);
os.flags(f);
} }
} // anonymous namespace } // anonymous namespace

View File

@@ -30,7 +30,7 @@ namespace Catch {
// + 1 for null terminator // + 1 for null terminator
const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize]; char buffer[maxDoubleSize];
// Save previous errno, to prevent sprintf from overwriting it // Save previous errno, to prevent sprintf from overwriting it
ErrnoGuard guard; ErrnoGuard guard;
#ifdef _MSC_VER #ifdef _MSC_VER
@@ -45,6 +45,10 @@ namespace Catch {
TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
:StreamingReporterBase(_config) {} :StreamingReporterBase(_config) {}
std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };
}
void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
bool TestEventListenerBase::assertionEnded(AssertionStats const &) { bool TestEventListenerBase::assertionEnded(AssertionStats const &) {

View File

@@ -217,7 +217,7 @@ namespace Catch {
node->children.push_back(m_rootSection); node->children.push_back(m_rootSection);
m_testCases.push_back(node); m_testCases.push_back(node);
m_rootSection.reset(); m_rootSection.reset();
assert(m_deepestSection); assert(m_deepestSection);
m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdOut = testCaseStats.stdOut;
m_deepestSection->stdErr = testCaseStats.stdErr; m_deepestSection->stdErr = testCaseStats.stdErr;
@@ -266,6 +266,8 @@ namespace Catch {
struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
TestEventListenerBase( ReporterConfig const& _config ); TestEventListenerBase( ReporterConfig const& _config );
static std::set<Verbosity> getSupportedVerbosities();
void assertionStarting(AssertionInfo const&) override; void assertionStarting(AssertionInfo const&) override;
bool assertionEnded(AssertionStats const&) override; bool assertionEnded(AssertionStats const&) override;
}; };

View File

@@ -111,8 +111,6 @@ public:
void print() const { void print() const {
printSourceInfo(); printSourceInfo();
if (stats.totals.assertions.total() > 0) { if (stats.totals.assertions.total() > 0) {
if (result.isOk())
stream << '\n';
printResultType(); printResultType();
printOriginalExpression(); printOriginalExpression();
printReconstructedExpression(); printReconstructedExpression();

View File

@@ -55,6 +55,9 @@ namespace Catch {
m_xml.startElement( "Catch" ); m_xml.startElement( "Catch" );
if( !m_config->name().empty() ) if( !m_config->name().empty() )
m_xml.writeAttribute( "name", m_config->name() ); m_xml.writeAttribute( "name", m_config->name() );
if( m_config->rngSeed() != 0 )
m_xml.scopedElement( "Randomness" )
.writeAttribute( "seed", m_config->rngSeed() );
} }
void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {

View File

@@ -1,3 +1,4 @@
SETLOCAL EnableDelayedExpansion
@REM # Possibilities: @REM # Possibilities:
@REM # Debug build + coverage @REM # Debug build + coverage
@@ -7,21 +8,15 @@
if "%CONFIGURATION%"=="Debug" ( if "%CONFIGURATION%"=="Debug" (
if "%coverage%"=="1" ( if "%coverage%"=="1" (
@REM # coverage needs to build the special helper as well as the main @REM # coverage needs to build the special helper as well as the main
cmake -Hmisc -Bbuild-misc -A%PLATFORM% cmake -Hmisc -Bbuild-misc -A%PLATFORM% || exit /b !ERRORLEVEL!
cmake --build build-misc cmake --build build-misc || exit /b !ERRORLEVEL!
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind || exit /b !ERRORLEVEL! || exit /b !ERRORLEVEL!
) else ( ) else (
@REM # We know that coverage is 0 @REM # We know that coverage is 0
if "%examples%"=="1" ( python scripts\generateSingleHeader.py || exit /b !ERRORLEVEL!
@REM # Examples live off the single header, so it needs to be regenerated cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=%examples% -DCATCH_BUILD_EXTRA_TESTS=%examples% || exit /b !ERRORLEVEL!
python scripts\generateSingleHeader.py
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON
) else (
@REM # This is just a plain debug build
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
)
) )
) )
if "%CONFIGURATION%"=="Release" ( if "%CONFIGURATION%"=="Release" (
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% || exit /b !ERRORLEVEL!
) )

View File

@@ -1,13 +1,15 @@
SETLOCAL EnableDelayedExpansion
cd Build cd Build
if "%CONFIGURATION%"=="Debug" ( if "%CONFIGURATION%"=="Debug" (
if "%coverage%"=="1" ( if "%coverage%"=="1" (
ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck || exit /b !ERRORLEVEL!
python ..\misc\appveyorMergeCoverageScript.py python ..\misc\appveyorMergeCoverageScript.py || exit /b !ERRORLEVEL!
codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN% codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN% || exit /b !ERRORLEVEL!
) else ( ) else (
ctest -j 2 -C %CONFIGURATION% ctest -j 2 -C %CONFIGURATION% || exit /b !ERRORLEVEL!
) )
) )
if "%CONFIGURATION%"=="Release" ( if "%CONFIGURATION%"=="Release" (
ctest -j 2 -C %CONFIGURATION% ctest -j 2 -C %CONFIGURATION% || exit /b !ERRORLEVEL!
) )

View File

@@ -9,6 +9,38 @@
#include <string> #include <string>
#include <vector> #include <vector>
std::string escape_arg(const std::string& arg) {
if (arg.empty() == false &&
arg.find_first_of(" \t\n\v\"") == arg.npos) {
return arg;
}
std::string escaped;
escaped.push_back('"');
for (auto it = arg.begin(); ; ++it) {
int num_backslashes = 0;
while (it != arg.end() && *it == '\\') {
++it;
++num_backslashes;
}
if (it == arg.end()) {
escaped.append(num_backslashes * 2, '\\');
break;
} else if (*it == '"') {
escaped.append(num_backslashes * 2 + 1, '\\');
escaped.push_back(*it);
} else {
escaped.append(num_backslashes, '\\');
escaped.push_back(*it);
}
}
escaped.push_back('"');
return escaped;
}
void create_empty_file(std::string const& path) { void create_empty_file(std::string const& path) {
std::ofstream ofs(path); std::ofstream ofs(path);
@@ -60,8 +92,9 @@ std::string windowsify_path(std::string path) {
void exec_cmd(std::string const& cmd, int log_num, std::string const& path) { void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
std::array<char, 128> buffer; std::array<char, 128> buffer;
#if defined(_WIN32) #if defined(_WIN32)
// cmd has already been escaped outside this function.
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num) auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
+ ".bin --quiet " + "--sources " + path + " --cover_children -- " + cmd; + ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n'; std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose); std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
#else // Just for testing, in the real world we will always work under WIN32 #else // Just for testing, in the real world we will always work under WIN32
@@ -91,9 +124,9 @@ int main(int argc, char** argv) {
assert(sep - begin(args) == 2 && "Structure differs from expected!"); assert(sep - begin(args) == 2 && "Structure differs from expected!");
auto num = parse_log_file_arg(args[1]); auto num = parse_log_file_arg(args[1]);
auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) { auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
return lhs + ' ' + rhs; return lhs + ' ' + escape_arg(rhs);
}); });
try { try {

View File

@@ -36,8 +36,10 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp ${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringOptional.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringVariant.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp ${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
@@ -117,11 +119,14 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_string.h
${HEADER_DIR}/internal/catch_matchers_vector.h ${HEADER_DIR}/internal/catch_matchers_vector.h
${HEADER_DIR}/internal/catch_message.h ${HEADER_DIR}/internal/catch_message.h
${HEADER_DIR}/internal/catch_meta.hpp
${HEADER_DIR}/internal/catch_objc.hpp ${HEADER_DIR}/internal/catch_objc.hpp
${HEADER_DIR}/internal/catch_objc_arc.hpp ${HEADER_DIR}/internal/catch_objc_arc.hpp
${HEADER_DIR}/internal/catch_option.hpp ${HEADER_DIR}/internal/catch_option.hpp
${HEADER_DIR}/internal/catch_output_redirect.h ${HEADER_DIR}/internal/catch_output_redirect.h
${HEADER_DIR}/internal/catch_platform.h ${HEADER_DIR}/internal/catch_platform.h
${HEADER_DIR}/internal/catch_polyfills.hpp
${HEADER_DIR}/internal/catch_preprocessor.hpp
${HEADER_DIR}/internal/catch_random_number_generator.h ${HEADER_DIR}/internal/catch_random_number_generator.h
${HEADER_DIR}/internal/catch_reenable_warnings.h ${HEADER_DIR}/internal/catch_reenable_warnings.h
${HEADER_DIR}/internal/catch_reporter_registrars.hpp ${HEADER_DIR}/internal/catch_reporter_registrars.hpp
@@ -152,6 +157,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_to_string.hpp ${HEADER_DIR}/internal/catch_to_string.hpp
${HEADER_DIR}/internal/catch_tostring.h ${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_totals.h ${HEADER_DIR}/internal/catch_totals.h
${HEADER_DIR}/internal/catch_type_traits.hpp
${HEADER_DIR}/internal/catch_uncaught_exceptions.h ${HEADER_DIR}/internal/catch_uncaught_exceptions.h
${HEADER_DIR}/internal/catch_user_interfaces.h ${HEADER_DIR}/internal/catch_user_interfaces.h
${HEADER_DIR}/internal/catch_version.h ${HEADER_DIR}/internal/catch_version.h
@@ -195,6 +201,7 @@ set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_output_redirect.cpp ${HEADER_DIR}/internal/catch_output_redirect.cpp
${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
${HEADER_DIR}/internal/catch_polyfills.cpp
${HEADER_DIR}/internal/catch_random_number_generator.cpp ${HEADER_DIR}/internal/catch_random_number_generator.cpp
${HEADER_DIR}/internal/catch_reporter_registry.cpp ${HEADER_DIR}/internal/catch_reporter_registry.cpp
${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_result_type.cpp
@@ -267,7 +274,10 @@ include(CTest)
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS}) add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
target_include_directories(SelfTest PRIVATE ${HEADER_DIR}) target_include_directories(SelfTest PRIVATE ${HEADER_DIR})
if(USE_CPP14) if(USE_CPP17)
message(STATUS "Enabling C++17")
set_property(TARGET SelfTest PROPERTY CXX_STANDARD 17)
elseif(USE_CPP14)
message(STATUS "Enabling C++14") message(STATUS "Enabling C++14")
set_property(TARGET SelfTest PROPERTY CXX_STANDARD 14) set_property(TARGET SelfTest PROPERTY CXX_STANDARD 14)
else() else()
@@ -299,7 +309,7 @@ if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
endif() endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
target_compile_options( SelfTest PRIVATE /w44265 /w44061 /w44062 ) target_compile_options( SelfTest PRIVATE /w44265 /w44061 /w44062 /w45038 )
if (CATCH_ENABLE_WERROR) if (CATCH_ENABLE_WERROR)
target_compile_options( SelfTest PRIVATE /WX) target_compile_options( SelfTest PRIVATE /WX)
endif() endif()
@@ -320,7 +330,7 @@ set_tests_properties(ListTests PROPERTIES
add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags) add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
set_tests_properties(ListTags PROPERTIES set_tests_properties(ListTags PROPERTIES
PASS_REGULAR_EXPRESSION "[0-9]+ tags" PASS_REGULAR_EXPRESSION "[0-9]+ tags"
FAIL_REGULAR_EXPRESSION "[.]") FAIL_REGULAR_EXPRESSION "\\[\\.\\]")
add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters) add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:") set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
@@ -336,10 +346,16 @@ set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No asserti
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___") add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched") set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable # AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>) add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed") set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
if (CATCH_USE_VALGRIND) if (CATCH_USE_VALGRIND)
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>) add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high) add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)

View File

@@ -2,8 +2,12 @@
// Test that Catch's prefixed macros compile and run properly. // Test that Catch's prefixed macros compile and run properly.
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
// This won't provide full coverage, but it might be worth checking
// the other branch as well
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
#include <type_traits>
#include <stdexcept> #include <stdexcept>
[[noreturn]] [[noreturn]]
@@ -23,7 +27,7 @@ CATCH_TEST_CASE("PrefixedMacros") {
CATCH_REQUIRE_THROWS_WITH(this_throws(), "Some msg"); CATCH_REQUIRE_THROWS_WITH(this_throws(), "Some msg");
CATCH_REQUIRE_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; })); CATCH_REQUIRE_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
CATCH_REQUIRE_NOTHROW(this_doesnt_throw()); CATCH_REQUIRE_NOTHROW(this_doesnt_throw());
CATCH_CHECK( 1 == 1 ); CATCH_CHECK( 1 == 1 );
CATCH_CHECK_FALSE( 1 != 1 ); CATCH_CHECK_FALSE( 1 != 1 );
CATCH_CHECKED_IF( 1 == 1 ) { CATCH_CHECKED_IF( 1 == 1 ) {
@@ -31,15 +35,15 @@ CATCH_TEST_CASE("PrefixedMacros") {
} CATCH_CHECKED_ELSE ( 1 == 1 ) { } CATCH_CHECKED_ELSE ( 1 == 1 ) {
CATCH_SUCCEED("don't care"); CATCH_SUCCEED("don't care");
} }
CATCH_CHECK_NOFAIL(1 == 2); CATCH_CHECK_NOFAIL(1 == 2);
CATCH_CHECK_THROWS(this_throws()); CATCH_CHECK_THROWS(this_throws());
CATCH_CHECK_THROWS_AS(this_throws(), std::runtime_error); CATCH_CHECK_THROWS_AS(this_throws(), std::runtime_error);
CATCH_CHECK_THROWS_WITH(this_throws(), "Some msg"); CATCH_CHECK_THROWS_WITH(this_throws(), "Some msg");
CATCH_CHECK_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; })); CATCH_CHECK_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
CATCH_CHECK_NOTHROW(this_doesnt_throw()); CATCH_CHECK_NOTHROW(this_doesnt_throw());
CATCH_REQUIRE_THAT("abcd", Equals("abcd")); CATCH_REQUIRE_THAT("abcd", Equals("abcd"));
CATCH_CHECK_THAT("bdef", Equals("bdef")); CATCH_CHECK_THAT("bdef", Equals("bdef"));
@@ -52,6 +56,9 @@ CATCH_TEST_CASE("PrefixedMacros") {
CATCH_FAIL_CHECK( "failure" ); CATCH_FAIL_CHECK( "failure" );
} }
} }
CATCH_STATIC_REQUIRE( std::is_void<void>::value );
CATCH_STATIC_REQUIRE_FALSE( std::is_void<int>::value );
} }
CATCH_ANON_TEST_CASE() { CATCH_ANON_TEST_CASE() {

View File

@@ -13,6 +13,7 @@ Misc.tests.cpp:<line number>: passed:
Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"' Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"' Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
Compilation.tests.cpp:<line number>: passed: Compilation.tests.cpp:<line number>: passed:
Compilation.tests.cpp:<line number>: passed: h1 == h2 for: [1403 helper] == [1403 helper]
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42' Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -56,110 +57,109 @@ Tricky.tests.cpp:<line number>: passed: !is_true<false>::value for: true
Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true
Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true
Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 101 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 102 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 103 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 104 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 105 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 106 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 107 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 108 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 109 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 110 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 101 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 102 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 103 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 104 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 105 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 106 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 107 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 108 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 109 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 110 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 101 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 102 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 103 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 104 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 105 Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 106 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 107 Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 108 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 109 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 110 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 101 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 102 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 103 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 104 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 105 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 106 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 107 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 108 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 109 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 110 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 101 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 102 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 103 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 104 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 105 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 106 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 107 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 108 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 109 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 110 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 101 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 102 Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 103 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 104 Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 105 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 106 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 107 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 108 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 109 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 110 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 101 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 102 Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 103 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 104 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 105 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 106 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 107 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 108 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 109 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 110 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 101 Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 102 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 103 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 104 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 105 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 106 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 107 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 108 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 109 Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 110 Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 101 Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 102
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 103
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 104
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 105
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 106
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 107
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 108
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 109
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 110
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 101
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 102
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 103
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 104
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 105
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 106
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 107
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 108
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 109
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 110
Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world" Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world"
Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello" Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello"
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0 == 2
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0f == 2
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1 == 2
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 1
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0f == 1
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2 Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1 Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Approx.tests.cpp:<line number>: passed: d == 1.23_a for: 1.23 == Approx( 1.23 ) Approx.tests.cpp:<line number>: passed: d == 1.23_a for: 1.23 == Approx( 1.23 )
Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 ) Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 )
Approx.tests.cpp:<line number>: passed: -d == -1.23_a for: -1.23 == Approx( -1.23 ) Approx.tests.cpp:<line number>: passed: -d == -1.23_a for: -1.23 == Approx( -1.23 )
@@ -221,18 +221,20 @@ Approx.tests.cpp:<line number>: passed: NAN != Approx(NAN) for: nanf != Approx(
Approx.tests.cpp:<line number>: passed: !(NAN == Approx(NAN)) for: !(nanf == Approx( nan )) Approx.tests.cpp:<line number>: passed: !(NAN == Approx(NAN)) for: !(nanf == Approx( nan ))
Tricky.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0 Tricky.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
Tricky.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0 Tricky.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
Message.tests.cpp:<line number>: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
Message.tests.cpp:<line number>: passed: with 7 messages: 'std::vector<int>{1, 2, 3}[0, 1, 2] := 3' and 'std::vector<int>{1, 2, 3}[(0, 1)] := 2' and 'std::vector<int>{1, 2, 3}[0] := 1' and '(helper_1436<int, int>{12, -12}) := { 12, -12 }' and '(helper_1436<int, int>(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3'
ToStringGeneral.tests.cpp:<line number>: passed: true with 1 message: 'i := 2' ToStringGeneral.tests.cpp:<line number>: passed: true with 1 message: 'i := 2'
ToStringGeneral.tests.cpp:<line number>: passed: true with 1 message: '3' ToStringGeneral.tests.cpp:<line number>: passed: true with 1 message: '3'
ToStringGeneral.tests.cpp:<line number>: passed: tab == '/t' for: '/t' == '/t' ToStringGeneral.tests.cpp:<line number>: passed: tab == '\t' for: '\t' == '\t'
ToStringGeneral.tests.cpp:<line number>: passed: newline == '/n' for: '/n' == '/n' ToStringGeneral.tests.cpp:<line number>: passed: newline == '\n' for: '\n' == '\n'
ToStringGeneral.tests.cpp:<line number>: passed: carr_return == '/r' for: '/r' == '/r' ToStringGeneral.tests.cpp:<line number>: passed: carr_return == '\r' for: '\r' == '\r'
ToStringGeneral.tests.cpp:<line number>: passed: form_feed == '/f' for: '/f' == '/f' ToStringGeneral.tests.cpp:<line number>: passed: form_feed == '\f' for: '\f' == '\f'
ToStringGeneral.tests.cpp:<line number>: passed: space == ' ' for: ' ' == ' ' ToStringGeneral.tests.cpp:<line number>: passed: space == ' ' for: ' ' == ' '
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'a' == 'a' ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'a' == 'a'
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'z' == 'z' ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'z' == 'z'
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'A' == 'A' ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'A' == 'A'
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'Z' == 'Z' ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'Z' == 'Z'
ToStringGeneral.tests.cpp:<line number>: passed: null_terminator == '/0' for: 0 == 0 ToStringGeneral.tests.cpp:<line number>: passed: null_terminator == '\0' for: 0 == 0
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2 ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3 ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4 ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
@@ -397,48 +399,98 @@ Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, 0.f)
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0) Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0)
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 8' Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 9' Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 10' Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 2' Generators.tests.cpp:<line number>: passed: i < 4 for: 1 < 4
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 3.141' Generators.tests.cpp:<line number>: passed: i < 4 for: 2 < 4
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 1.379' Generators.tests.cpp:<line number>: passed: i < 4 for: 3 < 4
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 8' Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 9' Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 10' Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 2' Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 3.141' Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 1.379' Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 8' Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 9' Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 10' Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 2' Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 3.141' Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 1.379' Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2 Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 1 for: 1 == 1 Generators.tests.cpp:<line number>: passed: j < i for: -2 < 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 2 for: 2 == 2 Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 4 for: 4 == 4 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen[2] == 4 for: 4 == 4 Generators.tests.cpp:<line number>: passed: j < i for: -3 < 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen[3] == 1 for: 1 == 1 Generators.tests.cpp:<line number>: passed: j < i for: -2 < 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 4 for: 4 == 4 Generators.tests.cpp:<line number>: passed: j < i for: -1 < 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 1 for: 1 == 1 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 2 for: 2 == 2 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen[2] == 9 for: 9 == 9 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen[3] == 7 for: 7 == 7 Generators.tests.cpp:<line number>: passed: j < i for: -3 < 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2 Generators.tests.cpp:<line number>: passed: j < i for: -2 < 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3 Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3 Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
GeneratorsImpl.tests.cpp:<line number>: passed: base->size() == 4 for: 4 == 4 GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: typed for: 0x<hex digits> GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: typed->size() == 4 for: 4 == 4 GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: (*typed)[0] == 7 for: 7 == 7 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: (*typed)[3] == 11 for: 11 == 11 GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4 for: 4 == 4
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get().size() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "aa" for: "aa" == "aa"
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "bb" for: "bb" == "bb"
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "cc" for: "cc" == "cc"
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2.0 for: 2.0 == 2.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4.0 for: 4.0 == 4.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 6.0 for: 6.0 == 6.0
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.22 ) for: 1.23 >= Approx( 1.22 ) Approx.tests.cpp:<line number>: passed: d >= Approx( 1.22 ) for: 1.23 >= Approx( 1.22 )
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.23 ) for: 1.23 >= Approx( 1.23 ) Approx.tests.cpp:<line number>: passed: d >= Approx( 1.23 ) for: 1.23 >= Approx( 1.23 )
Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 )) Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))
@@ -495,6 +547,8 @@ Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'c
Tricky.tests.cpp:<line number>: passed: True for: {?} Tricky.tests.cpp:<line number>: passed: True for: {?}
Tricky.tests.cpp:<line number>: passed: !False for: true Tricky.tests.cpp:<line number>: passed: !False for: true
Tricky.tests.cpp:<line number>: passed: !(False) for: !{?} Tricky.tests.cpp:<line number>: passed: !(False) for: !{?}
Compilation.tests.cpp:<line number>: passed: with 1 message: 'std::is_void<void>::value'
Compilation.tests.cpp:<line number>: passed: with 1 message: '!(std::is_void<int>::value)'
Condition.tests.cpp:<line number>: failed: data.int_seven > 7 for: 7 > 7 Condition.tests.cpp:<line number>: failed: data.int_seven > 7 for: 7 > 7
Condition.tests.cpp:<line number>: failed: data.int_seven < 7 for: 7 < 7 Condition.tests.cpp:<line number>: failed: data.int_seven < 7 for: 7 < 7
Condition.tests.cpp:<line number>: failed: data.int_seven > 8 for: 7 > 8 Condition.tests.cpp:<line number>: failed: data.int_seven > 8 for: 7 > 8
@@ -676,6 +730,7 @@ Condition.tests.cpp:<line number>: passed: cpc != 0 for: 0x<hex digits> != 0
Condition.tests.cpp:<line number>: passed: returnsNull() == 0 for: {null string} == 0 Condition.tests.cpp:<line number>: passed: returnsNull() == 0 for: {null string} == 0
Condition.tests.cpp:<line number>: passed: returnsConstNull() == 0 for: {null string} == 0 Condition.tests.cpp:<line number>: passed: returnsConstNull() == 0 for: {null string} == 0
Condition.tests.cpp:<line number>: passed: 0 != p for: 0 != 0x<hex digits> Condition.tests.cpp:<line number>: passed: 0 != p for: 0 != 0x<hex digits>
Matchers.tests.cpp:<line number>: passed: "foo", Predicate<const char*>([] (const char* const&) { return true; }) for: "foo" matches undescribed predicate
CmdLine.tests.cpp:<line number>: passed: result for: {?} CmdLine.tests.cpp:<line number>: passed: result for: {?}
CmdLine.tests.cpp:<line number>: passed: config.processName == "" for: "" == "" CmdLine.tests.cpp:<line number>: passed: config.processName == "" for: "" == ""
CmdLine.tests.cpp:<line number>: passed: result for: {?} CmdLine.tests.cpp:<line number>: passed: result for: {?}
@@ -704,6 +759,8 @@ CmdLine.tests.cpp:<line number>: passed: config.reporterName == "xml" for: "xml"
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--reporter", "junit"}) for: {?} CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--reporter", "junit"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "junit" for: "junit" == "junit" CmdLine.tests.cpp:<line number>: passed: config.reporterName == "junit" for: "junit" == "junit"
CmdLine.tests.cpp:<line number>: passed: !(cli.parse({ "test", "-r", "xml", "-r", "junit" })) for: !{?} CmdLine.tests.cpp:<line number>: passed: !(cli.parse({ "test", "-r", "xml", "-r", "junit" })) for: !{?}
CmdLine.tests.cpp:<line number>: passed: !result for: true
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("Unrecognized reporter") for: "Unrecognized reporter, 'unsupported'. Check available with --list-reporters" contains: "Unrecognized reporter"
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-b"}) for: {?} CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-b"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == true for: true == true CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == true for: true == true
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--break"}) for: {?} CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--break"}) for: {?}
@@ -736,10 +793,14 @@ CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--use-colour", "no"
CmdLine.tests.cpp:<line number>: passed: config.useColour == UseColour::No for: 2 == 2 CmdLine.tests.cpp:<line number>: passed: config.useColour == UseColour::No for: 2 == 2
CmdLine.tests.cpp:<line number>: passed: !result for: true CmdLine.tests.cpp:<line number>: passed: !result for: true
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of"
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 1 >= 1
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 2 >= 1
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 3 >= 1
Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy! Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy!
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this string contains 'abc' as a") for: "this string contains 'abc' as a substring" matches "this string contains 'abc' as a" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this string contains 'abc' as a") for: "this string contains 'abc' as a substring" matches "this string contains 'abc' as a" case sensitively
Matchers.tests.cpp:<line number>: passed: actual, !UnorderedEquals(expected) for: { 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
Message.tests.cpp:<line number>: passed: with 1 message: 'this is a success' Message.tests.cpp:<line number>: passed: with 1 message: 'this is a success'
Message.tests.cpp:<line number>: passed: Message.tests.cpp:<line number>: passed:
BDD.tests.cpp:<line number>: passed: before == 0 for: 0 == 0 BDD.tests.cpp:<line number>: passed: before == 0 for: 0 == 0
@@ -864,6 +925,74 @@ TagAlias.tests.cpp:<line number>: passed: registry.add( "[no ampersat]", "", Cat
TagAlias.tests.cpp:<line number>: passed: registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) TagAlias.tests.cpp:<line number>: passed: registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
TagAlias.tests.cpp:<line number>: passed: registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) TagAlias.tests.cpp:<line number>: passed: registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
TagAlias.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) TagAlias.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions' VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
Tricky.tests.cpp:<line number>: passed: 0x<hex digits> == bit30and31 for: 3221225472 (0x<hex digits>) == 3221225472 Tricky.tests.cpp:<line number>: passed: 0x<hex digits> == bit30and31 for: 3221225472 (0x<hex digits>) == 3221225472
Message.tests.cpp:<line number>: failed - but was ok: 1 == 2 Message.tests.cpp:<line number>: failed - but was ok: 1 == 2
@@ -936,69 +1065,6 @@ PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() for: true PartTracker.tests.cpp:<line number>: passed: s1.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase.isSuccessfullyCompleted() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.index() == 1 for: 1 == 1
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s2.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s2.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.index() == 1 for: 1 == 1
PartTracker.tests.cpp:<line number>: passed: s2b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s2b.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s2.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s2.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: s2.isSuccessfullyCompleted() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1b.index() == 0 for: 0 == 0
PartTracker.tests.cpp:<line number>: passed: s2b.isOpen() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() == false for: false == false
PartTracker.tests.cpp:<line number>: passed: testCase3.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s1c.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1c.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: g1c.index() == 1 for: 1 == 1
PartTracker.tests.cpp:<line number>: passed: s2c.isOpen() for: true
PartTracker.tests.cpp:<line number>: passed: s2c.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: g1c.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: s1c.isComplete() for: true
PartTracker.tests.cpp:<line number>: passed: testCase3.isComplete() for: true
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14' Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
Approx.tests.cpp:<line number>: passed: d == approx( 1.23 ) for: 1.23 == Approx( 1.23 ) Approx.tests.cpp:<line number>: passed: d == approx( 1.23 ) for: 1.23 == Approx( 1.23 )
Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 ) Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 )
@@ -1063,50 +1129,50 @@ Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes ) == stringWithQuo
Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" for: "don't &quot;quote&quot; me on that" Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" for: "don't &quot;quote&quot; me on that"
== ==
"don't &quot;quote&quot; me on that" "don't &quot;quote&quot; me on that"
Xml.tests.cpp:<line number>: passed: encode( "[/x01]" ) == "[//x01]" for: "[/x01]" == "[/x01]" Xml.tests.cpp:<line number>: passed: encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
Xml.tests.cpp:<line number>: passed: encode( "[/x7F]" ) == "[//x7F]" for: "[/x7F]" == "[/x7F]" Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾" Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾"
Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš" Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš"
Xml.tests.cpp:<line number>: passed: encode("/xDF/xBF") == "/xDF/xBF" for: "߿" == "߿" Xml.tests.cpp:<line number>: passed: encode("\xDF\xBF") == "\xDF\xBF" for: "߿" == "߿"
Xml.tests.cpp:<line number>: passed: encode("/xE0/xA0/x80") == "/xE0/xA0/x80" for: "ࠀ" == "ࠀ" Xml.tests.cpp:<line number>: passed: encode("\xE0\xA0\x80") == "\xE0\xA0\x80" for: "ࠀ" == "ࠀ"
Xml.tests.cpp:<line number>: passed: encode("/xED/x9F/xBF") == "/xED/x9F/xBF" for: "퟿" == "퟿" Xml.tests.cpp:<line number>: passed: encode("\xED\x9F\xBF") == "\xED\x9F\xBF" for: "퟿" == "퟿"
Xml.tests.cpp:<line number>: passed: encode("/xEE/x80/x80") == "/xEE/x80/x80" for: "" == "" Xml.tests.cpp:<line number>: passed: encode("\xEE\x80\x80") == "\xEE\x80\x80" for: "" == ""
Xml.tests.cpp:<line number>: passed: encode("/xEF/xBF/xBF") == "/xEF/xBF/xBF" for: "￿" == "￿" Xml.tests.cpp:<line number>: passed: encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" for: "￿" == "￿"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x90/x80/x80") == "/xF0/x90/x80/x80" for: "𐀀" == "𐀀" Xml.tests.cpp:<line number>: passed: encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" for: "𐀀" == "𐀀"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x8F/xBF/xBF") == "/xF4/x8F/xBF/xBF" for: "􏿿" == "􏿿" Xml.tests.cpp:<line number>: passed: encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" for: "􏿿" == "􏿿"
Xml.tests.cpp:<line number>: passed: encode("Here /xFF be 👾") == u8"Here //xFF be 👾" for: "Here /xFF be 👾" == "Here /xFF be 👾" Xml.tests.cpp:<line number>: passed: encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" for: "Here \xFF be 👾" == "Here \xFF be 👾"
Xml.tests.cpp:<line number>: passed: encode("/xFF") == "//xFF" for: "/xFF" == "/xFF" Xml.tests.cpp:<line number>: passed: encode("\xFF") == "\\xFF" for: "\xFF" == "\xFF"
Xml.tests.cpp:<line number>: passed: encode("/xC5/xC5/xA0") == u8"//xC5Š" for: "/xC5Š" == "/xC5Š" Xml.tests.cpp:<line number>: passed: encode("\xC5\xC5\xA0") == u8"\\xC5Š" for: "\xC5Š" == "\xC5Š"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x90/x80/x80") == u8"//xF4//x90//x80//x80" for: "/xF4/x90/x80/x80" == "/xF4/x90/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" for: "\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
Xml.tests.cpp:<line number>: passed: encode("/xC0/x80") == u8"//xC0//x80" for: "/xC0/x80" == "/xC0/x80" Xml.tests.cpp:<line number>: passed: encode("\xC0\x80") == u8"\\xC0\\x80" for: "\xC0\x80" == "\xC0\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80/x80/x80") == u8"//xF0//x80//x80//x80" for: "/xF0/x80/x80/x80" == "/xF0/x80/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" for: "\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
Xml.tests.cpp:<line number>: passed: encode("/xC1/xBF") == u8"//xC1//xBF" for: "/xC1/xBF" == "/xC1/xBF" Xml.tests.cpp:<line number>: passed: encode("\xC1\xBF") == u8"\\xC1\\xBF" for: "\xC1\xBF" == "\xC1\xBF"
Xml.tests.cpp:<line number>: passed: encode("/xE0/x9F/xBF") == u8"//xE0//x9F//xBF" for: "/xE0/x9F/xBF" == "/xE0/x9F/xBF" Xml.tests.cpp:<line number>: passed: encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" for: "\xE0\x9F\xBF" == "\xE0\x9F\xBF"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x8F/xBF/xBF") == u8"//xF0//x8F//xBF//xBF" for: "/xF0/x8F/xBF/xBF" == "/xF0/x8F/xBF/xBF" Xml.tests.cpp:<line number>: passed: encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" for: "\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
Xml.tests.cpp:<line number>: passed: encode("/xED/xA0/x80") == "/xED/xA0/x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>" Xml.tests.cpp:<line number>: passed: encode("\xED\xA0\x80") == "\xED\xA0\x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/xED/xAF/xBF") == "/xED/xAF/xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>" Xml.tests.cpp:<line number>: passed: encode("\xED\xAF\xBF") == "\xED\xAF\xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/xED/xB0/x80") == "/xED/xB0/x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>" Xml.tests.cpp:<line number>: passed: encode("\xED\xB0\x80") == "\xED\xB0\x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/xED/xBF/xBF") == "/xED/xBF/xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>" Xml.tests.cpp:<line number>: passed: encode("\xED\xBF\xBF") == "\xED\xBF\xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/x80") == u8"//x80" for: "/x80" == "/x80" Xml.tests.cpp:<line number>: passed: encode("\x80") == u8"\\x80" for: "\x80" == "\x80"
Xml.tests.cpp:<line number>: passed: encode("/x81") == u8"//x81" for: "/x81" == "/x81" Xml.tests.cpp:<line number>: passed: encode("\x81") == u8"\\x81" for: "\x81" == "\x81"
Xml.tests.cpp:<line number>: passed: encode("/xBC") == u8"//xBC" for: "/xBC" == "/xBC" Xml.tests.cpp:<line number>: passed: encode("\xBC") == u8"\\xBC" for: "\xBC" == "\xBC"
Xml.tests.cpp:<line number>: passed: encode("/xBF") == u8"//xBF" for: "/xBF" == "/xBF" Xml.tests.cpp:<line number>: passed: encode("\xBF") == u8"\\xBF" for: "\xBF" == "\xBF"
Xml.tests.cpp:<line number>: passed: encode("/xF5/x80/x80/x80") == u8"//xF5//x80//x80//x80" for: "/xF5/x80/x80/x80" == "/xF5/x80/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" for: "\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF6/x80/x80/x80") == u8"//xF6//x80//x80//x80" for: "/xF6/x80/x80/x80" == "/xF6/x80/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" for: "\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF7/x80/x80/x80") == u8"//xF7//x80//x80//x80" for: "/xF7/x80/x80/x80" == "/xF7/x80/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" for: "\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
Xml.tests.cpp:<line number>: passed: encode("/xDE") == u8"//xDE" for: "/xDE" == "/xDE" Xml.tests.cpp:<line number>: passed: encode("\xDE") == u8"\\xDE" for: "\xDE" == "\xDE"
Xml.tests.cpp:<line number>: passed: encode("/xDF") == u8"//xDF" for: "/xDF" == "/xDF" Xml.tests.cpp:<line number>: passed: encode("\xDF") == u8"\\xDF" for: "\xDF" == "\xDF"
Xml.tests.cpp:<line number>: passed: encode("/xE0") == u8"//xE0" for: "/xE0" == "/xE0" Xml.tests.cpp:<line number>: passed: encode("\xE0") == u8"\\xE0" for: "\xE0" == "\xE0"
Xml.tests.cpp:<line number>: passed: encode("/xEF") == u8"//xEF" for: "/xEF" == "/xEF" Xml.tests.cpp:<line number>: passed: encode("\xEF") == u8"\\xEF" for: "\xEF" == "\xEF"
Xml.tests.cpp:<line number>: passed: encode("/xF0") == u8"//xF0" for: "/xF0" == "/xF0" Xml.tests.cpp:<line number>: passed: encode("\xF0") == u8"\\xF0" for: "\xF0" == "\xF0"
Xml.tests.cpp:<line number>: passed: encode("/xF4") == u8"//xF4" for: "/xF4" == "/xF4" Xml.tests.cpp:<line number>: passed: encode("\xF4") == u8"\\xF4" for: "\xF4" == "\xF4"
Xml.tests.cpp:<line number>: passed: encode("/xE0/x80") == u8"//xE0//x80" for: "/xE0/x80" == "/xE0/x80" Xml.tests.cpp:<line number>: passed: encode("\xE0\x80") == u8"\\xE0\\x80" for: "\xE0\x80" == "\xE0\x80"
Xml.tests.cpp:<line number>: passed: encode("/xE0/xBF") == u8"//xE0//xBF" for: "/xE0/xBF" == "/xE0/xBF" Xml.tests.cpp:<line number>: passed: encode("\xE0\xBF") == u8"\\xE0\\xBF" for: "\xE0\xBF" == "\xE0\xBF"
Xml.tests.cpp:<line number>: passed: encode("/xE1/x80") == u8"//xE1//x80" for: "/xE1/x80" == "/xE1/x80" Xml.tests.cpp:<line number>: passed: encode("\xE1\x80") == u8"\\xE1\\x80" for: "\xE1\x80" == "\xE1\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80") == u8"//xF0//x80" for: "/xF0/x80" == "/xF0/x80" Xml.tests.cpp:<line number>: passed: encode("\xF0\x80") == u8"\\xF0\\x80" for: "\xF0\x80" == "\xF0\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x80") == u8"//xF4//x80" for: "/xF4/x80" == "/xF4/x80" Xml.tests.cpp:<line number>: passed: encode("\xF4\x80") == u8"\\xF4\\x80" for: "\xF4\x80" == "\xF4\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80/x80") == u8"//xF0//x80//x80" for: "/xF0/x80/x80" == "/xF0/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" for: "\xF0\x80\x80" == "\xF0\x80\x80"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x80/x80") == u8"//xF4//x80//x80" for: "/xF4/x80/x80" == "/xF4/x80/x80" Xml.tests.cpp:<line number>: passed: encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" for: "\xF4\x80\x80" == "\xF4\x80\x80"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }" ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }" ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }" ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
@@ -1166,7 +1232,7 @@ Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: makeString( false ) != static_cast<char*>(0) for: "valid string" != {null string} Misc.tests.cpp:<line number>: passed: makeString( false ) != static_cast<char*>(0) for: "valid string" != {null string}
Misc.tests.cpp:<line number>: passed: makeString( true ) == static_cast<char*>(0) for: {null string} == {null string} Misc.tests.cpp:<line number>: passed: makeString( true ) == static_cast<char*>(0) for: {null string} == {null string}
Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0 Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, /"Arthur/" }, { /"Ford/", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }" ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
== ==
"{ { 42, "Arthur" }, { "Ford", 24 } }" "{ { 42, "Arthur" }, { "Ford", 24 } }"
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0 Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
@@ -1190,18 +1256,18 @@ String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'
Misc.tests.cpp:<line number>: failed: false with 1 message: '3' Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7' Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }"
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { /"one/", 1 } }" for: "{ { "one", 1 } }" == "{ { "one", 1 } }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" for: "{ { "one", 1 } }" == "{ { "one", 1 } }"
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { /"abc/", 1 }, { /"def/", 2 }, { /"ghi/", 3 } }" for: "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" for: "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
== ==
"{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }" "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(value) == "{ 34, /"xyzzy/" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( value ) == "{ 34, /"xyzzy/" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptySet ) == "{ }" for: "{ }" == "{ }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptySet ) == "{ }" for: "{ }" == "{ }"
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ /"one/" }" for: "{ "one" }" == "{ "one" }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ \"one\" }" for: "{ "one" }" == "{ "one" }"
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ /"abc/", /"def/", /"ghi/" }" for: "{ "abc", "def", "ghi" }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" for: "{ "abc", "def", "ghi" }"
== ==
"{ "abc", "def", "ghi" }" "{ "abc", "def", "ghi" }"
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pr ) == "{ { /"green/", 55 } }" for: "{ { "green", 55 } }" ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" for: "{ { "green", 55 } }"
== ==
"{ { "green", 55 } }" "{ { "green", 55 } }"
Tricky.tests.cpp:<line number>: failed: std::string( "first" ) == "second" for: "first" == "second" Tricky.tests.cpp:<line number>: failed: std::string( "first" ) == "second" for: "first" == "second"
@@ -1239,11 +1305,15 @@ Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 =
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3 Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 5 == 5 Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 5 == 5
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 4 == 4 Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 4 == 4
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 5 == 5
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 5 == 5
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e0) == "E2/V0" for: "E2/V0" == "E2/V0" EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e0) == "E2/V0" for: "E2/V0" == "E2/V0"
EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e1) == "E2/V1" for: "E2/V1" == "E2/V1" EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e1) == "E2/V1" for: "E2/V1" == "E2/V1"
EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e3) == "Unknown enum value 10" for: "Unknown enum value 10" EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e3) == "Unknown enum value 10" for: "Unknown enum value 10"
@@ -1260,17 +1330,17 @@ ToStringTuple.tests.cpp:<line number>: passed: "{ }" == ::Catch::Detail::stringi
ToStringTuple.tests.cpp:<line number>: passed: "1.2f" == ::Catch::Detail::stringify(float(1.2)) for: "1.2f" == "1.2f" ToStringTuple.tests.cpp:<line number>: passed: "1.2f" == ::Catch::Detail::stringify(float(1.2)) for: "1.2f" == "1.2f"
ToStringTuple.tests.cpp:<line number>: passed: "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) for: "{ 1.2f, 0 }" == "{ 1.2f, 0 }" ToStringTuple.tests.cpp:<line number>: passed: "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) for: "{ 1.2f, 0 }" == "{ 1.2f, 0 }"
ToStringTuple.tests.cpp:<line number>: passed: "{ 0 }" == ::Catch::Detail::stringify(type{0}) for: "{ 0 }" == "{ 0 }" ToStringTuple.tests.cpp:<line number>: passed: "{ 0 }" == ::Catch::Detail::stringify(type{0}) for: "{ 0 }" == "{ 0 }"
ToStringTuple.tests.cpp:<line number>: passed: "{ 0, 42, /"Catch me/" }" == ::Catch::Detail::stringify(value) for: "{ 0, 42, "Catch me" }" ToStringTuple.tests.cpp:<line number>: passed: "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) for: "{ 0, 42, "Catch me" }"
== ==
"{ 0, 42, "Catch me" }" "{ 0, 42, "Catch me" }"
ToStringTuple.tests.cpp:<line number>: passed: "{ /"hello/", /"world/" }" == ::Catch::Detail::stringify(type{"hello","world"}) for: "{ "hello", "world" }" ToStringTuple.tests.cpp:<line number>: passed: "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) for: "{ "hello", "world" }"
== ==
"{ "hello", "world" }" "{ "hello", "world" }"
ToStringTuple.tests.cpp:<line number>: passed: "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) for: "{ { 42 }, { }, 1.2f }" ToStringTuple.tests.cpp:<line number>: passed: "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) for: "{ { 42 }, { }, 1.2f }"
== ==
"{ { 42 }, { }, 1.2f }" "{ { 42 }, { }, 1.2f }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{ }" for: "{ }" == "{ }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{ }" for: "{ }" == "{ }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{ { /"hello/" }, { /"world/" } }" for: "{ { "hello" }, { "world" } }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" for: "{ { "hello" }, { "world" } }"
== ==
"{ { "hello" }, { "world" } }" "{ { "hello" }, { "world" } }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(bools) == "{ }" for: "{ }" == "{ }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(bools) == "{ }" for: "{ }" == "{ }"
@@ -1283,8 +1353,8 @@ ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) =
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ 42 }" for: "{ 42 }" == "{ 42 }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ }" for: "{ }" == "{ }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ }" for: "{ }" == "{ }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ /"hello/" }" for: "{ "hello" }" == "{ "hello" }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ \"hello\" }" for: "{ "hello" }" == "{ "hello" }"
ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ /"hello/", /"world/" }" for: "{ "hello", "world" }" ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" for: "{ "hello", "world" }"
== ==
"{ "hello", "world" }" "{ "hello", "world" }"
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5 Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
@@ -1306,5 +1376,5 @@ Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5 Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Failed 62 test cases, failed 122 assertions. Failed 69 test cases, failed 129 assertions.

View File

@@ -3,6 +3,8 @@
<exe-name> is a <version> host application. <exe-name> is a <version> host application.
Run with -? for options Run with -? for options
Randomness seeded to: 1
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -90,6 +92,83 @@ Class.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
"hello" == "world" "hello" == "world"
-------------------------------------------------------------------------------
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 0
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
with expansion:
0 == 1
-------------------------------------------------------------------------------
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 1
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
with expansion:
0 == 1
-------------------------------------------------------------------------------
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 2
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
with expansion:
0 == 1
-------------------------------------------------------------------------------
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 3
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
with expansion:
0 == 1
-------------------------------------------------------------------------------
A TEMPLATE_TEST_CASE_METHOD based test run that fails - double
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture<TestType>::m_a == 2 )
with expansion:
1.0 == 2
-------------------------------------------------------------------------------
A TEMPLATE_TEST_CASE_METHOD based test run that fails - float
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture<TestType>::m_a == 2 )
with expansion:
1.0f == 2
-------------------------------------------------------------------------------
A TEMPLATE_TEST_CASE_METHOD based test run that fails - int
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( Template_Fixture<TestType>::m_a == 2 )
with expansion:
1 == 2
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
A TEST_CASE_METHOD based test run that fails A TEST_CASE_METHOD based test run that fails
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -390,8 +469,7 @@ Message.tests.cpp:<line number>: FAILED:
explicitly with message: explicitly with message:
This is a failure This is a failure
Message.tests.cpp:<line number>: Message.tests.cpp:<line number>: warning:
warning:
This message appears in the output This message appears in the output
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -400,8 +478,7 @@ INFO and WARN do not abort tests
Message.tests.cpp:<line number> Message.tests.cpp:<line number>
............................................................................... ...............................................................................
Message.tests.cpp:<line number>: Message.tests.cpp:<line number>: warning:
warning:
this is a warning this is a warning
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -526,8 +603,7 @@ Nice descriptive name
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: warning:
warning:
This one ran This one ran
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -907,8 +983,7 @@ Where the LHS is not a simple value
Tricky.tests.cpp:<line number> Tricky.tests.cpp:<line number>
............................................................................... ...............................................................................
Tricky.tests.cpp:<line number>: Tricky.tests.cpp:<line number>: warning:
warning:
Uncomment the code in this test to check that it gives a sensible compiler Uncomment the code in this test to check that it gives a sensible compiler
error error
@@ -918,8 +993,7 @@ Where there is more to the expression after the RHS
Tricky.tests.cpp:<line number> Tricky.tests.cpp:<line number>
............................................................................... ...............................................................................
Tricky.tests.cpp:<line number>: Tricky.tests.cpp:<line number>: warning:
warning:
Uncomment the code in this test to check that it gives a sensible compiler Uncomment the code in this test to check that it gives a sensible compiler
error error
@@ -1096,6 +1170,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 212 | 159 passed | 49 failed | 4 failed as expected test cases: 245 | 185 passed | 56 failed | 4 failed as expected
assertions: 1227 | 1098 passed | 108 failed | 21 failed as expected assertions: 1297 | 1161 passed | 115 failed | 21 failed as expected

File diff suppressed because it is too large Load Diff

View File

@@ -3,14 +3,15 @@
<exe-name> is a <version> host application. <exe-name> is a <version> host application.
Run with -? for options Run with -? for options
Randomness seeded to: 1
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
# A test name that starts with a # # A test name that starts with a #
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
with message: with message:
yay yay
@@ -21,14 +22,12 @@ with message:
Decomposition.tests.cpp:<line number> Decomposition.tests.cpp:<line number>
............................................................................... ...............................................................................
Decomposition.tests.cpp:<line number>: Decomposition.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( fptr == 0 ) REQUIRE( fptr == 0 )
with expansion: with expansion:
0 == 0 0 == 0
Decomposition.tests.cpp:<line number>: Decomposition.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( fptr == 0l ) REQUIRE( fptr == 0l )
with expansion: with expansion:
0 == 0 0 == 0
@@ -39,14 +38,12 @@ with expansion:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( y.v == 0 ) REQUIRE( y.v == 0 )
with expansion: with expansion:
0 == 0 0 == 0
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( 0 == y.v ) REQUIRE( 0 == y.v )
with expansion: with expansion:
0 == 0 0 == 0
@@ -57,38 +54,32 @@ with expansion:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( t1 == t2 ) REQUIRE( t1 == t2 )
with expansion: with expansion:
{?} == {?} {?} == {?}
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( t1 != t2 ) REQUIRE( t1 != t2 )
with expansion: with expansion:
{?} != {?} {?} != {?}
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( t1 < t2 ) REQUIRE( t1 < t2 )
with expansion: with expansion:
{?} < {?} {?} < {?}
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( t1 > t2 ) REQUIRE( t1 > t2 )
with expansion: with expansion:
{?} > {?} {?} > {?}
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( t1 <= t2 ) REQUIRE( t1 <= t2 )
with expansion: with expansion:
{?} <= {?} {?} <= {?}
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( t1 >= t2 ) REQUIRE( t1 >= t2 )
with expansion: with expansion:
{?} >= {?} {?} >= {?}
@@ -99,8 +90,7 @@ with expansion:
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#1238 #1238
@@ -108,8 +98,7 @@ PASSED:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 ) REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
with expansion: with expansion:
0 == 0 0 == 0
@@ -117,8 +106,7 @@ with messages:
uarr := "123" uarr := "123"
sarr := "456" sarr := "456"
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 ) REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
with expansion: with expansion:
0 == 0 0 == 0
@@ -132,8 +120,18 @@ with messages:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
-------------------------------------------------------------------------------
#1403
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( h1 == h2 )
with expansion:
[1403 helper] == [1403 helper]
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
@@ -167,8 +165,7 @@ due to unexpected exception with messages:
Exception.tests.cpp:<line number> Exception.tests.cpp:<line number>
............................................................................... ...............................................................................
Exception.tests.cpp:<line number>: Exception.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE_THROWS( thisThrows() ) REQUIRE_THROWS( thisThrows() )
with message: with message:
answer := 42 answer := 42
@@ -179,8 +176,7 @@ with message:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( 42 == f ) REQUIRE( 42 == f )
with expansion: with expansion:
42 == {?} 42 == {?}
@@ -191,38 +187,31 @@ with expansion:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( a == t ) REQUIRE( a == t )
with expansion: with expansion:
3 == 3 3 == 3
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
CHECK( a == t ) CHECK( a == t )
with expansion: with expansion:
3 == 3 3 == 3
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE_THROWS( throws_int(true) ) REQUIRE_THROWS( throws_int(true) )
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
CHECK_THROWS_AS( throws_int(true), int ) CHECK_THROWS_AS( throws_int(true), int )
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE_NOTHROW( throws_int(false) ) REQUIRE_NOTHROW( throws_int(false) )
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") )
with expansion: with expansion:
"aaa" ends with: "aaa" "aaa" ends with: "aaa"
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( templated_tests<int>(3) ) REQUIRE( templated_tests<int>(3) )
with expansion: with expansion:
true true
@@ -238,8 +227,7 @@ Misc.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
1 == 0 1 == 0
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( errno == 1 ) REQUIRE( errno == 1 )
with expansion: with expansion:
1 == 1 1 == 1
@@ -250,8 +238,7 @@ with expansion:
Compilation.tests.cpp:<line number> Compilation.tests.cpp:<line number>
............................................................................... ...............................................................................
Compilation.tests.cpp:<line number>: Compilation.tests.cpp:<line number>: PASSED:
PASSED:
REQUIRE( x == 4 ) REQUIRE( x == 4 )
with expansion: with expansion:
{?} == 4 {?} == 4
@@ -265,8 +252,7 @@ with message:
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
with message: with message:
Everything is OK Everything is OK
@@ -277,8 +263,7 @@ with message:
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
with message: with message:
Everything is OK Everything is OK
@@ -289,8 +274,7 @@ with message:
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
with message: with message:
Everything is OK Everything is OK
@@ -301,8 +285,7 @@ with message:
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
with message: with message:
Everything is OK Everything is OK
@@ -313,8 +296,7 @@ with message:
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>
............................................................................... ...............................................................................
Misc.tests.cpp:<line number>: Misc.tests.cpp:<line number>: PASSED:
PASSED:
with message: with message:
Everything is OK Everything is OK
@@ -341,6 +323,6 @@ with expansion:
!true !true
=============================================================================== ===============================================================================
test cases: 14 | 11 passed | 1 failed | 2 failed as expected test cases: 15 | 12 passed | 1 failed | 2 failed as expected
assertions: 38 | 31 passed | 4 failed | 3 failed as expected assertions: 39 | 32 passed | 4 failed | 3 failed as expected

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <testsuitesloose text artifact
> >
<testsuite name="<exe-name>" errors="17" failures="106" tests="1242" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="113" tests="1312" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/> <testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
@@ -9,6 +9,7 @@
<testcase classname="<exe-name>.global" name="#1175 - Hidden Test" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1175 - Hidden Test" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
<testcase classname="<exe-name>.(Fixture_1245&lt;int, int>)" name="#1245" time="{duration}"/> <testcase classname="<exe-name>.(Fixture_1245&lt;int, int>)" name="#1245" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1403" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}"> <testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
<error type="TEST_CASE"> <error type="TEST_CASE">
expected exception expected exception
@@ -69,19 +70,65 @@ Condition.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/> <testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/> <testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/> <testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/>
<testcase classname="<exe-name>.global" name="10x10 ints" time="{duration}"/> <testcase classname="<exe-name>.global" name="3x3x3 ints" time="{duration}"/>
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}"> <testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
<failure message="&quot;hello&quot; == &quot;world&quot;" type="REQUIRE"> <failure message="&quot;hello&quot; == &quot;world&quot;" type="REQUIRE">
Class.tests.cpp:<line number> Class.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/> <testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 0" time="{duration}">
<failure message="0 == 1" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 1" time="{duration}">
<failure message="0 == 1" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 2" time="{duration}">
<failure message="0 == 1" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - 3" time="{duration}">
<failure message="0 == 1" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - 0" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - 1" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - 2" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - 3" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - double" time="{duration}">
<failure message="1.0 == 2" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - float" time="{duration}">
<failure message="1.0f == 2" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - int" time="{duration}">
<failure message="1 == 2" type="REQUIRE">
Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - double" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - float" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - int" time="{duration}"/>
<testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that fails" time="{duration}"> <testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that fails" time="{duration}">
<failure message="1 == 2" type="REQUIRE"> <failure message="1 == 2" type="REQUIRE">
Class.tests.cpp:<line number> Class.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/> <testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
<testcase classname="<exe-name>.global" name="A Template product test case - 0" time="{duration}"/>
<testcase classname="<exe-name>.global" name="A Template product test case - 1" time="{duration}"/>
<testcase classname="<exe-name>.global" name="A Template product test case - 2" time="{duration}"/>
<testcase classname="<exe-name>.global" name="A Template product test case - 3" time="{duration}"/>
<testcase classname="<exe-name>.global" name="A comparison that uses literals instead of the normal constructor" time="{duration}"/> <testcase classname="<exe-name>.global" name="A comparison that uses literals instead of the normal constructor" time="{duration}"/>
<testcase classname="<exe-name>.global" name="A couple of nested sections followed by a failure" time="{duration}"> <testcase classname="<exe-name>.global" name="A couple of nested sections followed by a failure" time="{duration}">
<failure type="FAIL"> <failure type="FAIL">
@@ -122,6 +169,8 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/> <testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assorted miscellaneous tests" time="{duration}"/> <testcase classname="<exe-name>.global" name="Assorted miscellaneous tests" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Bitfields can be captured (#1027)" time="{duration}"/> <testcase classname="<exe-name>.global" name="Bitfields can be captured (#1027)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions involving commas" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Capture and info messages/Capture should stringify like assertions" time="{duration}"/> <testcase classname="<exe-name>.global" name="Capture and info messages/Capture should stringify like assertions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Capture and info messages/Info should NOT stringify the way assertions do" time="{duration}"/> <testcase classname="<exe-name>.global" name="Capture and info messages/Info should NOT stringify the way assertions do" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Character pretty printing/Specifically escaped" time="{duration}"/> <testcase classname="<exe-name>.global" name="Character pretty printing/Specifically escaped" time="{duration}"/>
@@ -290,14 +339,23 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/> <testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/> <testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/> <testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators/one" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators/two" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators impl/range" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Same type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators impl/fixed values" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Different type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators impl/combined" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- adapters/Repeating a generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators impl/values" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- simple/one" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators impl/values2" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators -- simple/two" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators impl/type erasure" time="{duration}"/> <testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Preset values" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Generator combinator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Explicitly typed generator sequence" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Filter generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take less" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take more" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Map" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Singular repeat" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Actual repeat" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/> <testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/> <testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}"> <testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
@@ -374,6 +432,7 @@ Exception.tests.cpp:<line number>
</error> </error>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/> <testcase classname="<exe-name>.global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Optionally static assertions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Ordering comparison checks that should fail" time="{duration}"> <testcase classname="<exe-name>.global" name="Ordering comparison checks that should fail" time="{duration}">
<failure message="7 > 7" type="CHECK"> <failure message="7 > 7" type="CHECK">
Condition.tests.cpp:<line number> Condition.tests.cpp:<line number>
@@ -478,6 +537,7 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Parse test names and tags/empty quoted name" time="{duration}"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/empty quoted name" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/quoted string followed by tag exclusion" time="{duration}"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/quoted string followed by tag exclusion" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Pointers can be compared to null" time="{duration}"/> <testcase classname="<exe-name>.global" name="Pointers can be compared to null" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Predicate matcher can accept const char*" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/empty args don't cause a crash" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/empty args don't cause a crash" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/default - no arguments" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/default - no arguments" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case using" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case using" time="{duration}"/>
@@ -487,6 +547,7 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/xml" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/xml" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/--reporter/junit" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/--reporter/junit" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/Only one reporter is accepted" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/Only one reporter is accepted" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/must match one of the available ones" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/-b" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/-b" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/--break" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/--break" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-a aborts after first failure" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-a aborts after first failure" time="{duration}"/>
@@ -502,6 +563,9 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/yes" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/yes" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/no" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/no" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/error" time="{duration}"/> <testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/error" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Product with differing arities - 0" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Product with differing arities - 1" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Product with differing arities - 2" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Reconstruction should be based on stringification: #914" time="{duration}"> <testcase classname="<exe-name>.global" name="Reconstruction should be based on stringification: #914" time="{duration}">
<failure message="Hey, its truthy!" type="CHECK"> <failure message="Hey, its truthy!" type="CHECK">
Decomposition.tests.cpp:<line number> Decomposition.tests.cpp:<line number>
@@ -518,6 +582,7 @@ Matchers.tests.cpp:<line number>
Matchers.tests.cpp:<line number> Matchers.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Regression test #1" time="{duration}"/>
<testcase classname="<exe-name>.global" name="SUCCEED counts as a test pass" time="{duration}"/> <testcase classname="<exe-name>.global" name="SUCCEED counts as a test pass" time="{duration}"/>
<testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/> <testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/>
<testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/> <testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
@@ -591,6 +656,30 @@ Misc.tests.cpp:<line number>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Tag alias can be registered against tag patterns/The same tag alias can only be registered once" time="{duration}"/> <testcase classname="<exe-name>.global" name="Tag alias can be registered against tag patterns/The same tag alias can only be registered once" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tag alias can be registered against tag patterns/Tag aliases must be of the form [@name]" time="{duration}"/> <testcase classname="<exe-name>.global" name="Tag alias can be registered against tag patterns/Tag aliases must be of the form [@name]" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/resizing bigger changes size and capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/resizing smaller changes size but not capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/reserving bigger changes capacity but not size" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/reserving smaller does not change size or capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/resizing bigger changes size and capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/resizing smaller changes size but not capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/reserving bigger changes capacity but not size" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/reserving smaller does not change size or capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/resizing bigger changes size and capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/resizing smaller changes size but not capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/reserving bigger changes capacity but not size" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/reserving smaller does not change size or capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/resizing bigger changes size and capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/resizing smaller changes size but not capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/reserving bigger changes capacity but not size" time="{duration}"/>
<testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/reserving smaller does not change size or capacity" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Test case with one argument" time="{duration}"/> <testcase classname="<exe-name>.global" name="Test case with one argument" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Test enum bit values" time="{duration}"/> <testcase classname="<exe-name>.global" name="Test enum bit values" time="{duration}"/>
<testcase classname="<exe-name>.global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/> <testcase classname="<exe-name>.global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/>
@@ -611,13 +700,6 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/> <testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/> <testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/open a nested section" time="{duration}"/> <testcase classname="<exe-name>.global" name="Tracker/open a nested section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator/close outer section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator/close outer section/Re-enter for second generation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Start a new inner section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Start a new inner section/Re-enter for second generation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Fail an inner section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Fail an inner section/Re-enter for second generation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Unexpected exceptions can be translated" time="{duration}"> <testcase classname="<exe-name>.global" name="Unexpected exceptions can be translated" time="{duration}">
<error type="TEST_CASE"> <error type="TEST_CASE">
3.14 3.14
@@ -865,6 +947,7 @@ Tricky.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_maker_and_operator> )" time="{duration}"/> <testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_maker_and_operator> )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_operator> )" time="{duration}"/> <testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_operator> )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="strlen3" time="{duration}"/> <testcase classname="<exe-name>.global" name="strlen3" time="{duration}"/>
<testcase classname="<exe-name>.global" name="tables" time="{duration}"/>
<testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}"> <testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
<error type="TEST_CASE"> <error type="TEST_CASE">
Why would you throw a std::string? Why would you throw a std::string?

File diff suppressed because it is too large Load Diff

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