Compare commits

...

105 Commits

Author SHA1 Message Date
Martin Hořeňovský
f526ff0fc3 Bump version to v3.0.0 preview 5 2022-04-20 23:46:07 +02:00
Martin Hořeňovský
17a04f88d9 Always report rng seed from builtin reporters
Not all reporters use a format that supports this, so TeamCity
and Automake reporters still do not report it. The console
reporter now reports it even on successful runs, where before
it only reported the rng seed in the header, which was showed
either for failed run, or for run with `-s`.

CLoses #2065
2022-04-19 10:32:13 +02:00
Martin Hořeňovský
90e6905050 Remove no longer used CATCH_USE_VALGRIND cmake option 2022-04-18 12:14:21 +02:00
Martin Hořeňovský
6bdc7e1a65 Remove unused function in Clara 2022-04-17 23:30:40 +02:00
Martin Hořeňovský
7b93a2014c Rename catch_stream -> catch_reusable_string_stream
After everything else was split out, this name much reflects the
actual contents of the file(s).
2022-04-16 16:34:08 +02:00
Martin Hořeňovský
98bb638fb2 Split out IStream out of catch_stream.hpp 2022-04-16 16:33:57 +02:00
Martin Hořeňovský
05e85c5652 Split out Catch::cout/cerr/clog into their own file 2022-04-16 16:33:50 +02:00
Martin Hořeňovský
b520257676 Split REMOVE_PARENS from catch_preprocessor.hpp
This way, some headers can include just the new header, which
transitively decreases the total include size of test_macros.hpp.
2022-04-15 17:14:28 +02:00
Martin Hořeňovský
574d042821 Push catch_preprocessor include down from test_macros header 2022-04-15 16:40:06 +02:00
Martin Hořeňovský
c742ea9ad9 Some IWYU include cleanups 2022-04-14 17:16:01 +02:00
Martin Hořeňovský
a243cbae52 Introduce type to handle reporter specs with defaults filled-in 2022-04-13 15:02:25 +02:00
Martin Hořeňovský
79d1e82381 Store IStream instance owning ptrs in reporter instances
This ended up being a surprisingly large refactoring, motivated
by removing a `const_cast` from `Config`'s handling of reporter
streams, forced by previous commit.
2022-04-13 15:00:50 +02:00
Martin Hořeňovský
4f09f1120b Make IStream::stream non-const
This way it makes much more sense from logically-const point
of view, and also means that concrete implementations don't
have to always have a `mutable` keyword on the stream member.
2022-04-13 14:59:39 +02:00
Martin Hořeňovský
9934b7de13 Remove pointless mutable from ScopedElement's XmlWriter ptr 2022-04-12 22:31:51 +02:00
Martin Hořeňovský
7a89916198 Remove superfluous default argument from XMLWriter's constructor 2022-04-12 22:28:40 +02:00
Martin Hořeňovský
61f803126d Use parent constructor where applicable in reporters 2022-04-12 22:27:12 +02:00
Martin Hořeňovský
d698776ec5 Remove unused RDBufStream type 2022-04-12 22:22:04 +02:00
Martin Hořeňovský
f25236ff43 Small cleanup for pluralise 2022-04-11 20:37:54 +02:00
Martin Hořeňovský
8cdaebe964 struct -> class normalization for various interface types 2022-04-11 18:32:35 +02:00
Martin Hořeňovský
1a56ba851b struct -> class normalization for matchers 2022-04-11 13:06:54 +02:00
Martin Hořeňovský
9abe49ec53 struct -> class normalization for reporters 2022-04-11 12:58:58 +02:00
Martin Hořeňovský
195a6ac941 Use StringRefs for operation name in StringMatcherBase 2022-04-11 10:58:45 +02:00
Martin Hořeňovský
be948f1fd0 Add COST property to the CMakeConfig tests 2022-04-10 21:55:52 +02:00
Martin Hořeňovský
4e006a93ff Rename IStreamingReporterPtr => IEventListenerPtr
This reflects the renaming of the reporter/listener base class.
2022-04-10 21:50:51 +02:00
Martin Hořeňovský
73d8fb5bca Update release-notes.md 2022-04-10 21:43:28 +02:00
Martin Hořeňovský
0a33405983 Mention Bazel support in release notes 2022-04-09 20:55:13 +02:00
Lukasz Okraszewski
cb551b4f6d Add default reporter for Bazel integration (#2399)
When the added Bazel configuration flag is enabled,
a default JUnit reporter will be added if the XML
envrioment variable is defined.
Fix include paths for generated config header.
Enable Bazel config by default when building with
Bazel.


Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2022-04-08 18:01:59 +02:00
Martin Hořeňovský
4b78157981 Remove Config::openStream function
It has become completely vestigial, as it only ever passed-through
the argument down to a different function, and being private
member function, it didn't even introduce a useful compilation
firewall.
2022-04-07 12:50:20 +02:00
Martin Hořeňovský
46b3f7ee5f Document magic %-prefixed streams 2022-04-07 12:50:18 +02:00
Martin Hořeňovský
f9f4e58dfb Add missing version placeholder to --colour-mode cli option docs 2022-04-07 12:50:14 +02:00
Martin Hořeňovský
d5bfce4d84 Rename config::colourMode to config::defaultConfigMode
This describes the actual intention much better.
2022-04-07 12:50:13 +02:00
Martin Hořeňovský
c43947eb47 Fix CLI hints for colour and reporter options 2022-04-07 12:50:10 +02:00
Martin Hořeňovský
423e1d2ebb Integrate the new reporter specs into Catch2
This means that the CLI interface now uses the new key-value oriented
reporter spec, the common reporter base creates the colour implementation
based on the reporter-specific configuration, and it also stores the
custom configuration options for each reporter instance.

Closes #339 as it allows per-reporter forcing of ansi colour codes.
2022-04-07 12:50:08 +02:00
Martin Hořeňovský
3c06bcb374 Fix reporter parser spec to use the right key for colour-mode 2022-04-06 21:41:45 +02:00
Martin Hořeňovský
a51fd07bd0 Add helper for parsing the new reporter specs
The new reporter spec generalizes key-value options that can be
passed to the reporter, looking like this
`reporterName[::key=value]*`. A key can be either Catch2-recognized,
which currently means either `out` or `colour`, or reporter-specific
which is anything prefixed with `X`, e.g. `Xfoo`.
2022-04-05 15:45:54 +02:00
Martin Hořeňovský
8ac86495de Cleanup ColourMode parsing in CLI 2022-04-05 13:42:21 +02:00
Martin Hořeňovský
d750da13a8 Split out colour mode string parsing into its own function 2022-04-05 13:42:06 +02:00
Martin Hořeňovský
c045733d05 Add splitReporterSpec helper 2022-04-05 12:57:33 +02:00
Martin Hořeňovský
9fea3d253f Add missing include to catch_optional.hpp 2022-04-05 12:55:30 +02:00
Martin Hořeňovský
797c3e7318 Refactor tests 2022-03-31 22:30:38 +02:00
Martin Hořeňovský
6206db5a73 Fix missing licence headers 2022-03-31 20:04:08 +02:00
Daniel Feist
78e33ce51f Added TestCaseInfoHasher and tests. (#2394)
Test case hashing includes tags and class name

As the hasher involves more code now, it was split out into its own file
and it got its own set of tests.

Closes #2304
2022-03-31 16:46:41 +02:00
Martin Hořeňovský
1a8a793178 Refactor colour handling to prepare for per-reporter colour modes
This includes always compiling the ANSI and None colour
implementations, as they don't need to touch any platform
specific APIs, and removing their respective compile-time
configuration options.

Because the Win32 colour implementation requires Win32-specific
APIs, it is still hidden behind a compile-time toggle,
`CATCH_CONFIG_COLOUR_WIN32` (renamed from `..._COLOUR_WINDOWS`).

The commandline options for colours were also changed. The
option now uses different name, and allows to select between
different implementations, rather than changing whether
the compiled-in colour implementation is used through
"yes/no/default" options.
2022-03-28 13:10:13 +02:00
Martin Hořeňovský
a4e4e82474 Always indent test names at 2 spaces with default listing
This makes the output slightly more parsable in cases where
using the xml output from xml reporter is impractical, e.g. from
CMake scripts.
2022-03-24 16:03:46 +01:00
Martin Hořeňovský
6227ca317e Add tests for ColourGuard 2022-03-24 16:02:56 +01:00
Martin Hořeňovský
081a1e9aba ColourGuard is no longer constructed engaged
Forcing it to be engaged explicitly, either via `op<<`, or by
`ColourGuard::engage`, fixes an issue with multiple `ColourGuard`s
being constructed in a single expression. Because the construction
of the `ColourGuard` instances can happen in arbitrary order,
colours would be applied in arbitrary order too. However, a chain
of `op<<`s has strict call orders, fixing this issue.
2022-03-24 16:02:54 +01:00
Martin Hořeňovský
4d8acafecb Rename isStdout => isConsole and add doccomment 2022-03-24 16:02:51 +01:00
Kochetkov, Yuriy
cf6dd937ab Add test for FatalConditionHandler and stack unwinding
Signed-off-by: Kochetkov, Yuriy <yuriyx.kochetkov@intel.com>
2022-03-24 15:49:02 +01:00
Kochetkov, Yuriy
2ce64d1d8f Fix disengage failure logs for FatalConditionHandlerGuard
FatalConditionHandlerGuard is used within RunContext::invokeActiveTestCase().
The intent of this guard is to avoid binary crash without failed test being
reported.
Still in case FatalConditionHandlerGuard destructor being called during stack
unwinding AND finds unexpected top-level filter for SEH unhandled exception,
the binary may still crash. As result of such crash the original exception
details are being hidden.

As the Catch2 provides only `CATCH_CATCH_ANON` macro, with no access to
exception details by design, looks like the best way to handle issue is to:
 - state requirements explicitly by `noexcept` specifier
 - use `Catch::cerr()` to print out possible issue notification

Signed-off-by: Kochetkov, Yuriy <yuriyx.kochetkov@intel.com>
2022-03-24 15:49:02 +01:00
Kochetkov, Yuriy
7882f7359e Remove unnecessary casts
May break the logic in case of WinAPI changes with no warnings

Signed-off-by: Kochetkov, Yuriy <yuriyx.kochetkov@intel.com>
2022-03-24 15:49:02 +01:00
Martin Hořeňovský
0e176c318b Refactored colour handling
* POSIX colour impl is now compiled for all platforms.
* Deciding whether a colour impl should be picked is now stream
  dependent, and thus incompatible implementations can be removed
  immediately, rather than checking when the colour is being used.
2022-03-18 14:04:07 +01:00
Martin Hořeňovský
c1c72c7e05 Better doccomment for IEventListener 2022-03-18 10:30:48 +01:00
Martin Hořeňovský
06092f727d Remove special handling of default stream for reporters
This fixes an issue where reporter with default-output to stdout
would think that it was given a stream _not_ backed by console,
thus not using colour.
2022-03-18 00:41:47 +01:00
Martin Hořeňovský
4acc520f76 Event listeners no longer take reporter config in constructor
This also required splitting out Listener factory from
the reporter factory hierarchy. In return, the listener
factories only need to take in `IConfig const*`, which
opens up further refactorings down the road in the colour
selection and implementation.
2022-03-18 00:36:18 +01:00
Alan Jowett
18c58667d7 Generate Visual Studio project files with constant project guids
By default, CMake derives a Visual Studio project GUID from the
file path but the GUID can be overridden via a property
(see https://gitlab.kitware.com/cmake/cmake/-/commit/c85367f4).

Using a non-constant GUID can cause problems if other projects/repos
want to reference the catch2 vcxproj files, so we force a constant GUID here.

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

Resolves: #2388
2022-03-18 00:21:12 +01:00
Vertexwahn
634cdb4efe Fix borken Bazel build 2022-03-16 14:01:18 +01:00
wqking
38879296a7 Add eventpp and accessorpp to Catch2 users 2022-03-13 16:56:07 +01:00
schallerr
81f612c96c Refactor MatchersRanges test utils (#2386)
- do not hardcode content of containers
- prefix members with m_
- add const and non-const iterators to `with_mocked_iterator_access`
- remove `m_touched` as it wasn't filled properly and isn't used anyway
2022-03-09 23:13:37 +01:00
Martin Hořeňovský
913f79a661 Each reporter keeps its own colour implementation
This opens path to per-reporter colour output customization,
and fixes multiple issues with the old colour implementation.

Under the old implementation, using Win32-backed colouring
would always change the colour used by the console, even if the
actual output was written elsewhere, such as a file passed by
the `--out` flag. This will no longer happen, as the reporter's
colour impl will check that the reporter's stream is pointed
to console before trying to change the colours.

POSIX/ANSI colour implementation suffered a similar-ish issue,
in that it only wrote the colour escape codes into the default
output stream, even if the reporter asking for colouring was
actually writing to a completely different output stream.
2022-03-08 12:51:13 +01:00
Martin Hořeňovský
06f74a0f8e Add %stderr and %stdout as recognized magic stream names 2022-03-07 10:59:27 +01:00
Martin Hořeňovský
61d0f7a9af Pass the whole IStream wrapper into reporter
This will become useful when reworking colour support, because
Win32 colour support requires checking whether the output is
stdout, which is done through the `IStream` wrapper.
2022-03-06 16:34:13 +01:00
Martin Hořeňovský
9b01c404f5 Fix cli help tooltip for --use-colour 2022-03-06 16:28:30 +01:00
Martin Hořeňovský
f206162b2d Fix some messy formatting in catch_stats 2022-03-06 16:28:28 +01:00
Martin Hořeňovský
05d4ec62c8 Add common ReporterBase as parent of the helper bases
This is useful as a centralized place for handling common reporter
problems like handling output streams, and soon also colour impl
handling.
2022-03-06 16:28:22 +01:00
Martin Hořeňovský
4dd5e2eece Rename base reporter iface IStreamingReporter -> IEventListener 2022-03-06 16:28:21 +01:00
John Beard
f9facc1881 Add variadic CAPTURE tests
This makes sure that CAPTURE works when called with variadic arguments,
and also works that way when disabled.

The underlying fix to #2316 is not applicable (CAPTURE is already
variadic when disabled).

This is a port of 5e94498ed0 to the
devel branch.
2022-03-05 16:06:54 +01:00
Joel Uckelman
2ebc041903 Fix name of with-main library. 2022-03-04 00:40:55 +01:00
Martin Hořeňovský
529eec97bb Mention CMake configure options in release notes 2022-02-23 14:16:36 +01:00
Martin Hořeňovský
ff5b311898 Remove superfluous warning suppression in tests 2022-02-22 20:13:17 +01:00
Martin Hořeňovský
4a2eb90302 Add basic CMake presets 2022-02-22 15:47:11 +01:00
Martin Hořeňovský
715cd25081 Add IStream::isStdOut 2022-02-22 15:45:51 +01:00
GravisZro
1d4b42ad7b Minor whitespace fix 2022-02-21 20:04:43 +01:00
Martin Hořeňovský
72f0372664 Add tests for CMake configure toggles passing to Catch2 build 2022-02-20 19:32:30 +01:00
Martin Hořeňovský
4396a9119f Add some missing configuration includes 2022-02-20 19:32:25 +01:00
Martin Hořeňovský
bda4b7df84 Fix fallback stringifier config 2022-02-20 19:32:22 +01:00
John Beard
0c722564c3 Examples: remove references to catch_default_main
catch_default_main.hpp was removed in db32550898

The example 000-CatchMain.cpp is no longer compiled, but is still
present in the examples and is still references by other example
files. Remove the file and references to it, as they are confusing.
2022-02-20 13:10:42 +01:00
Martin Hořeňovský
33ffc3b6fc Allow passing compile-time configuration options through CMake 2022-02-18 11:15:08 +01:00
Martin Hořeňovský
fc5552d27b Push down handling of default reporter to Config's constructor
This simplifies the handling of default reporter in console
parsing, at the cost of making `Config`'s constructor responsible
for more things.
2022-02-17 23:02:30 +01:00
Martin Hořeňovský
7cf2f88e50 Add small missing things to release notes 2022-02-14 18:22:11 +01:00
Martin Hořeňovský
a9ed2c235d Rename MiscFunctions.cmake -> CatchMiscFunctions.cmake 2022-02-07 00:05:11 +01:00
Martin Hořeňovský
a1e5934aa9 Add licence header to MiscFunctions.cmake 2022-02-06 23:59:15 +01:00
Guillaume Egles
190f71792a proper support for lib suffix in conan 2022-02-05 20:53:43 +01:00
Martin Hořeňovský
c912f62fc4 Remove Windows.h related defines 2022-02-05 16:21:06 +01:00
Martin Hořeňovský
aa3c7be434 Fix ToC in CLI documentation 2022-02-05 16:14:47 +01:00
Martin Hořeňovský
b0279e0c14 Remove mention of CATCH_CONFIG_MAIN from docs/configuration.md 2022-02-05 14:55:01 +01:00
Certseeds
9afb6ce138 feature: double -> const auto when static_cast in right
</subject>

Branch: devel

<type>:
- [ ] Bug fix
- [ ] Bug fix (Test)
- [x] New feature
- [ ] Breaking change
- [ ] Documentation update
- [ ] This change requires a documentation update

<body>

<footer>

Signed-off-by: Certseeds <51754303+Certseeds@users.noreply.github.com>
2022-02-04 00:09:01 +01:00
Martin Hořeňovský
efb54926ee Don't cache stdout handle in Windows console colour impl
The cached handle would become invalid if some other code, say
a user-provided test code, redirects stdout through `freopen`
or `_dup2`, which would then cause AppVerifier to complain.

Fixes #2345
2022-01-29 23:12:55 +01:00
Martin Hořeňovský
7a2f9f4633 Extend checkLicense.py to also check tests 2022-01-29 13:10:54 +01:00
Martin Hořeňovský
79e4cd1af4 Cleanup summary comments in ExtraTests 2022-01-29 00:40:03 +01:00
Martin Hořeňovský
635db2785f Use the new licence header in ExtraTests's cpp files 2022-01-29 00:07:44 +01:00
Martin Hořeňovský
51888d360a Use the new licence header in TestScripts 2022-01-29 00:04:49 +01:00
Martin Hořeňovský
f83332d89b Use the new licence header in SelfTest's cpp files 2022-01-29 00:03:43 +01:00
Martin Hořeňovský
b5dbdc858d Link to the v2-v3 migration docs from release notes 2022-01-28 23:55:27 +01:00
Martin Hořeňovský
e53a75b425 Add integration test for listener-reporter event ordering 2022-01-28 00:00:52 +01:00
Martin Hořeňovský
4ff8b27bb6 Cleanups output normalization in ApprovalTests
Removed:
 * NaN normalization
 * INFINITY normalization
 * errno normalization
 * Completely unused duration regex

Tests using these macros should be tagged `[approvals]`
so they are not run as part of approval tests.

Also simplified regex for the test's executable filename,
and hidden some tests relying on nullptr normalization.
2022-01-27 21:11:51 +01:00
Martin Hořeňovský
d861e73f86 Handle full unique test identifiers in testRandomOrder.py 2022-01-27 21:11:37 +01:00
Martin Hořeňovský
dc86d51af2 Update version string to mention Catch2 2022-01-27 20:15:05 +01:00
Simon Weis
5121660e7f Add OpenALpp as an open source library that uses Catch2 2022-01-22 21:33:19 +01:00
Rodrigo Severo
ce556fd646 Ignoring VSCode settings dir 2022-01-15 15:45:56 +01:00
Martin Hořeňovský
b6ff2c3dda Error out reporter registration for reporter names with '::' 2022-01-09 19:01:14 +01:00
Martin Hořeňovský
875299cff0 Remove unused member from Totals
At one point it was inserted there as the simplest way to smuggle
around an extra return value for specific errors in executing
tests. Since then, the error has been changed to be handled
differently, and the member became unused.
2022-01-07 10:34:25 +01:00
Martin Hořeňovský
39d3de17f3 Fix mentions of CATCH_INSTALL_HELPERS
Fixes #2347
2022-01-06 23:37:44 +01:00
Martin Hořeňovský
fff494c10a Tear out trivial_abi on unique_ptr
Turns out people are bad at not combining code compiled with GCC
and Clang, and the improvement from `trivial_abi` on `unique_ptr`
is not worth the maintenance cost of having this be an opt-in
change.

Closes #2344
2022-01-05 00:04:25 +01:00
Martin Hořeňovský
103cb16696 Rename listening reporter to multi reporter 2022-01-05 00:00:28 +01:00
Martin Hořeňovský
244680d512 Update release-process.md for v3 2022-01-03 23:30:39 +01:00
251 changed files with 7725 additions and 3585 deletions

4
.bazelrc Normal file
View File

@@ -0,0 +1,4 @@
build:gcc9 --cxxopt=-std=c++2a
build:clang13 --cxxopt=-std=c++17
build:vs2019 --cxxopt=/std:c++17
build:vs2022 --cxxopt=/std:c++17

View File

@@ -51,6 +51,14 @@ jobs:
other_pkgs: clang-10
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON
# Configure tests with Clang-10
- cxx: clang++-10
build_description: CMake configuration tests
build_type: Debug
std: 14
other_pks: clang-10
cmake_configurations: -DCATCH_ENABLE_CONFIGURE_TESTS=ON
steps:
- uses: actions/checkout@v2

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ benchmark-dir
bazel-*
build-fuzzers
debug-build
.vscode

View File

@@ -1,25 +1,91 @@
# Load the cc_library rule.
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
expand_template(
name = "catch_user_config",
out = "catch2/catch_user_config.hpp",
substitutions = {
"#cmakedefine CATCH_CONFIG_ANDROID_LOGWRITE": "",
"#cmakedefine CATCH_CONFIG_BAZEL_SUPPORT": "#define CATCH_CONFIG_BAZEL_SUPPORT",
"#cmakedefine CATCH_CONFIG_NO_COLOUR_WIN32": "",
"#cmakedefine CATCH_CONFIG_COLOUR_WIN32": "",
"#cmakedefine CATCH_CONFIG_COUNTER": "",
"#cmakedefine CATCH_CONFIG_CPP11_TO_STRING": "",
"#cmakedefine CATCH_CONFIG_CPP17_BYTE": "",
"#cmakedefine CATCH_CONFIG_CPP17_OPTIONAL": "",
"#cmakedefine CATCH_CONFIG_CPP17_STRING_VIEW": "",
"#cmakedefine CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS": "",
"#cmakedefine CATCH_CONFIG_CPP17_VARIANT": "",
"#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER": "",
"#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS": "",
"#cmakedefine CATCH_CONFIG_DISABLE_STRINGIFICATION": "",
"#cmakedefine CATCH_CONFIG_DISABLE": "",
"#cmakedefine CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS": "",
"#cmakedefine CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER": "",
"#cmakedefine CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER": "",
"#cmakedefine CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER": "",
"#cmakedefine CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER": "",
"#cmakedefine CATCH_CONFIG_EXPERIMENTAL_REDIRECT": "",
"#cmakedefine CATCH_CONFIG_FALLBACK_STRINGIFIER @CATCH_CONFIG_FALLBACK_STRINGIFIER@": "",
"#cmakedefine CATCH_CONFIG_FAST_COMPILE": "",
"#cmakedefine CATCH_CONFIG_GLOBAL_NEXTAFTER": "",
"#cmakedefine CATCH_CONFIG_NO_COUNTER": "",
"#cmakedefine CATCH_CONFIG_NO_CPP11_TO_STRING": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_BYTE": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_OPTIONAL": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_STRING_VIEW": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_VARIANT": "",
"#cmakedefine CATCH_CONFIG_NO_GLOBAL_NEXTAFTER": "",
"#cmakedefine CATCH_CONFIG_NO_POSIX_SIGNALS": "",
"#cmakedefine CATCH_CONFIG_NO_USE_ASYNC": "",
"#cmakedefine CATCH_CONFIG_NO_WCHAR": "",
"#cmakedefine CATCH_CONFIG_NO_WINDOWS_SEH": "",
"#cmakedefine CATCH_CONFIG_NOSTDOUT": "",
"#cmakedefine CATCH_CONFIG_POSIX_SIGNALS": "",
"#cmakedefine CATCH_CONFIG_PREFIX_ALL": "",
"#cmakedefine CATCH_CONFIG_USE_ASYNC": "",
"#cmakedefine CATCH_CONFIG_WCHAR": "",
"#cmakedefine CATCH_CONFIG_WINDOWS_CRTDBG": "",
"#cmakedefine CATCH_CONFIG_WINDOWS_SEH": "",
"#cmakedefine CATCH_CONFIG_NO_ANDROID_LOGWRITE": "",
"@CATCH_CONFIG_DEFAULT_REPORTER@": "console",
"@CATCH_CONFIG_CONSOLE_WIDTH@": "80",
},
template = "src/catch2/catch_user_config.hpp.in",
)
# Generated header library, modifies the include prefix to account for
# generation path so that we can include <catch2/catch_user_config.hpp>
# correctly.
cc_library(
name = "catch2_generated",
hdrs = ["catch2/catch_user_config.hpp"],
include_prefix = ".", # to manipulate -I of dependenices
visibility = ["//visibility:public"],
)
# Static library, without main.
cc_library(
name = "catch2",
srcs = glob(
["src/catch2/**/*.cpp"],
exclude = ["src/catch2/internal/catch_main.cpp"],
),
hdrs = glob(["src/catch2/**/*.hpp"]),
srcs = glob(["src/catch2/**/*.cpp"],
exclude=[ "src/catch2/internal/catch_main.cpp"]),
visibility = ["//visibility:public"],
copts = ["-std=c++14"],
linkstatic = True,
includes = ["src/"],
linkstatic = True,
visibility = ["//visibility:public"],
deps = [":catch2_generated"],
)
# Static library, with main.
cc_library(
name = "catch2_main",
srcs = ["src/catch2/internal/catch_main.cpp"],
deps = [":catch2"],
visibility = ["//visibility:public"],
linkstatic = True,
copts = ["-std=c++14"],
includes = ["src/"],
)
linkstatic = True,
visibility = ["//visibility:public"],
deps = [":catch2"],
)

View File

@@ -0,0 +1,77 @@
# Copyright Catch2 Authors
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# https://www.boost.org/LICENSE_1_0.txt)
# SPDX-License-Identifier: BSL-1.0
##
# This file contains options that are materialized into the Catch2
# compiled library. All of them default to OFF, as even the positive
# forms correspond to the user _forcing_ them to ON, while being OFF
# means that Catch2 can use its own autodetection.
#
# For detailed docs look into docs/configuration.md
macro(AddOverridableConfigOption OptionBaseName)
option(CATCH_CONFIG_${OptionBaseName} "Read docs/configuration.md for details" OFF)
option(CATCH_CONFIG_NO_${OptionBaseName} "Read docs/configuration.md for details" OFF)
endmacro()
macro(AddConfigOption OptionBaseName)
option(CATCH_CONFIG_${OptionBaseName} "Read docs/configuration.md for details" OFF)
endmacro()
set(_OverridableOptions
"ANDROID_LOGWRITE"
"BAZEL_SUPPORT"
"COLOUR_WIN32"
"COUNTER"
"CPP11_TO_STRING"
"CPP17_BYTE"
"CPP17_OPTIONAL"
"CPP17_STRING_VIEW"
"CPP17_UNCAUGHT_EXCEPTIONS"
"CPP17_VARIANT"
"GLOBAL_NEXTAFTER"
"POSIX_SIGNALS"
"USE_ASYNC"
"WCHAR"
"WINDOWS_SEH"
)
foreach(OptionName ${_OverridableOptions})
AddOverridableConfigOption(${OptionName})
endforeach()
set(_OtherConfigOptions
"DISABLE_EXCEPTIONS"
"DISABLE_EXCEPTIONS_CUSTOM_HANDLER"
"DISABLE"
"DISABLE_STRINGIFICATION"
"ENABLE_ALL_STRINGMAKERS"
"ENABLE_OPTIONAL_STRINGMAKER"
"ENABLE_PAIR_STRINGMAKER"
"ENABLE_TUPLE_STRINGMAKER"
"ENABLE_VARIANT_STRINGMAKER"
"EXPERIMENTAL_REDIRECT"
"FAST_COMPILE"
"NOSTDOUT"
"PREFIX_ALL"
"WINDOWS_CRTDBG"
)
foreach(OptionName ${_OtherConfigOptions})
AddConfigOption(${OptionName})
endforeach()
set(CATCH_CONFIG_DEFAULT_REPORTER "console" CACHE STRING "Read docs/configuration.md for details. The name of the reporter should be without quotes.")
set(CATCH_CONFIG_CONSOLE_WIDTH "80" CACHE STRING "Read docs/configuration.md for details. Must form a valid integer literal.")
# There is no good way to both turn this into a CMake cache variable,
# and keep reasonable default semantics inside the project. Thus we do
# not define it and users have to provide it as an outside variable.
#set(CATCH_CONFIG_FALLBACK_STRINGIFIER "" CACHE STRING "Read docs/configuration.md for details.")

View File

@@ -1,3 +1,11 @@
# Copyright Catch2 Authors
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# https://www.boost.org/LICENSE_1_0.txt)
# SPDX-License-Identifier: BSL-1.0
include(CheckCXXCompilerFlag)
function(add_cxx_flag_if_supported_to_targets flagname targets)
check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flagname})

View File

@@ -7,4 +7,4 @@ Description: A modern, C++-native test framework for C++14 and above (links in d
Version: ${pkg_version}
Requires: catch2 = ${pkg_version}
Cflags: -I${includedir}
Libs: -L${libdir} -lCatch2WithMain
Libs: -L${libdir} -lCatch2Main

View File

@@ -9,7 +9,7 @@ else()
endif()
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
option(CATCH_INSTALL_EXTRAS "Install extras alongside library" ON)
option(CATCH_INSTALL_EXTRAS "Install extras (CMake scripts, debugger helpers) alongside library" ON)
option(CATCH_DEVELOPMENT_BUILD "Build tests, enable warnings, enable Werror, etc" OFF)
include(CMakeDependentOption)
@@ -20,6 +20,7 @@ cmake_dependent_option(CATCH_BUILD_FUZZERS "Build fuzzers" OFF "CATCH_DEVELOPMEN
cmake_dependent_option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_WERROR "Enables Werror during build" ON "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_SURROGATES "Enable generating and building surrogate TUs for the main headers" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_CONFIGURE_TESTS "Enable CMake configuration tests. WARNING: VERY EXPENSIVE" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
# Catch2's build breaks if done in-tree. You probably should not build
@@ -41,6 +42,7 @@ project(Catch2 LANGUAGES CXX VERSION 3.0.0)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CatchConfigOptions)
if(CATCH_DEVELOPMENT_BUILD)
include(CTest)
endif()
@@ -94,9 +96,6 @@ if (CATCH_DEVELOPMENT_BUILD)
endif()
#option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
#option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
#
#set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#
#

25
CMakePresets.json Normal file
View File

@@ -0,0 +1,25 @@
{
"version": 3,
"configurePresets": [
{
"name": "basic-tests",
"displayName": "Basic development build",
"description": "Enables development build with basic tests that are cheap to build and run",
"cacheVariables": {
"CATCH_DEVELOPMENT_BUILD": "ON"
}
},
{
"name": "all-tests",
"inherits": "basic-tests",
"displayName": "Full development build",
"description": "Enables development build with examples and ALL tests",
"cacheVariables": {
"CATCH_BUILD_EXAMPLES": "ON",
"CATCH_BUILD_EXTRA_TESTS": "ON",
"CATCH_BUILD_SURROGATES": "ON",
"CATCH_ENABLE_CONFIGURE_TESTS": "ON"
}
}
]
}

View File

@@ -0,0 +1,14 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "bazel_skylib",
strip_prefix = "bazel-skylib-2a87d4a62af886fb320883aba102255aba87275e",
urls = [
"https://github.com/bazelbuild/bazel-skylib/archive/2a87d4a62af886fb320883aba102255aba87275e.tar.gz",
],
sha256 = "d847b08d6702d2779e9eb399b54ff8920fa7521dc45e3e53572d1d8907767de7",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()

View File

@@ -51,9 +51,10 @@ test_script:
# build explicitly.
environment:
matrix:
- FLAVOR: VS 2019 x64 Debug Surrogates
- FLAVOR: VS 2019 x64 Debug Surrogates Configure Tests
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
surrogates: 1
configure_tests: 1
platform: x64
configuration: Debug

View File

@@ -20,7 +20,7 @@ class CatchConan(ConanFile):
cmake = CMake(self)
cmake.definitions["BUILD_TESTING"] = "OFF"
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
cmake.definitions["CATCH_INSTALL_HELPERS"] = "ON"
cmake.definitions["CATCH_INSTALL_EXTRAS"] = "ON"
cmake.configure(build_folder="build")
return cmake
@@ -42,16 +42,18 @@ conan_basic_setup()'''.format(line_to_replace, self.install_folder.replace("\\",
cmake.install()
def package_info(self):
lib_suffix = "d" if self.settings.build_type == "Debug" else ""
self.cpp_info.names["cmake_find_package"] = "Catch2"
self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
# Catch2
self.cpp_info.components["catch2base"].names["cmake_find_package"] = "Catch2"
self.cpp_info.components["catch2base"].names["cmake_find_package_multi"] = "Catch2"
self.cpp_info.components["catch2base"].names["pkg_config"] = "Catch2"
self.cpp_info.components["catch2base"].libs = ["Catch2"]
self.cpp_info.components["catch2base"].libs = ["Catch2" + lib_suffix]
# Catch2WithMain
self.cpp_info.components["catch2main"].names["cmake_find_package"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["cmake_find_package_multi"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["pkg_config"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].libs = ["Catch2Main"]
self.cpp_info.components["catch2main"].libs = ["Catch2Main" + lib_suffix]
self.cpp_info.components["catch2main"].requires = ["catch2base"]

View File

@@ -265,8 +265,9 @@ that consume it. These are:
Catch2's test binary will be built. Defaults to `ON`.
* `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be
included in the installation. Defaults to `ON`.
* `CATCH_INSTALL_HELPERS` -- When `ON`, Catch2's extras folder will be
included in the installation. Defaults to `ON`.
* `CATCH_INSTALL_EXTRAS` -- When `ON`, Catch2's extras folder (the CMake
scripts mentioned above, debugger helpers) will be included in the
installation. Defaults to `ON`.
* `CATCH_DEVELOPMENT_BUILD` -- When `ON`, configures the build for development
of Catch2. This means enabling test projects, warnings and so on.
Defaults to `OFF`.

View File

@@ -15,7 +15,6 @@
[Warnings](#warnings)<br>
[Reporting timings](#reporting-timings)<br>
[Load test names to run from a file](#load-test-names-to-run-from-a-file)<br>
[Just test names](#just-test-names)<br>
[Specify the order test cases are run](#specify-the-order-test-cases-are-run)<br>
[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator)<br>
[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard)<br>
@@ -31,6 +30,7 @@
[Override output colouring](#override-output-colouring)<br>
[Test Sharding](#test-sharding)<br>
[Allow running the binary without tests](#allow-running-the-binary-without-tests)<br>
[Output verbosity](#output-verbosity)<br>
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
Click one of the following links to take you straight to that option - or scroll on to browse the available options.
@@ -67,7 +67,7 @@ Click one of the following links to take you straight to that option - or scroll
<a href="#benchmark-confidence-interval"> ` --benchmark-confidence-interval`</a><br />
<a href="#benchmark-no-analysis"> ` --benchmark-no-analysis`</a><br />
<a href="#benchmark-warmup-time"> ` --benchmark-warmup-time`</a><br />
<a href="#use-colour"> ` --use-colour`</a><br />
<a href="#colour-mode"> ` --colour-mode`</a><br />
<a href="#test-sharding"> ` --shard-count`</a><br />
<a href="#test-sharding"> ` --shard-index`</a><br />
<a href=#no-tests-override> ` --allow-running-no-tests`</a><br />
@@ -123,22 +123,33 @@ Test names containing special characters, such as `,` or `[` can specify them on
<a id="choosing-a-reporter-to-use"></a>
## Choosing a reporter to use
<pre>-r, --reporter &lt;reporter[::output-file]&gt;</pre>
> Support for providing output-file through the `-r`, `--reporter` flag was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 X.Y.Z
<pre>-r, --reporter &lt;reporter[::key=value]*&gt;</pre>
Reporters are how the output from Catch2 (results of assertions, tests,
benchmarks and so on) is formatted and written out. The default reporter
is called the "Console" reporter and is intended to provide relatively
verbose and human-friendly output.
Reporters are also individually configurable. To pass configuration options
to the reporter, you append `::key=value` to the reporter specification
as many times as you want, e.g. `--reporter xml::out=someFile.xml`.
The keys must either be prefixed by "X", in which case they are not parsed
by Catch2 and are only passed down to the reporter, or one of options
hardcoded into Catch2. Currently there are only 2,
["out"](#sending-output-to-a-file), and ["colour-mode"](#colour-mode).
_Note that the reporter might still check the X-prefixed options for
validity, and throw an error if they are wrong._
> Support for passing arguments to reporters through the `-r`, `--reporter` flag was introduced in Catch2 X.Y.Z
There are multiple built-in reporters, you can see what they do by using the
[`--list-reporter`](command-line.md#listing-available-tests-tags-or-reporters)
flag. If you need a reporter providing custom format outside of the already
provided ones, look at the ["write your own reporter" part of the reporter
documentation](reporters.md#writing-your-own-reporter).
This option may be passed multiple times to use multiple (different)
reporters at the same time. See the [reporter documentation](reporters.md#multiple-reporters)
for details on what the resulting behaviour is. Also note that at most one
@@ -148,13 +159,12 @@ the [`-o`, `--out`](#sending-output-to-a-file) option.
> Support for using multiple different reporters at the same time was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 X.Y.Z
As with the `--out` option, using `-` for the output file name sends the
output to stdout.
_Note: There is currently no way to escape `::` in the reporter spec,
and thus reporter/file names with `::` in them will not work properly.
As `::` in paths is relatively obscure (unlike `:`), we do not consider
this an issue._
and thus the reporter names, or configuration keys and values, cannot
contain `::`. As `::` in paths is relatively obscure (unlike ':'), we do
not consider this an issue._
<a id="breaking-into-the-debugger"></a>
## Breaking into the debugger
@@ -208,12 +218,24 @@ similar information.
<pre>-o, --out &lt;filename&gt;
</pre>
Use this option to send all output to a file. By default output is sent to stdout (note that uses of stdout and stderr *from within test cases* are redirected and included in the report - so even stderr will effectively end up on stdout).
Using `-` as the filename sends the output to stdout.
Use this option to send all output to a file, instead of stdout. You can
use `-` as the filename to explicitly send the output to stdout (this is
useful e.g. when using multiple reporters).
> Support for `-` as the filename was introduced in Catch2 X.Y.Z
Filenames starting with "%" (percent symbol) are reserved by Catch2 for
meta purposes, e.g. using `%debug` as the filename opens stream that
writes to platform specific debugging/logging mechanism.
Catch2 currently recognizes 3 meta streams:
* `%debug` - writes to platform specific debugging/logging output
* `%stdout` - writes to stdout
* `%stderr` - writes to stderr
> Support for `%stdout` and `%stderr` was introduced in Catch2 X.Y.Z
<a id="naming-a-test-run"></a>
## Naming a test run
@@ -457,16 +479,29 @@ filename it is found in, with any extension stripped, prefixed with the `#` char
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
<a id="use-colour"></a>
<a id="colour-mode"></a>
## Override output colouring
<pre>--use-colour &lt;yes|no|auto&gt;</pre>
<pre>--colour-mode &lt;ansi|win32|none|default&gt;</pre>
Catch colours output for terminals, but omits colouring when it detects that
output is being sent to a pipe. This is done to avoid interfering with automated
processing of output.
> The `--colour-mode` option replaced the old `--colour` option in Catch2 X.Y.Z
Catch2 support two different ways of colouring terminal output, and by
default it attempts to make a good guess on which implementation to use
(and whether to even use it, e.g. Catch2 tries to avoid writing colour
codes when writing the results into a file).
`--colour-mode` allows the user to explicitly select what happens.
* `--colour-mode ansi` tells Catch2 to always use ANSI colour codes, even
when writing to a file
* `--colour-mode win32` tells Catch2 to use colour implementation based
on Win32 terminal API
* `--colour-mode none` tells Catch2 to disable colours completely
* `--colour-mode default` lets Catch2 decide
`--colour-mode default` is the default setting.
`--use-colour yes` forces coloured output, `--use-colour no` disables coloured
output. The default behaviour is `--use-colour auto`.
<a id="test-sharding"></a>
## Test Sharding

View File

@@ -8,17 +8,19 @@
[stdout](#stdout)<br>
[Fallback stringifier](#fallback-stringifier)<br>
[Default reporter](#default-reporter)<br>
[Bazel support](#bazel-support)<br>
[C++11 toggles](#c11-toggles)<br>
[C++17 toggles](#c17-toggles)<br>
[Other toggles](#other-toggles)<br>
[Windows header clutter](#windows-header-clutter)<br>
[Enabling stringification](#enabling-stringification)<br>
[Disabling exceptions](#disabling-exceptions)<br>
[Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<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```).
Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a set of macros for configuring how it is built.
Catch2 is designed to "just work" as much as possible, and most of the
configuration options below are changed automatically during compilation,
according to the detected environment. However, this detection can also
be overriden by users, using macros documented below, and/or CMake options
with the same name.
## Prefixing Catch macros
@@ -30,19 +32,18 @@ To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TE
## Terminal colour
CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring
CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used
CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used
CATCH_CONFIG_COLOUR_WIN32 // Force enables compiling colouring impl based on Win32 console API
CATCH_CONFIG_NO_COLOUR_WIN32 // Force disables ...
Yes, I am English, so I will continue to spell "colour" with a 'u'.
Yes, Catch2 uses the british spelling of colour.
When sending output to the terminal, if it detects that it can, Catch will use colourised text. On Windows the Win32 API, ```SetConsoleTextAttribute```, is used. On POSIX systems ANSI colour escape codes are inserted into the stream.
Catch2 attempts to autodetect whether the Win32 console colouring API,
`SetConsoleTextAttribute`, is available, and if it is available it compiles
in a console colouring implementation that uses it.
For finer control you can define one of the above identifiers (these are mutually exclusive - but that is not checked so may behave unexpectedly if you mix them):
This option can be used to override Catch2's autodetection and force the
compilation either ON or OFF.
Note that when ANSI colour codes are used "unistd.h" must be includable - along with a definition of ```isatty()```
Typically you should place the ```#define``` before #including "catch.hpp" in your main source file - but if you prefer you can define it for your whole project by whatever your IDE or build system provides for you to do so.
## Console width
@@ -96,6 +97,12 @@ This means that defining `CATCH_CONFIG_DEFAULT_REPORTER` to `"console"`
is equivalent with the out-of-the-box experience.
## Bazel support
When `CATCH_CONFIG_BAZEL_SUPPORT` is defined, Catch2 will register a `JUnit`
reporter writing to a path pointed by `XML_OUTPUT_FILE` provided by Bazel.
> `CATCH_CONFIG_BAZEL_SUPPORT` was [introduced](https://github.com/catchorg/Catch2/pull/2399) in Catch2 X.Y.Z.
## C++11 toggles
CATCH_CONFIG_CPP11_TO_STRING // Use `std::to_string`
@@ -179,13 +186,6 @@ This feature is considered experimental and might change at any point.
_Inspired by Doctest's `DOCTEST_CONFIG_DISABLE`_
## Windows header clutter
On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros:
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
## Enabling stringification

View File

@@ -62,18 +62,23 @@ test using an external check script. Catch2 integration tests are written
using CTest, either as a direct command invocation + pass/fail regex,
or by delegating the check to a Python script.
There are also two more kinds of tests, examples and "ExtraTests".
Catch2 is slowly gaining more and more types of tests, currently Catch2
project also has buildable examples, "ExtraTests", and CMake config tests.
Examples present a small and self-contained snippets of code that
use Catch2's facilities for specific purpose. Currently they are assumed
passing if they compile. ExtraTests then are expensive tests, that we
do not want to run all the time. This can be either because they take
a long time to run, or because they take a long time to compile, e.g.
because they test compile time configuration and require separate
compilation.
passing if they compile.
Examples and ExtraTests are not compiled by default. To compile them,
add `-DCATCH_BUILD_EXAMPLES=ON` and `-DCATCH_BUILD_EXTRA_TESTS=ON` to
the invocation of CMake configuration step.
ExtraTests then are expensive tests, that we do not want to run all the
time. This can be either because they take a long time to run, or because
they take a long time to compile, e.g. because they test compile time
configuration and require separate compilation.
Finally, CMake config tests test that you set Catch2's compile-time
configuration options through CMake, using CMake options of the same name.
None of these tests are enabled by default. To enable them, add
`-DCATCH_BUILD_EXAMPLES=ON`, `-DCATCH_BUILD_EXTRA_TESTS=ON`, and
`-DCATCH_ENABLE_CONFIGURE_TESTS=ON` when configuration the CMake build.
Bringing this all together, the steps below should configure, build,
and run all tests in the `Debug` compilation.
@@ -85,7 +90,7 @@ and run all tests in the `Debug` compilation.
./tools/scripts/generateAmalgamatedFiles.py
# 2. Configure the full test build
cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_DEVELOPMENT_BUILD=ON
cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_DEVELOPMENT_BUILD=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON
# 3. Run the actual build
cmake --build debug-build

View File

@@ -3,7 +3,6 @@
## Already available
- Catch main: [Catch-provided main](../examples/000-CatchMain.cpp)
- Test Case: [Single-file](../examples/010-TestCase.cpp)
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-2.cpp)
- Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)

View File

@@ -17,6 +17,9 @@ maintainer's explicit consent._
## Libraries & Frameworks
### [accessorpp](https://github.com/wqking/accessorpp)
C++ library for implementing property and data binding.
### [alpaka](https://github.com/alpaka-group/alpaka)
A header-only C++14 abstraction library for accelerator development.
@@ -50,6 +53,9 @@ Header-only C++11 library to encode/decode base64, base64url, base32, base32hex
### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
A High-performance Cluster Computing Engine.
### [eventpp](https://github.com/wqking/eventpp)
C++ event library for callbacks, event dispatcher, and event queue. With eventpp you can easily implement signal and slot mechanism, publisher and subscriber pattern, or observer pattern.
### [forest](https://github.com/xorz57/forest)
Template Library of Tree Data Structures.
@@ -77,6 +83,9 @@ A small C++ library wrapper for the native C ODBC API.
### [Nonius](https://github.com/libnonius/nonius)
A header-only framework for benchmarking small snippets of C++ code.
### [OpenALpp](https://github.com/Laguna1989/OpenALpp)
A modern OOP C++14 audio library built on OpenAL for Windows, Linux and web (emscripten).
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
A polymorphic value-type for C++.

View File

@@ -55,19 +55,9 @@
This also means that to get all of Catch2's functionality in a test file,
you have to include multiple headers.**
For quick'n'dirty migration, you can replace the old `#include <catch2/catch.hpp>`
with `#include <catch2/catch_all.hpp>`. This is a (one of) convenience
header(s) that brings in _all_ of headers in Catch2. By doing this,
you should be able to migrate instantly, but at the cost of (significantly)
increased compilation times. You should prefer piecemeal including
headers that are actually required by your test code.
The basic set of functionality (`TEST_CASE`, `SECTION`, `REQUIRE`) is in
`catch2/catch_test_macros.hpp`. Matchers are in `matchers` subfolder,
generators in `generators` subfolder, and so on.
Note that documentation has not yet been updated to account for the
new design.
You probably want to look into the [migration docs](migrate-v2-to-v3.md#top),
which were written to help people coming from v2.x.x versions to the
v3 releases.
### FAQ
@@ -132,11 +122,14 @@ new design.
* With the exception of the XmlReporter, the outputs of first party reporters should remain the same
* New pair of events were added
* One obsolete event was removed
* The base class has been renamed
* The built-in reporter class hierarchy has been redone
* Catch2 generates a random seed if one hasn't been specified by the user
* The short flag for `--list-tests`, `-l`, has been removed.
* This is not a commonly used flag and does not need to use up valuable single-letter space.
* The short flag for `--list-tags`, `-t`, has been removed.
* This is not a commonly used flag and does not need to use up valuable single-letter space.
* The `--colour` option has been replaced with `--colour-mode` option
### Improvements
@@ -188,6 +181,16 @@ new design.
* Multiple reporters can now run at the same time and write to different files (#1712, #2183)
* To support this, the `-r`, `--reporter` flag now also accepts optional output destination
* For full overview of the semantics of using multiple reporters, look into the reporter documentation
* To enable the new syntax, reporter names can no longer contain `::`.
* Console colour support has been rewritten and significantly improved
* The colour implementation based on ANSI colour codes is always available
* Colour implementations respect their associated stream
* previously e.g. Win32 impl would change console colour even if Catch2 was writing to a file
* The colour API is resilient against changing evaluation order of expressions
* The associated CLI flag and compile-time configuration options have changed
* For details see the docs for command-line and compile-time Catch2 configuration
* Added a support for Bazel integration with `XML_OUTPUT_FILE` env var (#2399)
* This has to be enabled during compilation.
### Fixes
@@ -200,6 +203,7 @@ new design.
* Previously it forced lower cased name, which would fail for reporters with upper case characters in name
* The cumulative reporter base stores benchmark results alongside assertion results
* Catch2's SE handling should no longer interferes with ASan on Windows (#2334)
* Fixed Windows console colour handling for tests that redirect stdout (#2345)
### Other changes
@@ -217,7 +221,11 @@ new design.
* Running 0 tests (e.g. due to empty binary, or test spec not matching anything) returns non-0 exit code
* Flag `--allow-running-no-tests` overrides this behaviour.
* `NoTests` warning has been removed because it is fully subsumed by this change.
* Catch2's compile-time configuration options (`CATCH_CONFIG_FOO`) can be set through CMake options of the same name
* They use the same semantics as C++ defines, including the `CATCH_CONFIG_NO_FOO` overrides,
* `-DCATCH_CONFIG_DEFAULT_REPORTER=compact` changes default reporter to "compact"
* `-DCATCH_CONFIG_NO_ANDROID_LOGWRITE=ON` forces android logwrite to off
* `-DCATCH_CONFIG_ANDROID_LOGWRITE=OFF` does nothing (the define will not exist)
## 2.13.7

View File

@@ -40,14 +40,10 @@ After version number is incremented, single-include header is regenerated and re
After pushing changes to GitHub, GitHub release *needs* to be created.
Tag version and release title should be same as the new version,
description should contain the release notes for the current release.
Single header version of `catch.hpp` *needs* to be attached as a binary,
as that is where the official download link links to. Preferably
it should use linux line endings. All non-bundled reporters (Automake, TAP,
TeamCity, SonarQube) should also be attached as binaries, as they might be
dependent on a specific version of the single-include header.
We also attach the two amalgamated files as "binaries".
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
signed.
Since 2.5.0, the release tag and the "binaries" (amalgamated files) should
be PGP signed.
#### Signing a tag
@@ -57,16 +53,14 @@ is the version being released, e.g. `git tag -s v2.6.0`.
Use the version name as the short message and the release notes as
the body (long) message.
#### Signing the headers
#### Signing the amalgamated files
This will create ASCII-armored signatures for the headers that are
uploaded to the GitHub release:
This will create ASCII-armored signatures for the two amalgamated files
that are uploaded to the GitHub release:
```
$ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
gpg --armor --output extras/catch_amalgamated.hpp.asc --detach-sig extras/catch_amalgamated.hpp
gpg --armor --output extras/catch_amalgamated.cpp.asc --detach-sig extras/catch_amalgamated.cpp
```
_GPG does not support signing multiple files in single invocation._

View File

@@ -43,9 +43,14 @@ them write into different destinations. The two main uses of this are
Specifying multiple reporter looks like this:
```
--reporter console::- --reporter JUnit::result-junit.xml
--reporter JUnit::out=result-junit.xml --reporter console::out=-::colour-mode=ansi
```
This tells Catch2 to use two reporters, `JUnit` reporter that writes
its machine-readable XML output to file `result-junit.xml`, and the
`console` reporter that writes its user-friendly output to stdout and
uses ANSI colour codes for colouring the output.
Using multiple reporters (or one reporter and one-or-more [event
listeners](event-listener.md#top)) can have surprisingly complex semantics
when using customization points provided to reporters by Catch2, namely
@@ -70,7 +75,7 @@ out in batch after each runthrough of a test case is finished.
You can also write your own custom reporter and tell Catch2 to use it.
When writing your reporter, you have two options:
* Derive from `Catch::IStreamingReporter`. When doing this, you will have
* Derive from `Catch::ReporterBase`. When doing this, you will have
to provide handling for all [reporter events](reporter-events.md#top).
* Derive from one of the provided [utility reporter bases in
Catch2](#utility-reporter-bases).
@@ -162,6 +167,26 @@ Currently there are two customization options:
format includes passing assertions even without the `-s` flag.
### Per-reporter configuration
> Per-reporter configuration was introduced in Catch2 X.Y.Z
Catch2 supports some configuration to happen per reporter. The configuration
options fall into one of two categories:
* Catch2-recognized options
* Reporter-specific options
The former is a small set of universal options that Catch2 handles for
the reporters, e.g. output file or console colour mode. The latter are
options that the reporters have to handle themselves, but the keys and
values can be arbitrary strings, as long as they don't contain `::`. This
allows writing reporters that can be significantly customized at runtime.
Reporter-specific options always have to be prefixed with "X" (large
letter X).
### Other expected functionality of a reporter
When writing a custom reporter, there are few more things that you should

View File

@@ -1,13 +0,0 @@
// 000-CatchMain.cpp
// It is generally recommended to have a single file provide the main
// of a testing binary, and other test files to link against it.
// Let Catch provide main():
#include <catch2/internal/catch_default_main.hpp>
// That's it
// Compile implementation of Catch for use with files that do contain tests:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -c 000-CatchMain.cpp
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% -c 000-CatchMain.cpp

View File

@@ -8,7 +8,7 @@
// - REQUIRE_FALSE() stops at first failure.
// - CHECK_FALSE() continues after failure.
// main() provided in 000-CatchMain.cpp
// main() provided by linkage to Catch2WithMain
#include <catch2/catch_test_macros.hpp>
@@ -53,8 +53,8 @@ TEST_CASE( "Assert that something is false (continue after failure)", "[check-fa
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 030-Asn-Require-Check 030-Asn-Require-Check.cpp 000-CatchMain.o && 030-Asn-Require-Check --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 030-Asn-Require-Check.cpp 000-CatchMain.obj && 030-Asn-Require-Check --success
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 030-Asn-Require-Check 030-Asn-Require-Check.cpp && 030-Asn-Require-Check --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 030-Asn-Require-Check.cpp && 030-Asn-Require-Check --success
// Expected compact output (all assertions):
//

View File

@@ -4,7 +4,7 @@
// - Sections (this file)
// - Traditional class-based fixtures
// main() provided in 000-CatchMain.cpp
// main() provided by linkage to Catch2WithMain
#include <catch2/catch_test_macros.hpp>
#include <vector>
@@ -45,8 +45,8 @@ TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 100-Fix-Section 100-Fix-Section.cpp 000-CatchMain.o && 100-Fix-Section --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 100-Fix-Section.cpp 000-CatchMain.obj && 100-Fix-Section --success
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 100-Fix-Section 100-Fix-Section.cpp && 100-Fix-Section --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 100-Fix-Section.cpp && 100-Fix-Section --success
// Expected compact output (all assertions):
//

View File

@@ -4,7 +4,7 @@
// - Sections
// - Traditional class-based fixtures (this file)
// main() provided in 000-CatchMain.cpp
// main() provided by linkage to Catch2WithMain
#include <catch2/catch_test_macros.hpp>
@@ -52,8 +52,8 @@ TEST_CASE_METHOD( UniqueTestsFixture, "Create Employee/Normal", "[create]" ) {
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp 000-CatchMain.o && 110-Fix-ClassFixture --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 110-Fix-ClassFixture.cpp 000-CatchMain.obj && 110-Fix-ClassFixture --success
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp && 110-Fix-ClassFixture --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 110-Fix-ClassFixture.cpp && 110-Fix-ClassFixture --success
// Expected compact output (all assertions):
//

View File

@@ -1,6 +1,6 @@
// 120-Bdd-ScenarioGivenWhenThen.cpp
// main() provided in 000-CatchMain.cpp
// main() provided by linkage with Catch2WithMain
#include <catch2/catch_test_macros.hpp>
@@ -48,8 +48,8 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 120-Bdd-ScenarioGivenWhenThen 120-Bdd-ScenarioGivenWhenThen.cpp 000-CatchMain.o && 120-Bdd-ScenarioGivenWhenThen --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 120-Bdd-ScenarioGivenWhenThen.cpp 000-CatchMain.obj && 120-Bdd-ScenarioGivenWhenThen --success
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 120-Bdd-ScenarioGivenWhenThen 120-Bdd-ScenarioGivenWhenThen.cpp && 120-Bdd-ScenarioGivenWhenThen --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 120-Bdd-ScenarioGivenWhenThen.cpp && 120-Bdd-ScenarioGivenWhenThen --success
// Expected compact output (all assertions):
//

View File

@@ -420,8 +420,8 @@ TEST_CASE_METHOD( Fixture, "3: Testcase with class-based fixture", "[tag-C][tag-
}
// Compile & run:
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp 000-CatchMain.o && 210-Evt-EventListeners --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp 000-CatchMain.obj && 210-Evt-EventListeners --success
// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
// Expected compact output (all assertions):
//

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,11 @@
include(MiscFunctions)
include(CatchMiscFunctions)
# CMake derives a Visual Studio project GUID from the file path but can be overridden via a property
# (see https://gitlab.kitware.com/cmake/cmake/-/commit/c85367f4). Using a non-constant GUID
# can cause problems if other projects/repos want to reference the vcxproj file,
# so we force a constant GUID here.
set(Catch2_GUID_CMAKE "8d538cbe-01bf-4a2e-a98a-6c368fdf13d7" CACHE INTERNAL "Project GUID")
set(Catch2WithMain_GUID_CMAKE "8bd3552a-2cfb-4a59-ab15-2031b97ada1e" CACHE INTERNAL "Project GUID")
# Please keep these ordered alphabetically
set(BENCHMARK_HEADERS
@@ -31,6 +38,8 @@ set(BENCHMARK_SOURCES
SOURCE_GROUP("benchmark" FILES ${BENCHMARK_HEADERS} ${BENCHMARK_SOURCES})
set(INTERNAL_HEADERS
"${CMAKE_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp"
"${SOURCES_DIR}/catch_user_config.hpp.in"
${SOURCES_DIR}/catch_all.hpp
${SOURCES_DIR}/matchers/catch_matchers_all.hpp
${SOURCES_DIR}/generators/catch_generators_all.hpp
@@ -67,6 +76,7 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp
${SOURCES_DIR}/internal/catch_floating_point_helpers.hpp
${SOURCES_DIR}/internal/catch_istream.hpp
${SOURCES_DIR}/internal/catch_unique_name.hpp
${SOURCES_DIR}/internal/catch_sharding.hpp
${SOURCES_DIR}/generators/catch_generator_exception.hpp
@@ -107,18 +117,21 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_platform.hpp
${SOURCES_DIR}/internal/catch_polyfills.hpp
${SOURCES_DIR}/internal/catch_preprocessor.hpp
${SOURCES_DIR}/internal/catch_preprocessor_remove_parens.hpp
${SOURCES_DIR}/internal/catch_random_number_generator.hpp
${SOURCES_DIR}/internal/catch_random_seed_generation.hpp
${SOURCES_DIR}/reporters/catch_reporter_registrars.hpp
${SOURCES_DIR}/internal/catch_reporter_registry.hpp
${SOURCES_DIR}/internal/catch_reporter_spec_parser.hpp
${SOURCES_DIR}/internal/catch_result_type.hpp
${SOURCES_DIR}/internal/catch_run_context.hpp
${SOURCES_DIR}/internal/catch_section.hpp
${SOURCES_DIR}/internal/catch_stdstreams.hpp
${SOURCES_DIR}/catch_section_info.hpp
${SOURCES_DIR}/catch_session.hpp
${SOURCES_DIR}/internal/catch_singletons.hpp
${SOURCES_DIR}/internal/catch_startup_exception_registry.hpp
${SOURCES_DIR}/internal/catch_stream.hpp
${SOURCES_DIR}/internal/catch_reusable_string_stream.hpp
${SOURCES_DIR}/internal/catch_stream_end_stop.hpp
${SOURCES_DIR}/internal/catch_string_manip.hpp
${SOURCES_DIR}/internal/catch_stringref.hpp
@@ -148,6 +161,7 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_wildcard_pattern.hpp
${SOURCES_DIR}/internal/catch_windows_h_proxy.hpp
${SOURCES_DIR}/internal/catch_xmlwriter.hpp
${SOURCES_DIR}/internal/catch_test_case_info_hasher.hpp
)
set(IMPL_SOURCES
${SOURCES_DIR}/catch_approx.cpp
@@ -168,6 +182,7 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
${SOURCES_DIR}/internal/catch_floating_point_helpers.cpp
${SOURCES_DIR}/internal/catch_istream.cpp
${SOURCES_DIR}/generators/internal/catch_generators_combined_tu.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_combined_tu.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp
@@ -182,12 +197,14 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_random_number_generator.cpp
${SOURCES_DIR}/internal/catch_random_seed_generation.cpp
${SOURCES_DIR}/internal/catch_reporter_registry.cpp
${SOURCES_DIR}/internal/catch_reporter_spec_parser.cpp
${SOURCES_DIR}/internal/catch_result_type.cpp
${SOURCES_DIR}/internal/catch_run_context.cpp
${SOURCES_DIR}/internal/catch_section.cpp
${SOURCES_DIR}/internal/catch_stdstreams.cpp
${SOURCES_DIR}/catch_session.cpp
${SOURCES_DIR}/internal/catch_singletons.cpp
${SOURCES_DIR}/internal/catch_stream.cpp
${SOURCES_DIR}/internal/catch_reusable_string_stream.cpp
${SOURCES_DIR}/internal/catch_stringref.cpp
${SOURCES_DIR}/internal/catch_string_manip.cpp
${SOURCES_DIR}/internal/catch_tag_alias_registry.cpp
@@ -204,6 +221,7 @@ set(IMPL_SOURCES
${SOURCES_DIR}/catch_version.cpp
${SOURCES_DIR}/internal/catch_wildcard_pattern.cpp
${SOURCES_DIR}/internal/catch_xmlwriter.cpp
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
)
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
@@ -211,13 +229,14 @@ set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
set(REPORTER_HEADERS
${SOURCES_DIR}/reporters/catch_reporters_all.hpp
${SOURCES_DIR}/reporters/catch_reporter_automake.hpp
${SOURCES_DIR}/reporters/catch_reporter_common_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_compact.hpp
${SOURCES_DIR}/reporters/catch_reporter_console.hpp
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_event_listener.hpp
${SOURCES_DIR}/reporters/catch_reporter_helpers.hpp
${SOURCES_DIR}/reporters/catch_reporter_junit.hpp
${SOURCES_DIR}/reporters/catch_reporter_listening.hpp
${SOURCES_DIR}/reporters/catch_reporter_multi.hpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.hpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_tap.hpp
@@ -227,11 +246,12 @@ set(REPORTER_HEADERS
set(REPORTER_SOURCES
${SOURCES_DIR}/reporters/catch_reporter_automake.cpp
${SOURCES_DIR}/reporters/catch_reporter_combined_tu.cpp
${SOURCES_DIR}/reporters/catch_reporter_common_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_compact.cpp
${SOURCES_DIR}/reporters/catch_reporter_console.cpp
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_junit.cpp
${SOURCES_DIR}/reporters/catch_reporter_listening.cpp
${SOURCES_DIR}/reporters/catch_reporter_multi.cpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.cpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_tap.cpp
@@ -282,9 +302,15 @@ target_compile_features(Catch2
cxx_variadic_macros
)
configure_file(
"${SOURCES_DIR}/catch_user_config.hpp.in"
"${CMAKE_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp"
)
target_include_directories(Catch2
PUBLIC
$<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-includes>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
@@ -323,7 +349,15 @@ if (NOT_SUBPROJECT)
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install the headers
install(DIRECTORY ${SOURCES_DIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h*")
install(
DIRECTORY
"${SOURCES_DIR}"
"${CMAKE_BINARY_DIR}/generated-includes/catch2" # Also install the generated header
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING
PATTERN "*.hpp"
)
endif()
# Some tests require a full recompilation of Catch2 lib with different
@@ -342,6 +376,7 @@ if (CATCH_BUILD_EXAMPLES OR CATCH_BUILD_EXTRA_TESTS)
target_include_directories(Catch2_buildall_interface
INTERFACE
$<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-includes>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_features(Catch2_buildall_interface

View File

@@ -12,6 +12,7 @@
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <random>
@@ -119,11 +120,15 @@ using Catch::Benchmark::Detail::sample;
double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) {
auto m = Catch::Benchmark::Detail::mean(first, last);
double variance = std::accumulate(first, last, 0., [m](double a, double b) {
double diff = b - m;
return a + diff * diff;
}) / (last - first);
return std::sqrt(variance);
double variance = std::accumulate( first,
last,
0.,
[m]( double a, double b ) {
double diff = b - m;
return a + diff * diff;
} ) /
( last - first );
return std::sqrt( variance );
}
}

View File

@@ -108,8 +108,9 @@ namespace Catch {
double bias = normal_quantile(prob_n);
double z1 = normal_quantile((1. - confidence_level) / 2.);
auto cumn = [n](double x) -> int {
return std::lround(normal_cdf(x) * n); };
auto cumn = [n]( double x ) -> int {
return std::lround( normal_cdf( x ) * n );
};
auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
double b1 = bias + z1;
double b2 = bias - z1;

View File

@@ -67,6 +67,7 @@
#include <catch2/internal/catch_exception_translator_registry.hpp>
#include <catch2/internal/catch_fatal_condition_handler.hpp>
#include <catch2/internal/catch_floating_point_helpers.hpp>
#include <catch2/internal/catch_istream.hpp>
#include <catch2/internal/catch_lazy_expr.hpp>
#include <catch2/internal/catch_leak_detector.hpp>
#include <catch2/internal/catch_list.hpp>
@@ -79,22 +80,26 @@
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_polyfills.hpp>
#include <catch2/internal/catch_preprocessor.hpp>
#include <catch2/internal/catch_preprocessor_remove_parens.hpp>
#include <catch2/internal/catch_random_number_generator.hpp>
#include <catch2/internal/catch_random_seed_generation.hpp>
#include <catch2/internal/catch_reporter_registry.hpp>
#include <catch2/internal/catch_reporter_spec_parser.hpp>
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_run_context.hpp>
#include <catch2/internal/catch_section.hpp>
#include <catch2/internal/catch_sharding.hpp>
#include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_startup_exception_registry.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <catch2/internal/catch_stream_end_stop.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <catch2/internal/catch_template_test_registry.hpp>
#include <catch2/internal/catch_test_case_info_hasher.hpp>
#include <catch2/internal/catch_test_case_registry_impl.hpp>
#include <catch2/internal/catch_test_case_tracker.hpp>
#include <catch2/internal/catch_test_failure_exception.hpp>

View File

@@ -7,6 +7,7 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_approx.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <cmath>
#include <limits>

View File

@@ -86,14 +86,14 @@ namespace Catch {
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
Approx& epsilon( T const& newEpsilon ) {
double epsilonAsDouble = static_cast<double>(newEpsilon);
const auto epsilonAsDouble = static_cast<double>(newEpsilon);
setEpsilon(epsilonAsDouble);
return *this;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
Approx& margin( T const& newMargin ) {
double marginAsDouble = static_cast<double>(newMargin);
const auto marginAsDouble = static_cast<double>(newMargin);
setMargin(marginAsDouble);
return *this;
}

View File

@@ -6,7 +6,7 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_assertion_result.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
namespace Catch {

View File

@@ -6,46 +6,25 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_config.hpp>
#include <catch2/catch_user_config.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/interfaces/catch_interfaces_tag_alias_registry.hpp>
#include <ostream>
namespace Catch {
namespace Detail {
namespace {
class RDBufStream : public IStream {
mutable std::ostream m_os;
public:
//! The streambuf `sb` must outlive the constructed object.
RDBufStream( std::streambuf* sb ): m_os( sb ) {}
~RDBufStream() override = default;
public: // IStream
std::ostream& stream() const override { return m_os; }
};
} // unnamed namespace
} // namespace Detail
std::ostream& operator<<( std::ostream& os,
ConfigData::ReporterAndFile const& reporter ) {
os << "{ " << reporter.reporterName << ", ";
if ( reporter.outputFileName ) {
os << *reporter.outputFileName;
} else {
os << "<default-output>";
}
return os << " }";
bool operator==( ProcessedReporterSpec const& lhs,
ProcessedReporterSpec const& rhs ) {
return lhs.name == rhs.name &&
lhs.outputFilename == rhs.outputFilename &&
lhs.colourMode == rhs.colourMode &&
lhs.customOptions == rhs.customOptions;
}
Config::Config( ConfigData const& data ):
m_data( data ),
m_defaultStream( openStream( data.defaultOutputFilename ) ) {
m_data( data ) {
// We need to trim filter specs to avoid trouble with superfluous
// whitespace (esp. important for bdd macros, as those are manually
// aligned with whitespace).
@@ -57,6 +36,7 @@ namespace Catch {
elem = trim(elem);
}
TestSpecParser parser(ITagAliasRegistry::get());
if (!m_data.testsOrTags.empty()) {
m_hasTestFilters = true;
@@ -66,15 +46,62 @@ namespace Catch {
}
m_testSpec = parser.testSpec();
m_reporterStreams.reserve( m_data.reporterSpecifications.size() );
for ( auto const& reporterAndFile : m_data.reporterSpecifications ) {
if ( reporterAndFile.outputFileName.none() ) {
m_reporterStreams.emplace_back( new Detail::RDBufStream(
m_defaultStream->stream().rdbuf() ) );
} else {
m_reporterStreams.emplace_back(
openStream( *reporterAndFile.outputFileName ) );
// Insert the default reporter if user hasn't asked for a specfic one
if ( m_data.reporterSpecifications.empty() ) {
m_data.reporterSpecifications.push_back( {
#if defined( CATCH_CONFIG_DEFAULT_REPORTER )
CATCH_CONFIG_DEFAULT_REPORTER,
#else
"console",
#endif
{}, {}, {}
} );
}
#if defined( CATCH_CONFIG_BAZEL_SUPPORT )
// Register a JUnit reporter for Bazel. Bazel sets an environment
// variable with the path to XML output. If this file is written to
// during test, Bazel will not generate a default XML output.
// This allows the XML output file to contain higher level of detail
// than what is possible otherwise.
# if defined( _MSC_VER )
// On Windows getenv throws a warning as there is no input validation,
// since the key is hardcoded, this should not be an issue.
# pragma warning( push )
# pragma warning( disable : 4996 )
# endif
const auto bazelOutputFilePtr = std::getenv( "XML_OUTPUT_FILE" );
# if defined( _MSC_VER )
# pragma warning( pop )
# endif
if ( bazelOutputFilePtr != nullptr ) {
m_data.reporterSpecifications.push_back(
{ "junit", std::string( bazelOutputFilePtr ), {}, {} } );
}
#endif
// We now fixup the reporter specs to handle default output spec,
// default colour spec, etc
bool defaultOutputUsed = false;
for ( auto const& reporterSpec : m_data.reporterSpecifications ) {
// We do the default-output check separately, while always
// using the default output below to make the code simpler
// and avoid superfluous copies.
if ( reporterSpec.outputFile().none() ) {
CATCH_ENFORCE( !defaultOutputUsed,
"Internal error: cannot use default output for "
"multiple reporters" );
defaultOutputUsed = true;
}
m_processedReporterSpecs.push_back( ProcessedReporterSpec{
reporterSpec.name(),
reporterSpec.outputFile() ? *reporterSpec.outputFile()
: data.defaultOutputFilename,
reporterSpec.colourMode().valueOr( data.defaultColourMode ),
reporterSpec.customOptions() } );
}
}
@@ -88,12 +115,13 @@ namespace Catch {
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
std::vector<ConfigData::ReporterAndFile> const& Config::getReportersAndOutputFiles() const {
std::vector<ReporterSpec> const& Config::getReporterSpecs() const {
return m_data.reporterSpecifications;
}
std::ostream& Config::getReporterOutputStream(std::size_t reporterIdx) const {
return m_reporterStreams.at(reporterIdx)->stream();
std::vector<ProcessedReporterSpec> const&
Config::getProcessedReporterSpecs() const {
return m_processedReporterSpecs;
}
TestSpec const& Config::testSpec() const { return m_testSpec; }
@@ -103,7 +131,6 @@ namespace Catch {
// IConfig interface
bool Config::allowThrows() const { return !m_data.noThrow; }
std::ostream& Config::defaultStream() const { return m_defaultStream->stream(); }
StringRef Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const {
@@ -119,7 +146,7 @@ namespace Catch {
uint32_t Config::rngSeed() const { return m_data.rngSeed; }
unsigned int Config::shardCount() const { return m_data.shardCount; }
unsigned int Config::shardIndex() const { return m_data.shardIndex; }
UseColour Config::useColour() const { return m_data.useColour; }
ColourMode Config::defaultColourMode() const { return m_data.defaultColourMode; }
bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
int Config::abortAfter() const { return m_data.abortAfter; }
bool Config::showInvisibles() const { return m_data.showInvisibles; }
@@ -131,8 +158,4 @@ namespace Catch {
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
Detail::unique_ptr<IStream const> Config::openStream(std::string const& outputFileName) {
return Catch::makeStream(outputFileName);
}
} // end namespace Catch

View File

@@ -12,28 +12,38 @@
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_random_seed_generation.hpp>
#include <catch2/internal/catch_reporter_spec_parser.hpp>
#include <iosfwd>
#include <vector>
#include <chrono>
#include <map>
#include <string>
#include <vector>
namespace Catch {
struct IStream;
class IStream;
/**
* `ReporterSpec` but with the defaults filled in.
*
* Like `ReporterSpec`, the semantics are unchecked.
*/
struct ProcessedReporterSpec {
std::string name;
std::string outputFilename;
ColourMode colourMode;
std::map<std::string, std::string> customOptions;
friend bool operator==( ProcessedReporterSpec const& lhs,
ProcessedReporterSpec const& rhs );
friend bool operator!=( ProcessedReporterSpec const& lhs,
ProcessedReporterSpec const& rhs ) {
return !( lhs == rhs );
}
};
struct ConfigData {
struct ReporterAndFile {
std::string reporterName;
// If none, the output goes to the default output.
Optional<std::string> outputFileName;
friend bool operator==(ReporterAndFile const& lhs, ReporterAndFile const& rhs) {
return lhs.reporterName == rhs.reporterName && lhs.outputFileName == rhs.outputFileName;
}
friend std::ostream& operator<<(std::ostream &os, ReporterAndFile const& reporter);
};
bool listTests = false;
bool listTags = false;
@@ -65,21 +75,13 @@ namespace Catch {
ShowDurations showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1;
TestRunOrder runOrder = TestRunOrder::Declared;
UseColour useColour = UseColour::Auto;
ColourMode defaultColourMode = ColourMode::PlatformDefault;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
std::string defaultOutputFilename;
std::string name;
std::string processName;
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
std::vector<ReporterAndFile> reporterSpecifications = {
{CATCH_CONFIG_DEFAULT_REPORTER, {}}
};
// Internal: used as parser state
bool _nonDefaultReporterSpecifications = false;
#undef CATCH_CONFIG_DEFAULT_REPORTER
std::vector<ReporterSpec> reporterSpecifications;
std::vector<std::string> testsOrTags;
std::vector<std::string> sectionsToRun;
@@ -97,8 +99,9 @@ namespace Catch {
bool listTags() const;
bool listReporters() const;
std::vector<ConfigData::ReporterAndFile> const& getReportersAndOutputFiles() const;
std::ostream& getReporterOutputStream(std::size_t reporterIdx) const;
std::vector<ReporterSpec> const& getReporterSpecs() const;
std::vector<ProcessedReporterSpec> const&
getProcessedReporterSpecs() const;
std::vector<std::string> const& getTestsOrTags() const override;
std::vector<std::string> const& getSectionsToRun() const override;
@@ -110,7 +113,6 @@ namespace Catch {
// IConfig interface
bool allowThrows() const override;
std::ostream& defaultStream() const override;
StringRef name() const override;
bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override;
@@ -122,7 +124,7 @@ namespace Catch {
uint32_t rngSeed() const override;
unsigned int shardCount() const override;
unsigned int shardIndex() const override;
UseColour useColour() const override;
ColourMode defaultColourMode() const override;
bool shouldDebugBreak() const override;
int abortAfter() const override;
bool showInvisibles() const override;
@@ -134,11 +136,8 @@ namespace Catch {
std::chrono::milliseconds benchmarkWarmupTime() const override;
private:
Detail::unique_ptr<IStream const> openStream(std::string const& outputFileName);
ConfigData m_data;
Detail::unique_ptr<IStream const> m_defaultStream;
std::vector<Detail::unique_ptr<IStream const>> m_reporterStreams;
std::vector<ProcessedReporterSpec> m_processedReporterSpecs;
TestSpec m_testSpec;
bool m_hasTestFilters = false;
};

View File

@@ -9,7 +9,7 @@
#define CATCH_MESSAGE_HPP_INCLUDED
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_stream_end_stop.hpp>
#include <catch2/internal/catch_message_info.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>

View File

@@ -51,7 +51,7 @@ namespace Catch {
void registerReporter( std::string const& name, IReporterFactoryPtr factory ) override {
m_reporterRegistry.registerReporter( name, CATCH_MOVE(factory) );
}
void registerListener( IReporterFactoryPtr factory ) override {
void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) override {
m_reporterRegistry.registerListener( CATCH_MOVE(factory) );
}
void registerTest( Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker ) override {

View File

@@ -11,7 +11,6 @@
#include <catch2/internal/catch_list.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_run_context.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/catch_test_spec.hpp>
#include <catch2/catch_version.hpp>
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
@@ -19,10 +18,12 @@
#include <catch2/internal/catch_sharding.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/reporters/catch_reporter_listening.hpp>
#include <catch2/reporters/catch_reporter_multi.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_registry.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <catch2/internal/catch_istream.hpp>
#include <algorithm>
#include <cassert>
@@ -34,31 +35,40 @@ namespace Catch {
namespace {
const int MaxExitCode = 255;
IStreamingReporterPtr createReporter(std::string const& reporterName, ReporterConfig const& config) {
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) {
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\'');
return reporter;
}
IStreamingReporterPtr makeReporter(Config const* config) {
IEventListenerPtr prepareReporters(Config const* config) {
if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()
&& config->getReportersAndOutputFiles().size() == 1) {
auto& stream = config->getReporterOutputStream(0);
return createReporter(config->getReportersAndOutputFiles()[0].reporterName, ReporterConfig(config, stream));
&& config->getProcessedReporterSpecs().size() == 1) {
auto const& spec = config->getProcessedReporterSpecs()[0];
return createReporter(
spec.name,
ReporterConfig( config,
makeStream( spec.outputFilename ),
spec.colourMode,
spec.customOptions ) );
}
auto multi = Detail::make_unique<ListeningReporter>(config);
auto multi = Detail::make_unique<MultiReporter>(config);
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
for (auto const& listener : listeners) {
multi->addListener(listener->create(Catch::ReporterConfig(config, config->defaultStream())));
multi->addListener(listener->create(config));
}
std::size_t reporterIdx = 0;
for (auto const& reporterAndFile : config->getReportersAndOutputFiles()) {
auto& stream = config->getReporterOutputStream(reporterIdx);
multi->addReporter(createReporter(reporterAndFile.reporterName, ReporterConfig(config, stream)));
for ( auto const& reporterSpec : config->getProcessedReporterSpecs() ) {
multi->addReporter( createReporter(
reporterSpec.name,
ReporterConfig( config,
makeStream( reporterSpec.outputFilename ),
reporterSpec.colourMode,
reporterSpec.customOptions ) ) );
reporterIdx++;
}
@@ -67,7 +77,7 @@ namespace Catch {
class TestGroup {
public:
explicit TestGroup(IStreamingReporterPtr&& reporter, Config const* config):
explicit TestGroup(IEventListenerPtr&& reporter, Config const* config):
m_reporter(reporter.get()),
m_config{config},
m_context{config, CATCH_MOVE(reporter)} {
@@ -120,7 +130,7 @@ namespace Catch {
private:
IStreamingReporter* m_reporter;
IEventListener* m_reporter;
Config const* m_config;
RunContext m_context;
std::set<TestCaseHandle const*> m_tests;
@@ -151,14 +161,17 @@ namespace Catch {
getCurrentMutableContext().setConfig(m_config.get());
m_startupExceptions = true;
Colour colourGuard( Colour::Red );
Catch::cerr() << "Errors occurred during startup!" << '\n';
auto errStream = makeStream( "%stderr" );
auto colourImpl = makeColourImpl(
ColourMode::PlatformDefault, errStream.get() );
auto guard = colourImpl->guardColour( Colour::Red );
errStream->stream() << "Errors occurred during startup!" << '\n';
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
std::rethrow_exception(ex_ptr);
} catch ( std::exception const& ex ) {
Catch::cerr() << TextFlow::Column( ex.what() ).indent(2) << '\n';
errStream->stream() << TextFlow::Column( ex.what() ).indent(2) << '\n';
}
}
}
@@ -173,7 +186,7 @@ namespace Catch {
void Session::showHelp() const {
Catch::cout()
<< "\nCatch v" << libraryVersion() << '\n'
<< "\nCatch2 v" << libraryVersion() << '\n'
<< m_cli << '\n'
<< "For more detailed usage please see the project docs\n\n" << std::flush;
}
@@ -181,7 +194,7 @@ namespace Catch {
Catch::cout()
<< std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
<< std::left << std::setw(16) << "category: " << "testframework\n"
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
<< std::left << std::setw(16) << "framework: " << "Catch2\n"
<< std::left << std::setw(16) << "version: " << libraryVersion() << '\n' << std::flush;
}
@@ -194,12 +207,15 @@ namespace Catch {
if( !result ) {
config();
getCurrentMutableContext().setConfig(m_config.get());
Catch::cerr()
<< Colour( Colour::Red )
auto errStream = makeStream( "%stderr" );
auto colour = makeColourImpl( ColourMode::PlatformDefault, errStream.get() );
errStream->stream()
<< colour->guardColour( Colour::Red )
<< "\nError(s) in input:\n"
<< TextFlow::Column( result.errorMessage() ).indent( 2 )
<< "\n\n";
Catch::cerr() << "Run with -? for usage\n\n" << std::flush;
errStream->stream() << "Run with -? for usage\n\n" << std::flush;
return MaxExitCode;
}
@@ -298,7 +314,7 @@ namespace Catch {
getCurrentMutableContext().setConfig(m_config.get());
// Create reporter(s) so we can route listings through them
auto reporter = makeReporter(m_config.get());
auto reporter = prepareReporters(m_config.get());
auto const& invalidSpecs = m_config->testSpec().getInvalidSpecs();
if ( !invalidSpecs.empty() ) {
@@ -330,7 +346,7 @@ namespace Catch {
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
return (std::min) (MaxExitCode, static_cast<int>(totals.assertions.failed));
}
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
catch( std::exception& ex ) {

View File

@@ -7,8 +7,6 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_case_info.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/catch_test_spec.hpp>
#include <catch2/interfaces/catch_interfaces_testcase.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_case_insensitive_comparisons.hpp>

View File

@@ -42,7 +42,7 @@ namespace Catch {
friend bool operator==( Tag const& lhs, Tag const& rhs );
};
struct ITestInvoker;
class ITestInvoker;
enum class TestCaseProperties : uint8_t {
None = 0,

View File

@@ -10,7 +10,7 @@
#include <catch2/internal/catch_test_macro_impl.hpp>
#include <catch2/catch_message.hpp>
#include <catch2/internal/catch_preprocessor.hpp>
#include <catch2/catch_user_config.hpp>
#include <catch2/internal/catch_section.hpp>
#include <catch2/internal/catch_test_registry.hpp>
#include <catch2/internal/catch_unique_name.hpp>

View File

@@ -21,7 +21,7 @@
namespace Catch {
struct IConfig;
class IConfig;
struct TestCaseInfo;
class TestCaseHandle;

View File

@@ -17,7 +17,7 @@
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_config_wchar.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_void_type.hpp>
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>

View File

@@ -8,7 +8,6 @@
#ifndef CATCH_TOTALS_HPP_INCLUDED
#define CATCH_TOTALS_HPP_INCLUDED
#include <cstddef>
#include <cstdint>
namespace Catch {
@@ -33,7 +32,6 @@ namespace Catch {
Totals delta( Totals const& prevTotals ) const;
int error = 0;
Counts assertions;
Counts testCases;
};

View File

@@ -0,0 +1,198 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/**\file
* **AUTOGENERATED FROM CMAKE CONFIGURATION**
*
* Contains materialized compile-time configuration provided to Catch2's
* CMake configuration. All compile-time configuration options need to
* be here, and also documented in `docs/configuration.md`.
*/
#ifndef CATCH_USER_CONFIG_HPP_INCLUDED
#define CATCH_USER_CONFIG_HPP_INCLUDED
// ------
// Overridable compilation flags,
// these can have 3 "states": Force Yes, Force No, Use Default.
// Setting both Force Yes and Force No is an error
// ------
#cmakedefine CATCH_CONFIG_ANDROID_LOGWRITE
#cmakedefine CATCH_CONFIG_NO_ANDROID_LOGWRITE
#if defined( CATCH_CONFIG_ANDROID_LOGWRITE ) && \
defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE )
# error Cannot force ANDROID_LOGWRITE to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_COLOUR_WIN32
#cmakedefine CATCH_CONFIG_NO_COLOUR_WIN32
#if defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
defined( CATCH_CONFIG_NO_COLOUR_WIN32 )
# error Cannot force COLOUR_WIN32 to be ON and OFF
#endif
#cmakedefine CATCH_CONFIG_COUNTER
#cmakedefine CATCH_CONFIG_NO_COUNTER
#if defined( CATCH_CONFIG_COUNTER ) && \
defined( CATCH_CONFIG_NO_COUNTER )
# error Cannot force COUNTER to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP11_TO_STRING
#cmakedefine CATCH_CONFIG_NO_CPP11_TO_STRING
#if defined( CATCH_CONFIG_CPP11_TO_STRING ) && \
defined( CATCH_CONFIG_NO_CPP11_TO_STRING )
# error Cannot force CPP11_TO_STRING to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_BYTE
#cmakedefine CATCH_CONFIG_NO_CPP17_BYTE
#if defined( CATCH_CONFIG_CPP17_BYTE ) && \
defined( CATCH_CONFIG_NO_CPP17_BYTE )
# error Cannot force CPP17_BYTE to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_OPTIONAL
#cmakedefine CATCH_CONFIG_NO_CPP17_OPTIONAL
#if defined( CATCH_CONFIG_CPP17_OPTIONAL ) && \
defined( CATCH_CONFIG_NO_CPP17_OPTIONAL )
# error Cannot force CPP17_OPTIONAL to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_STRING_VIEW
#cmakedefine CATCH_CONFIG_NO_CPP17_STRING_VIEW
#if defined( CATCH_CONFIG_CPP17_STRING_VIEW ) && \
defined( CATCH_CONFIG_NO_CPP17_STRING_VIEW )
# error Cannot force CPP17_STRING_VIEW to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#cmakedefine CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS
#if defined( CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS ) && \
defined( CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS )
# error Cannot force CPP17_UNCAUGHT_EXCEPTIONS to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_VARIANT
#cmakedefine CATCH_CONFIG_NO_CPP17_VARIANT
#if defined( CATCH_CONFIG_CPP17_VARIANT ) && \
defined( CATCH_CONFIG_NO_CPP17_VARIANT )
# error Cannot force CPP17_VARIANT to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_GLOBAL_NEXTAFTER
#cmakedefine CATCH_CONFIG_NO_GLOBAL_NEXTAFTER
#if defined( CATCH_CONFIG_GLOBAL_NEXTAFTER ) && \
defined( CATCH_CONFIG_NO_GLOBAL_NEXTAFTER )
# error Cannot force GLOBAL_NEXTAFTER to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_POSIX_SIGNALS
#cmakedefine CATCH_CONFIG_NO_POSIX_SIGNALS
#if defined( CATCH_CONFIG_POSIX_SIGNALS ) && \
defined( CATCH_CONFIG_NO_POSIX_SIGNALS )
# error Cannot force POSIX_SIGNALS to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_USE_ASYNC
#cmakedefine CATCH_CONFIG_NO_USE_ASYNC
#if defined( CATCH_CONFIG_USE_ASYNC ) && \
defined( CATCH_CONFIG_NO_USE_ASYNC )
# error Cannot force USE_ASYNC to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_WCHAR
#cmakedefine CATCH_CONFIG_NO_WCHAR
#if defined( CATCH_CONFIG_WCHAR ) && \
defined( CATCH_CONFIG_NO_WCHAR )
# error Cannot force WCHAR to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_WINDOWS_SEH
#cmakedefine CATCH_CONFIG_NO_WINDOWS_SEH
#if defined( CATCH_CONFIG_WINDOWS_SEH ) && \
defined( CATCH_CONFIG_NO_WINDOWS_SEH )
# error Cannot force WINDOWS_SEH to both ON and OFF
#endif
// ------
// Simple toggle defines
// their value is never used and they cannot be overriden
// ------
#cmakedefine CATCH_CONFIG_BAZEL_SUPPORT
#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS
#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
#cmakedefine CATCH_CONFIG_DISABLE
#cmakedefine CATCH_CONFIG_DISABLE_STRINGIFICATION
#cmakedefine CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
#cmakedefine CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
#cmakedefine CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
#cmakedefine CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
#cmakedefine CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
#cmakedefine CATCH_CONFIG_EXPERIMENTAL_REDIRECT
#cmakedefine CATCH_CONFIG_FAST_COMPILE
#cmakedefine CATCH_CONFIG_NOSTDOUT
#cmakedefine CATCH_CONFIG_PREFIX_ALL
#cmakedefine CATCH_CONFIG_WINDOWS_CRTDBG
// ------
// "Variable" defines, these have actual values
// ------
#define CATCH_CONFIG_DEFAULT_REPORTER "@CATCH_CONFIG_DEFAULT_REPORTER@"
#define CATCH_CONFIG_CONSOLE_WIDTH @CATCH_CONFIG_CONSOLE_WIDTH@
// Unlike the macros above, CATCH_CONFIG_FALLBACK_STRINGIFIER does not
// have a good default value, so we cannot always define it, and cannot
// even expose it as a variable in CMake. The users will have to find
// out about it from docs and set it only if they use it.
#cmakedefine CATCH_CONFIG_FALLBACK_STRINGIFIER @CATCH_CONFIG_FALLBACK_STRINGIFIER@
#endif // CATCH_USER_CONFIG_HPP_INCLUDED

View File

@@ -36,7 +36,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 3, 0, 0, "preview", 4 );
static Version version( 3, 0, 0, "preview", 5 );
return version;
}

View File

@@ -12,6 +12,8 @@
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_unique_name.hpp>
#include <catch2/internal/catch_preprocessor.hpp>
#include <vector>
#include <tuple>
@@ -29,7 +31,8 @@ namespace Detail {
} // end namespace detail
template<typename T>
struct IGenerator : GeneratorUntypedBase {
class IGenerator : public GeneratorUntypedBase {
public:
~IGenerator() override = default;
IGenerator() = default;
IGenerator(IGenerator const&) = default;

View File

@@ -26,15 +26,15 @@ namespace Catch {
struct AssertionReaction;
struct SourceLineInfo;
struct ITransientExpression;
struct IGeneratorTracker;
class ITransientExpression;
class IGeneratorTracker;
struct BenchmarkInfo;
template <typename Duration = std::chrono::duration<double, std::nano>>
struct BenchmarkStats;
struct IResultCapture {
class IResultCapture {
public:
virtual ~IResultCapture();
virtual bool sectionStarted( SectionInfo const& sectionInfo,

View File

@@ -86,4 +86,5 @@ namespace Catch {
namespace Catch {
IReporterFactory::~IReporterFactory() = default;
EventListenerFactory::~EventListenerFactory() = default;
}

View File

@@ -42,10 +42,15 @@ namespace Catch {
LexicographicallySorted,
Randomized
};
enum class UseColour {
Auto,
Yes,
No
enum class ColourMode : std::uint8_t {
//! Let Catch2 pick implementation based on platform detection
PlatformDefault,
//! Use ANSI colour code escapes
ANSI,
//! Use Win32 console colour API
Win32,
//! Don't use any colour
None
};
struct WaitForKeypress { enum When {
Never,
@@ -55,13 +60,13 @@ namespace Catch {
}; };
class TestSpec;
class IStream;
struct IConfig : Detail::NonCopyable {
class IConfig : public Detail::NonCopyable {
public:
virtual ~IConfig();
virtual bool allowThrows() const = 0;
virtual std::ostream& defaultStream() const = 0;
virtual StringRef name() const = 0;
virtual bool includeSuccessfulResults() const = 0;
virtual bool shouldDebugBreak() const = 0;
@@ -79,7 +84,7 @@ namespace Catch {
virtual uint32_t rngSeed() const = 0;
virtual unsigned int shardCount() const = 0;
virtual unsigned int shardIndex() const = 0;
virtual UseColour useColour() const = 0;
virtual ColourMode defaultColourMode() const = 0;
virtual std::vector<std::string> const& getSectionsToRun() const = 0;
virtual Verbosity verbosity() const = 0;

View File

@@ -25,7 +25,8 @@ namespace Catch {
};
} // namespace Detail
struct IMutableEnumValuesRegistry {
class IMutableEnumValuesRegistry {
public:
virtual ~IMutableEnumValuesRegistry(); // = default;
virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;

View File

@@ -17,17 +17,18 @@
namespace Catch {
using exceptionTranslateFunction = std::string(*)();
struct IExceptionTranslator;
class IExceptionTranslator;
using ExceptionTranslators = std::vector<Detail::unique_ptr<IExceptionTranslator const>>;
struct IExceptionTranslator {
class IExceptionTranslator {
public:
virtual ~IExceptionTranslator(); // = default
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
};
struct IExceptionTranslatorRegistry {
class IExceptionTranslatorRegistry {
public:
virtual ~IExceptionTranslatorRegistry(); // = default
virtual std::string translateActiveException() const = 0;
};

View File

@@ -33,7 +33,8 @@ namespace Catch {
} // namespace Generators
struct IGeneratorTracker {
class IGeneratorTracker {
public:
virtual ~IGeneratorTracker(); // = default;
virtual auto hasGenerator() const -> bool = 0;
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;

View File

@@ -16,21 +16,23 @@ namespace Catch {
class TestCaseHandle;
struct TestCaseInfo;
struct ITestCaseRegistry;
struct IExceptionTranslatorRegistry;
struct IExceptionTranslator;
struct IReporterRegistry;
struct IReporterFactory;
struct ITagAliasRegistry;
struct ITestInvoker;
struct IMutableEnumValuesRegistry;
class ITestCaseRegistry;
class IExceptionTranslatorRegistry;
class IExceptionTranslator;
class IReporterRegistry;
class IReporterFactory;
class ITagAliasRegistry;
class ITestInvoker;
class IMutableEnumValuesRegistry;
struct SourceLineInfo;
class StartupExceptionRegistry;
class EventListenerFactory;
using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
struct IRegistryHub {
class IRegistryHub {
public:
virtual ~IRegistryHub(); // = default
virtual IReporterRegistry const& getReporterRegistry() const = 0;
@@ -42,10 +44,11 @@ namespace Catch {
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
};
struct IMutableRegistryHub {
class IMutableRegistryHub {
public:
virtual ~IMutableRegistryHub(); // = default
virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0;
virtual void registerListener( IReporterFactoryPtr factory ) = 0;
virtual void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) = 0;
virtual void registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0;
virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;

View File

@@ -14,17 +14,38 @@
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/catch_test_case_info.hpp>
#include <catch2/reporters/catch_reporter_helpers.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_istream.hpp>
#include <algorithm>
#include <cassert>
#include <iomanip>
namespace Catch {
ReporterConfig::ReporterConfig( IConfig const* _fullConfig, std::ostream& _stream )
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
ReporterConfig::ReporterConfig(
IConfig const* _fullConfig,
Detail::unique_ptr<IStream> _stream,
ColourMode colourMode,
std::map<std::string, std::string> customOptions ):
m_stream( CATCH_MOVE(_stream) ),
m_fullConfig( _fullConfig ),
m_colourMode( colourMode ),
m_customOptions( CATCH_MOVE( customOptions ) ) {}
std::ostream& ReporterConfig::stream() const { return *m_stream; }
Detail::unique_ptr<IStream> ReporterConfig::takeStream() && {
assert( m_stream );
return CATCH_MOVE( m_stream );
}
IConfig const * ReporterConfig::fullConfig() const { return m_fullConfig; }
ColourMode ReporterConfig::colourMode() const { return m_colourMode; }
std::map<std::string, std::string> const&
ReporterConfig::customOptions() const {
return m_customOptions;
}
ReporterConfig::~ReporterConfig() = default;
AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages,
@@ -78,6 +99,6 @@ namespace Catch {
aborting( _aborting )
{}
IStreamingReporter::~IStreamingReporter() = default;
IEventListener::~IEventListener() = default;
} // end namespace Catch

View File

@@ -19,6 +19,7 @@
#include <catch2/benchmark/catch_outlier_classification.hpp>
#include <map>
#include <string>
#include <vector>
#include <iosfwd>
@@ -29,17 +30,30 @@ namespace Catch {
struct TagInfo;
struct TestCaseInfo;
class TestCaseHandle;
struct IConfig;
class IConfig;
class IStream;
enum class ColourMode : std::uint8_t;
struct ReporterConfig {
ReporterConfig( IConfig const* _fullConfig, std::ostream& _stream );
ReporterConfig( IConfig const* _fullConfig,
Detail::unique_ptr<IStream> _stream,
ColourMode colourMode,
std::map<std::string, std::string> customOptions );
std::ostream& stream() const;
ReporterConfig( ReporterConfig&& ) = default;
ReporterConfig& operator=( ReporterConfig&& ) = default;
~ReporterConfig(); // = default
Detail::unique_ptr<IStream> takeStream() &&;
IConfig const* fullConfig() const;
ColourMode colourMode() const;
std::map<std::string, std::string> const& customOptions() const;
private:
std::ostream* m_stream;
Detail::unique_ptr<IStream> m_stream;
IConfig const* m_fullConfig;
ColourMode m_colourMode;
std::map<std::string, std::string> m_customOptions;
};
struct TestRunInfo {
@@ -149,8 +163,19 @@ namespace Catch {
bool shouldReportAllAssertions = false;
};
//! The common base for all reporters and event listeners
struct IStreamingReporter {
/**
* The common base for all reporters and event listeners
*
* Implementing classes must also implement:
*
* //! User-friendly description of the reporter/listener type
* static std::string getDescription()
*
* Generally shouldn't be derived from by users of Catch2 directly,
* instead they should derive from one of the utility bases that
* derive from this class.
*/
class IEventListener {
protected:
//! Derived classes can set up their preferences here
ReporterPreferences m_preferences;
@@ -158,9 +183,9 @@ namespace Catch {
IConfig const* m_config;
public:
IStreamingReporter( IConfig const* config ): m_config( config ) {}
IEventListener( IConfig const* config ): m_config( config ) {}
virtual ~IStreamingReporter(); // = default;
virtual ~IEventListener(); // = default;
// Implementing class must also provide the following static methods:
// static std::string getDescription();
@@ -230,7 +255,7 @@ namespace Catch {
virtual void listTags(std::vector<TagInfo> const& tags) = 0;
};
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>;
using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
} // end namespace Catch

View File

@@ -15,18 +15,27 @@
namespace Catch {
struct ReporterConfig;
struct IStreamingReporter;
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>;
class IConfig;
class IEventListener;
using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
struct IReporterFactory {
class IReporterFactory {
public:
virtual ~IReporterFactory(); // = default
virtual IStreamingReporterPtr
create( ReporterConfig const& config ) const = 0;
virtual IEventListenerPtr
create( ReporterConfig&& config ) const = 0;
virtual std::string getDescription() const = 0;
};
using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
class EventListenerFactory {
public:
virtual ~EventListenerFactory(); // = default
virtual IEventListenerPtr create( IConfig const* config ) const = 0;
virtual std::string getDescription() const = 0;
};
} // namespace Catch
#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED

View File

@@ -17,20 +17,22 @@
namespace Catch {
struct IConfig;
class IConfig;
struct IStreamingReporter;
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>;
struct IReporterFactory;
class IEventListener;
using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
class IReporterFactory;
using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
struct ReporterConfig;
class EventListenerFactory;
struct IReporterRegistry {
class IReporterRegistry {
public:
using FactoryMap = std::map<std::string, IReporterFactoryPtr, Detail::CaseInsensitiveLess>;
using Listeners = std::vector<IReporterFactoryPtr>;
using Listeners = std::vector<Detail::unique_ptr<EventListenerFactory>>;
virtual ~IReporterRegistry(); // = default
virtual IStreamingReporterPtr create( std::string const& name, ReporterConfig const& config ) const = 0;
virtual IEventListenerPtr create( std::string const& name, ReporterConfig&& config ) const = 0;
virtual FactoryMap const& getFactories() const = 0;
virtual Listeners const& getListeners() const = 0;
};

View File

@@ -14,7 +14,8 @@ namespace Catch {
struct TagAlias;
struct ITagAliasRegistry {
class ITagAliasRegistry {
public:
virtual ~ITagAliasRegistry(); // = default
// Nullptr if not present
virtual TagAlias const* find( std::string const& alias ) const = 0;

View File

@@ -15,15 +15,17 @@ namespace Catch {
class TestSpec;
struct TestCaseInfo;
struct ITestInvoker {
class ITestInvoker {
public:
virtual void invoke () const = 0;
virtual ~ITestInvoker(); // = default
};
class TestCaseHandle;
struct IConfig;
class IConfig;
struct ITestCaseRegistry {
class ITestCaseRegistry {
public:
virtual ~ITestCaseRegistry(); // = default
// TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later
virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0;

View File

@@ -13,11 +13,11 @@
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/internal/catch_lazy_expr.hpp>
#include <string>
namespace Catch {
struct AssertionResultData;
struct IResultCapture;
class RunContext;
class IResultCapture;
struct AssertionReaction {
bool shouldDebugBreak = false;

View File

@@ -10,8 +10,6 @@
#include <catch2/internal/catch_stringref.hpp>
#include <string>
namespace Catch {
namespace Detail {
//! Provides case-insensitive `op<` semantics when called

View File

@@ -5,13 +5,16 @@
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <algorithm>
#include <catch2/internal/catch_clara.hpp>
#include <catch2/internal/catch_console_width.hpp>
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <algorithm>
#include <ostream>
namespace {
bool isOptPrefix( char c ) {
return c == '-'

View File

@@ -34,7 +34,6 @@
#include <catch2/internal/catch_void_type.hpp>
#include <cassert>
#include <cctype>
#include <memory>
#include <ostream>
#include <sstream>
@@ -589,12 +588,6 @@ namespace Catch {
std::shared_ptr<std::string> m_name;
std::shared_ptr<Detail::BoundValueRefBase> m_ref;
template <typename LambdaT>
static auto makeRef(LambdaT const& lambda)
-> std::shared_ptr<Detail::BoundValueRefBase> {
return std::make_shared<Detail::BoundLambda<LambdaT>>(lambda);
}
public:
ExeName();
explicit ExeName(std::string& ref);

View File

@@ -12,9 +12,9 @@
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_registry.hpp>
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/internal/catch_reporter_spec_parser.hpp>
#include <algorithm>
#include <fstream>
#include <string>
@@ -95,19 +95,23 @@ namespace Catch {
return ParserResult::runtimeError("Could not parse '" + seed + "' as seed");
}
};
auto const setColourUsage = [&]( std::string const& useColour ) {
auto mode = toLower( useColour );
if( mode == "yes" )
config.useColour = UseColour::Yes;
else if( mode == "no" )
config.useColour = UseColour::No;
else if( mode == "auto" )
config.useColour = UseColour::Auto;
else
return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
if ( !maybeMode ) {
return ParserResult::runtimeError(
"colour mode must be one of: default, ansi, win32, "
"or none. '" +
colourMode + "' is not recognised" );
}
auto mode = *maybeMode;
if ( !isColourImplAvailable( mode ) ) {
return ParserResult::runtimeError(
"colour mode '" + colourMode +
"' is not supported in this binary" );
}
config.defaultColourMode = mode;
return ParserResult::ok( ParseResultType::Matched );
};
auto const setWaitForKeypress = [&]( std::string const& keypress ) {
auto keypressLc = toLower( keypress );
if (keypressLc == "never")
@@ -134,64 +138,42 @@ namespace Catch {
return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' );
return ParserResult::ok( ParseResultType::Matched );
};
auto const setReporter = [&]( std::string const& reporterSpec ) {
if ( reporterSpec.empty() ) {
auto const setReporter = [&]( std::string const& userReporterSpec ) {
if ( userReporterSpec.empty() ) {
return ParserResult::runtimeError( "Received empty reporter spec." );
}
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Optional<ReporterSpec> parsed =
parseReporterSpec( userReporterSpec );
if ( !parsed ) {
return ParserResult::runtimeError(
"Could not parse reporter spec '" + userReporterSpec +
"'" );
}
// clear the default reporter
if (!config._nonDefaultReporterSpecifications) {
config.reporterSpecifications.clear();
config._nonDefaultReporterSpecifications = true;
auto const& reporterSpec = *parsed;
IReporterRegistry::FactoryMap const& factories =
getRegistryHub().getReporterRegistry().getFactories();
auto result = factories.find( reporterSpec.name() );
if ( result == factories.end() ) {
return ParserResult::runtimeError(
"Unrecognized reporter, '" + reporterSpec.name() +
"'. Check available with --list-reporters" );
}
// Exactly one of the reporters may be specified without an output
// file, in which case it defaults to the output specified by "-o"
// (or standard output).
static constexpr auto separator = "::";
static constexpr size_t separatorSize = 2;
auto fileNameSeparatorPos = reporterSpec.find( separator );
const bool containsFileName = fileNameSeparatorPos != reporterSpec.npos;
if ( containsFileName ) {
auto nextSeparatorPos = reporterSpec.find(
separator, fileNameSeparatorPos + separatorSize );
if ( nextSeparatorPos != reporterSpec.npos ) {
return ParserResult::runtimeError(
"Too many separators in reporter spec '" + reporterSpec + '\'' );
}
}
std::string reporterName;
Optional<std::string> outputFileName;
reporterName = reporterSpec.substr( 0, fileNameSeparatorPos );
if ( reporterName.empty() ) {
return ParserResult::runtimeError( "Reporter name cannot be empty." );
}
if ( containsFileName ) {
outputFileName = reporterSpec.substr(
fileNameSeparatorPos + separatorSize, reporterSpec.size() );
}
auto result = factories.find( reporterName );
if( result == factories.end() )
return ParserResult::runtimeError( "Unrecognized reporter, '" + reporterName + "'. Check available with --list-reporters" );
if( containsFileName && outputFileName->empty() )
return ParserResult::runtimeError( "Reporter '" + reporterName + "' has empty filename specified as its output. Supply a filename or remove the colons to use the default output." );
config.reporterSpecifications.push_back({ std::move(reporterName), std::move(outputFileName) });
// It would be enough to check this only once at the very end, but there is
// not a place where we could call this check, so do it every time it could fail.
// For valid inputs, this is still called at most once.
if (!containsFileName) {
const bool hadOutputFile = reporterSpec.outputFile().some();
config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
// It would be enough to check this only once at the very end, but
// there is not a place where we could call this check, so do it
// every time it could fail. For valid inputs, this is still called
// at most once.
if (!hadOutputFile) {
int n_reporters_without_file = 0;
for (auto const& spec : config.reporterSpecifications) {
if (spec.outputFileName.none()) {
if (spec.outputFile().none()) {
n_reporters_without_file++;
}
}
@@ -257,7 +239,7 @@ namespace Catch {
| Opt( config.defaultOutputFilename, "filename" )
["-o"]["--out"]
( "default output filename" )
| Opt( accept_many, setReporter, "name[:output-file]" )
| Opt( accept_many, setReporter, "name[::key=value]*" )
["-r"]["--reporter"]
( "reporter to use (defaults to console)" )
| Opt( config.name, "name" )
@@ -305,9 +287,9 @@ namespace Catch {
| Opt( setRngSeed, "'time'|'random-device'|number" )
["--rng-seed"]
( "set a specific seed for random numbers" )
| Opt( setColourUsage, "yes|no" )
["--use-colour"]
( "should output be colourised" )
| Opt( setDefaultColourMode, "ansi|win32|none|default" )
["--colour-mode"]
( "what color mode should be used as default" )
| Opt( config.libIdentify )
["--libidentify"]
( "report name and version according to libidentify standard" )

View File

@@ -25,6 +25,7 @@
// can be combined, en-mass, with the _NO_ forms later.
#include <catch2/internal/catch_platform.hpp>
#include <catch2/catch_user_config.hpp>
#ifdef __cplusplus
@@ -115,7 +116,6 @@
#ifdef __OS400__
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# define CATCH_CONFIG_COLOUR_NONE
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -163,7 +163,7 @@
// Universal Windows platform does not support SEH
// Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
# define CATCH_CONFIG_COLOUR_NONE
# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
# else
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif
@@ -205,7 +205,7 @@
#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
#define CATCH_INTERNAL_CONFIG_NO_ASYNC
#define CATCH_CONFIG_COLOUR_NONE
#define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
#endif
#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
@@ -287,7 +287,9 @@
# define CATCH_CONFIG_NEW_CAPTURE
#endif
#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
#if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \
!defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) && \
!defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS )
# define CATCH_CONFIG_DISABLE_EXCEPTIONS
#endif
@@ -355,4 +357,12 @@
#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#endif
#if defined( CATCH_PLATFORM_WINDOWS ) && \
!defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
!defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \
!defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 )
# define CATCH_CONFIG_COLOUR_WIN32
#endif
#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED

View File

@@ -17,6 +17,8 @@
#ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
#include <catch2/catch_user_config.hpp>
#if defined(__ANDROID__)
# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
#endif

View File

@@ -15,59 +15,115 @@
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_errno_guard.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_istream.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_debugger.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <cassert>
#include <ostream>
#include <utility>
namespace Catch {
ColourImpl::~ColourImpl() = default;
ColourImpl::ColourGuard ColourImpl::guardColour( Colour::Code colourCode ) {
return ColourGuard(colourCode, this );
}
void ColourImpl::ColourGuard::engageImpl( std::ostream& stream ) {
assert( &stream == &m_colourImpl->m_stream->stream() &&
"Engaging colour guard for different stream than used by the "
"parent colour implementation" );
static_cast<void>( stream );
m_engaged = true;
m_colourImpl->use( m_code );
}
ColourImpl::ColourGuard::ColourGuard( Colour::Code code,
ColourImpl const* colour ):
m_colourImpl( colour ), m_code( code ) {
}
ColourImpl::ColourGuard::ColourGuard( ColourGuard&& rhs ) noexcept:
m_colourImpl( rhs.m_colourImpl ),
m_code( rhs.m_code ),
m_engaged( rhs.m_engaged ) {
rhs.m_engaged = false;
}
ColourImpl::ColourGuard&
ColourImpl::ColourGuard::operator=( ColourGuard&& rhs ) noexcept {
using std::swap;
swap( m_colourImpl, rhs.m_colourImpl );
swap( m_code, rhs.m_code );
swap( m_engaged, rhs.m_engaged );
return *this;
}
ColourImpl::ColourGuard::~ColourGuard() {
if ( m_engaged ) {
m_colourImpl->use( Colour::None );
}
}
ColourImpl::ColourGuard&
ColourImpl::ColourGuard::engage( std::ostream& stream ) & {
engageImpl( stream );
return *this;
}
ColourImpl::ColourGuard&&
ColourImpl::ColourGuard::engage( std::ostream& stream ) && {
engageImpl( stream );
return CATCH_MOVE(*this);
}
namespace {
//! A do-nothing implementation of colour, used as fallback for unknown
//! platforms, and when the user asks to deactivate all colours.
class NoColourImpl : public ColourImpl {
public:
NoColourImpl( IStream* stream ): ColourImpl( stream ) {}
static bool useColourOnPlatform() { return true; }
struct IColourImpl {
virtual ~IColourImpl() = default;
virtual void use( Colour::Code _colourCode ) = 0;
private:
void use( Colour::Code ) const override {}
};
} // namespace
struct NoColourImpl : IColourImpl {
void use( Colour::Code ) override {}
static IColourImpl* instance() {
static NoColourImpl s_instance;
return &s_instance;
}
};
} // anon namespace
} // namespace Catch
#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
# ifdef CATCH_PLATFORM_WINDOWS
# define CATCH_CONFIG_COLOUR_WINDOWS
# else
# define CATCH_CONFIG_COLOUR_ANSI
# endif
#endif
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
#if defined ( CATCH_CONFIG_COLOUR_WIN32 ) /////////////////////////////////////////
namespace Catch {
namespace {
class Win32ColourImpl : public IColourImpl {
class Win32ColourImpl : public ColourImpl {
public:
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
{
Win32ColourImpl(IStream* stream):
ColourImpl(stream) {
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ),
&csbiInfo );
originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
}
void use( Colour::Code _colourCode ) override {
static bool useColourOnPlatform(IStream const& stream) {
// Win32 text colour APIs can only be used on console streams
// We cannot check that the output hasn't been redirected,
// so we just check that the original stream is console stream.
return stream.isConsole();
}
private:
void use( Colour::Code _colourCode ) const override {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -91,45 +147,63 @@ namespace {
}
}
private:
void setTextAttribute( WORD _textAttribute ) {
SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
void setTextAttribute( WORD _textAttribute ) const {
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ),
_textAttribute |
originalBackgroundAttributes );
}
HANDLE stdoutHandle;
WORD originalForegroundAttributes;
WORD originalBackgroundAttributes;
};
IColourImpl* platformColourInstance() {
static Win32ColourImpl s_instance;
auto const* config = getCurrentContext().getConfig();
UseColour colourMode = config?
config->useColour() : UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = UseColour::Yes;
return colourMode == UseColour::Yes
? &s_instance
: NoColourImpl::instance();
}
} // end anon namespace
} // end namespace Catch
#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
#endif // Windows/ ANSI/ None
#include <unistd.h>
#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC )
# define CATCH_INTERNAL_HAS_ISATTY
# include <unistd.h>
#endif
namespace Catch {
namespace {
// use POSIX/ ANSI console terminal codes
// Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
class ANSIColourImpl : public ColourImpl {
public:
void use( Colour::Code _colourCode ) override {
ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {}
static bool useColourOnPlatform(IStream const& stream) {
// This is kinda messy due to trying to support a bunch of
// different platforms at once.
// The basic idea is that if we are asked to do autodetection (as
// opposed to being told to use posixy colours outright), then we
// only want to use the colours if we are writing to console.
// However, console might be redirected, so we make an attempt at
// checking for that on platforms where we know how to do that.
bool useColour = stream.isConsole();
#if defined( CATCH_INTERNAL_HAS_ISATTY ) && \
!( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) )
ErrnoGuard _; // for isatty
useColour = useColour && isatty( STDOUT_FILENO );
# endif
# if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE )
useColour = useColour && !isDebuggerActive();
# endif
return useColour;
}
private:
void use( Colour::Code _colourCode ) const override {
auto setColour = [&out =
m_stream->stream()]( char const* escapeCode ) {
// The escape sequence must be flushed to console, otherwise
// if stdin and stderr are intermixed, we'd get accidentally
// coloured output.
out << '\033' << escapeCode << std::flush;
};
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@@ -150,89 +224,59 @@ namespace {
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
}
}
static IColourImpl* instance() {
static PosixColourImpl s_instance;
return &s_instance;
}
private:
void setColour( const char* _escapeCode ) {
// The escape sequence must be flushed to console, otherwise if
// stdin and stderr are intermixed, we'd get accidentally coloured output.
getCurrentContext().getConfig()->defaultStream()
<< '\033' << _escapeCode << std::flush;
}
};
bool useColourOnPlatform() {
return
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
!isDebuggerActive() &&
#endif
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
isatty(STDOUT_FILENO)
#else
false
#endif
;
}
IColourImpl* platformColourInstance() {
ErrnoGuard guard;
auto const* config = getCurrentContext().getConfig();
UseColour colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = useColourOnPlatform()
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes
? PosixColourImpl::instance()
: NoColourImpl::instance();
}
} // end anon namespace
} // end namespace Catch
#else // not Windows or ANSI ///////////////////////////////////////////////
namespace Catch {
static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode implSelection,
IStream* stream ) {
if ( implSelection == ColourMode::None ) {
return Detail::make_unique<NoColourImpl>( stream );
}
if ( implSelection == ColourMode::ANSI ) {
return Detail::make_unique<ANSIColourImpl>( stream );
}
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
if ( implSelection == ColourMode::Win32 ) {
return Detail::make_unique<Win32ColourImpl>( stream );
}
#endif
} // end namespace Catch
// todo: check win32 eligibility under ifdef, otherwise ansi
if ( implSelection == ColourMode::PlatformDefault) {
#if defined (CATCH_CONFIG_COLOUR_WIN32)
if ( Win32ColourImpl::useColourOnPlatform( *stream ) ) {
return Detail::make_unique<Win32ColourImpl>( stream );
} else {
return Detail::make_unique<NoColourImpl>( stream );
}
#endif
if ( ANSIColourImpl::useColourOnPlatform( *stream ) ) {
return Detail::make_unique<ANSIColourImpl>( stream );
}
return Detail::make_unique<NoColourImpl>( stream );
}
#endif // Windows/ ANSI/ None
namespace Catch {
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour::Colour( Colour&& other ) noexcept {
m_moved = other.m_moved;
other.m_moved = true;
}
Colour& Colour::operator=( Colour&& other ) noexcept {
m_moved = other.m_moved;
other.m_moved = true;
return *this;
CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(implSelection) );
}
Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) {
static IColourImpl* impl = platformColourInstance();
// Strictly speaking, this cannot possibly happen.
// However, under some conditions it does happen (see #1626),
// and this change is small enough that we can let practicality
// triumph over purity in this case.
if (impl != nullptr) {
impl->use( _colourCode );
bool isColourImplAvailable( ColourMode colourSelection ) {
switch ( colourSelection ) {
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
case ColourMode::Win32:
#endif
case ColourMode::ANSI:
case ColourMode::None:
case ColourMode::PlatformDefault:
return true;
default:
return false;
}
}
std::ostream& operator << ( std::ostream& os, Colour const& ) {
return os;
}
} // end namespace Catch

View File

@@ -8,10 +8,16 @@
#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
#include <catch2/internal/catch_unique_ptr.hpp>
#include <iosfwd>
#include <cstdint>
namespace Catch {
enum class ColourMode : std::uint8_t;
class IStream;
struct Colour {
enum Code {
None = 0,
@@ -48,22 +54,86 @@ namespace Catch {
SecondaryText = LightGrey,
Headers = White
};
// Use constructed object for RAII guard
Colour( Code _colourCode );
Colour( Colour&& other ) noexcept;
Colour& operator=( Colour&& other ) noexcept;
~Colour();
// Use static method for one-shot changes
static void use( Code _colourCode );
private:
bool m_moved = false;
friend std::ostream& operator << (std::ostream& os, Colour const&);
};
class ColourImpl {
protected:
//! The associated stream of this ColourImpl instance
IStream* m_stream;
public:
ColourImpl( IStream* stream ): m_stream( stream ) {}
//! RAII wrapper around writing specific colour of text using specific
//! colour impl into a stream.
class ColourGuard {
ColourImpl const* m_colourImpl;
Colour::Code m_code;
bool m_engaged = false;
public:
//! Does **not** engage the guard/start the colour
ColourGuard( Colour::Code code,
ColourImpl const* colour );
ColourGuard( ColourGuard const& rhs ) = delete;
ColourGuard& operator=( ColourGuard const& rhs ) = delete;
ColourGuard( ColourGuard&& rhs ) noexcept;
ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
//! Removes colour _if_ the guard was engaged
~ColourGuard();
/**
* Explicitly engages colour for given stream.
*
* The API based on operator<< should be preferred.
*/
ColourGuard& engage( std::ostream& stream ) &;
/**
* Explicitly engages colour for given stream.
*
* The API based on operator<< should be preferred.
*/
ColourGuard&& engage( std::ostream& stream ) &&;
private:
//! Engages the guard and starts using colour
friend std::ostream& operator<<( std::ostream& lhs,
ColourGuard& guard ) {
guard.engageImpl( lhs );
return lhs;
}
//! Engages the guard and starts using colour
friend std::ostream& operator<<( std::ostream& lhs,
ColourGuard&& guard) {
guard.engageImpl( lhs );
return lhs;
}
void engageImpl( std::ostream& stream );
};
virtual ~ColourImpl(); // = default
/**
* Creates a guard object for given colour and this colour impl
*
* **Important:**
* the guard starts disengaged, and has to be engaged explicitly.
*/
ColourGuard guardColour( Colour::Code colourCode );
private:
virtual void use( Colour::Code colourCode ) const = 0;
};
//! Provides ColourImpl based on global config and target compilation platform
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
IStream* stream );
//! Checks if specific colour impl has been compiled into the binary
bool isColourImplAvailable( ColourMode colourSelection );
} // end namespace Catch

View File

@@ -10,19 +10,19 @@
namespace Catch {
struct IResultCapture;
struct IConfig;
class IResultCapture;
class IConfig;
struct IContext
{
class IContext {
public:
virtual ~IContext(); // = default
virtual IResultCapture* getResultCapture() = 0;
virtual IConfig const* getConfig() const = 0;
};
struct IMutableContext : IContext
{
class IMutableContext : public IContext {
public:
virtual ~IMutableContext(); // = default
virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
virtual void setConfig( IConfig const* config ) = 0;

View File

@@ -5,11 +5,16 @@
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_debug_console.hpp>
#include <catch2/internal/catch_config_android_logwrite.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/catch_user_config.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <ostream>
#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
#include <android/log.h>

View File

@@ -7,8 +7,8 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_debugger.hpp>
#include <catch2/internal/catch_errno_guard.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)

View File

@@ -33,7 +33,11 @@
namespace Catch {
struct ITransientExpression {
class ITransientExpression {
bool m_isBinaryExpression;
bool m_result;
public:
auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
auto getResult() const -> bool { return m_result; }
virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
@@ -51,8 +55,6 @@ namespace Catch {
// complain if it's not here :-(
virtual ~ITransientExpression(); // = default;
bool m_isBinaryExpression;
bool m_result;
friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
expr.streamReconstructedExpression(out);
return out;

View File

@@ -6,6 +6,7 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <stdexcept>

View File

@@ -10,7 +10,7 @@
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <exception>

View File

@@ -7,7 +7,6 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_enum_values_registry.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <cassert>

View File

@@ -30,6 +30,7 @@
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <algorithm>
@@ -40,7 +41,7 @@ namespace Catch {
// If neither SEH nor signal handling is required, the handler impls
// do not have to do anything, and can be empty.
void FatalConditionHandler::engage_platform() {}
void FatalConditionHandler::disengage_platform() {}
void FatalConditionHandler::disengage_platform() noexcept {}
FatalConditionHandler::FatalConditionHandler() = default;
FatalConditionHandler::~FatalConditionHandler() = default;
@@ -78,10 +79,10 @@ namespace Catch {
// Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently.
static SignalDefs signalDefs[] = {
{ static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" },
{ static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" },
{ static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" },
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
};
static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
@@ -124,9 +125,11 @@ namespace Catch {
previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
}
void FatalConditionHandler::disengage_platform() {
if (SetUnhandledExceptionFilter(reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(previousTopLevelExceptionFilter)) != topLevelExceptionFilter) {
CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter");
void FatalConditionHandler::disengage_platform() noexcept {
if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) {
Catch::cerr()
<< "Unexpected SEH unhandled exception filter on disengage."
<< " The filter was restored, but might be rolled back unexpectedly.";
}
previousTopLevelExceptionFilter = nullptr;
}
@@ -168,7 +171,7 @@ namespace Catch {
static stack_t oldSigStack{};
static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
static void restorePreviousSignalHandlers() {
static void restorePreviousSignalHandlers() noexcept {
// We set signal handlers back to the previous ones. Hopefully
// nobody overwrote them in the meantime, and doesn't expect
// their signal handlers to live past ours given that they
@@ -231,7 +234,7 @@ namespace Catch {
#endif
void FatalConditionHandler::disengage_platform() {
void FatalConditionHandler::disengage_platform() noexcept {
restorePreviousSignalHandlers();
}

View File

@@ -32,7 +32,7 @@ namespace Catch {
// Should be if-defed to work on current platform, can assume
// engage-disengage 1:1 pairing.
void engage_platform();
void disengage_platform();
void disengage_platform() noexcept;
public:
// Should also have platform-specific implementations as needed
FatalConditionHandler();
@@ -44,7 +44,7 @@ namespace Catch {
engage_platform();
}
void disengage() {
void disengage() noexcept {
assert(m_started && "Handler cannot be uninstalled without being installed first");
m_started = false;
disengage_platform();

View File

@@ -5,15 +5,14 @@
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_istream.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_debug_console.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
@@ -74,7 +73,7 @@ namespace Detail {
///////////////////////////////////////////////////////////////////////////
class FileStream : public IStream {
mutable std::ofstream m_ofs;
std::ofstream m_ofs;
public:
FileStream( std::string const& filename ) {
m_ofs.open( filename.c_str() );
@@ -82,7 +81,7 @@ namespace Detail {
}
~FileStream() override = default;
public: // IStream
std::ostream& stream() const override {
std::ostream& stream() override {
return m_ofs;
}
};
@@ -90,7 +89,7 @@ namespace Detail {
///////////////////////////////////////////////////////////////////////////
class CoutStream : public IStream {
mutable std::ostream m_os;
std::ostream m_os;
public:
// Store the streambuf from cout up-front because
// cout may get redirected when running tests
@@ -98,14 +97,29 @@ namespace Detail {
~CoutStream() override = default;
public: // IStream
std::ostream& stream() const override { return m_os; }
std::ostream& stream() override { return m_os; }
bool isConsole() const override { return true; }
};
class CerrStream : public IStream {
std::ostream m_os;
public:
// Store the streambuf from cerr up-front because
// cout may get redirected when running tests
CerrStream(): m_os( Catch::cerr().rdbuf() ) {}
~CerrStream() override = default;
public: // IStream
std::ostream& stream() override { return m_os; }
bool isConsole() const override { return true; }
};
///////////////////////////////////////////////////////////////////////////
class DebugOutStream : public IStream {
Detail::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
mutable std::ostream m_os;
std::ostream m_os;
public:
DebugOutStream()
: m_streamBuf( Detail::make_unique<StreamBufImpl<OutputDebugWriter>>() ),
@@ -115,7 +129,7 @@ namespace Detail {
~DebugOutStream() override = default;
public: // IStream
std::ostream& stream() const override { return m_os; }
std::ostream& stream() override { return m_os; }
};
} // unnamed namespace
@@ -123,71 +137,22 @@ namespace Detail {
///////////////////////////////////////////////////////////////////////////
auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream const> {
auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream> {
if ( filename.empty() || filename == "-" ) {
return Detail::make_unique<Detail::CoutStream>();
}
else if( filename[0] == '%' ) {
if( filename == "%debug" )
if( filename[0] == '%' ) {
if ( filename == "%debug" ) {
return Detail::make_unique<Detail::DebugOutStream>();
else
} else if ( filename == "%stderr" ) {
return Detail::make_unique<Detail::CerrStream>();
} else if ( filename == "%stdout" ) {
return Detail::make_unique<Detail::CoutStream>();
} else {
CATCH_ERROR( "Unrecognised stream: '" << filename << '\'' );
}
else
return Detail::make_unique<Detail::FileStream>( filename );
}
// This class encapsulates the idea of a pool of ostringstreams that can be reused.
struct StringStreams {
std::vector<Detail::unique_ptr<std::ostringstream>> m_streams;
std::vector<std::size_t> m_unused;
std::ostringstream m_referenceStream; // Used for copy state/ flags from
auto add() -> std::size_t {
if( m_unused.empty() ) {
m_streams.push_back( Detail::make_unique<std::ostringstream>() );
return m_streams.size()-1;
}
else {
auto index = m_unused.back();
m_unused.pop_back();
return index;
}
}
void release( std::size_t index ) {
m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
m_unused.push_back(index);
}
};
ReusableStringStream::ReusableStringStream()
: m_index( Singleton<StringStreams>::getMutable().add() ),
m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
{}
ReusableStringStream::~ReusableStringStream() {
static_cast<std::ostringstream*>( m_oss )->str("");
m_oss->clear();
Singleton<StringStreams>::getMutable().release( m_index );
return Detail::make_unique<Detail::FileStream>( filename );
}
std::string ReusableStringStream::str() const {
return static_cast<std::ostringstream*>( m_oss )->str();
}
void ReusableStringStream::str( std::string const& str ) {
static_cast<std::ostringstream*>( m_oss )->str( str );
}
///////////////////////////////////////////////////////////////////////////
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
std::ostream& cout() { return std::cout; }
std::ostream& cerr() { return std::cerr; }
std::ostream& clog() { return std::clog; }
#endif
}

View File

@@ -0,0 +1,54 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_ISTREAM_HPP_INCLUDED
#define CATCH_ISTREAM_HPP_INCLUDED
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <iosfwd>
#include <cstddef>
#include <ostream>
#include <string>
namespace Catch {
class IStream {
public:
virtual ~IStream(); // = default
virtual std::ostream& stream() = 0;
/**
* Best guess on whether the instance is writing to a console (e.g. via stdout/stderr)
*
* This is useful for e.g. Win32 colour support, because the Win32
* API manipulates console directly, unlike POSIX escape codes,
* that can be written anywhere.
*
* Due to variety of ways to change where the stdout/stderr is
* _actually_ being written, users should always assume that
* the answer might be wrong.
*/
virtual bool isConsole() const { return false; }
};
/**
* Creates a stream wrapper that writes to specific file.
*
* Also recognizes 4 special filenames
* * `-` for stdout
* * `%stdout` for stdout
* * `%stderr` for stderr
* * `%debug` for platform specific debugging output
*
* \throws if passed an unrecognized %-prefixed stream
*/
auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>;
}
#endif // CATCH_STREAM_HPP_INCLUDED

View File

@@ -12,7 +12,7 @@
namespace Catch {
struct ITransientExpression;
class ITransientExpression;
class LazyExpression {
friend class AssertionHandler;

View File

@@ -23,13 +23,13 @@
namespace Catch {
namespace {
void listTests(IStreamingReporter& reporter, IConfig const& config) {
void listTests(IEventListener& reporter, IConfig const& config) {
auto const& testSpec = config.testSpec();
auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
reporter.listTests(matchedTestCases);
}
void listTags(IStreamingReporter& reporter, IConfig const& config) {
void listTags(IEventListener& reporter, IConfig const& config) {
auto const& testSpec = config.testSpec();
std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
@@ -51,7 +51,7 @@ namespace Catch {
reporter.listTags(infos);
}
void listReporters(IStreamingReporter& reporter) {
void listReporters(IEventListener& reporter) {
std::vector<ReporterDescription> descriptions;
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
@@ -86,7 +86,7 @@ namespace Catch {
return out;
}
bool list( IStreamingReporter& reporter, Config const& config ) {
bool list( IEventListener& reporter, Config const& config ) {
bool listed = false;
if (config.listTests()) {
listed = true;

View File

@@ -16,7 +16,7 @@
namespace Catch {
struct IStreamingReporter;
class IEventListener;
class Config;
@@ -32,7 +32,7 @@ namespace Catch {
std::size_t count = 0;
};
bool list( IStreamingReporter& reporter, Config const& config );
bool list( IEventListener& reporter, Config const& config );
} // end namespace Catch

View File

@@ -8,6 +8,8 @@
#ifndef CATCH_OPTIONAL_HPP_INCLUDED
#define CATCH_OPTIONAL_HPP_INCLUDED
#include <cassert>
namespace Catch {
// An optional type

View File

@@ -7,6 +7,7 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_output_redirect.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <cstdio>
#include <cstring>

View File

@@ -9,7 +9,8 @@
#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <cstdio>
#include <iosfwd>

View File

@@ -8,6 +8,7 @@
#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED
#define CATCH_PREPROCESSOR_HPP_INCLUDED
#include <catch2/internal/catch_preprocessor_remove_parens.hpp>
#if defined(__GNUC__)
// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work
@@ -59,10 +60,6 @@
#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_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
@@ -77,8 +74,6 @@
#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))

View File

@@ -0,0 +1,19 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
#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__ )
#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED

View File

@@ -17,6 +17,7 @@
#include <catch2/reporters/catch_reporter_teamcity.hpp>
#include <catch2/reporters/catch_reporter_xml.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_enforce.hpp>
namespace Catch {
@@ -36,17 +37,20 @@ namespace Catch {
ReporterRegistry::~ReporterRegistry() = default;
IStreamingReporterPtr ReporterRegistry::create( std::string const& name, ReporterConfig const& config ) const {
IEventListenerPtr ReporterRegistry::create( std::string const& name, ReporterConfig&& config ) const {
auto it = m_factories.find( name );
if( it == m_factories.end() )
return nullptr;
return it->second->create( config );
return it->second->create( CATCH_MOVE(config) );
}
void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr factory ) {
CATCH_ENFORCE( name.find( "::" ) == name.npos,
"'::' is not allowed in reporter name: '" + name + '\'' );
m_factories.emplace(name, CATCH_MOVE(factory));
}
void ReporterRegistry::registerListener( IReporterFactoryPtr factory ) {
void ReporterRegistry::registerListener(
Detail::unique_ptr<EventListenerFactory> factory ) {
m_listeners.push_back( CATCH_MOVE(factory) );
}

View File

@@ -21,10 +21,10 @@ namespace Catch {
ReporterRegistry();
~ReporterRegistry() override; // = default, out of line to allow fwd decl
IStreamingReporterPtr create( std::string const& name, ReporterConfig const& config ) const override;
IEventListenerPtr create( std::string const& name, ReporterConfig&& config ) const override;
void registerReporter( std::string const& name, IReporterFactoryPtr factory );
void registerListener( IReporterFactoryPtr factory );
void registerListener( Detail::unique_ptr<EventListenerFactory> factory );
FactoryMap const& getFactories() const override;
Listeners const& getListeners() const override;

View File

@@ -0,0 +1,173 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_reporter_spec_parser.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <algorithm>
namespace Catch {
namespace {
struct kvPair {
StringRef key, value;
};
kvPair splitKVPair(StringRef kvString) {
auto splitPos = static_cast<size_t>( std::distance(
kvString.begin(),
std::find( kvString.begin(), kvString.end(), '=' ) ) );
return { kvString.substr( 0, splitPos ),
kvString.substr( splitPos + 1, kvString.size() ) };
}
}
namespace Detail {
std::vector<std::string> splitReporterSpec( StringRef reporterSpec ) {
static constexpr auto separator = "::";
static constexpr size_t separatorSize = 2;
size_t separatorPos = 0;
auto findNextSeparator = [&reporterSpec]( size_t startPos ) {
static_assert(
separatorSize == 2,
"The code below currently assumes 2 char separator" );
auto currentPos = startPos;
do {
while ( currentPos < reporterSpec.size() &&
reporterSpec[currentPos] != separator[0] ) {
++currentPos;
}
if ( currentPos + 1 < reporterSpec.size() &&
reporterSpec[currentPos + 1] == separator[1] ) {
return currentPos;
}
++currentPos;
} while ( currentPos < reporterSpec.size() );
return static_cast<size_t>( -1 );
};
std::vector<std::string> parts;
while ( separatorPos < reporterSpec.size() ) {
const auto nextSeparator = findNextSeparator( separatorPos );
parts.push_back( static_cast<std::string>( reporterSpec.substr(
separatorPos, nextSeparator - separatorPos ) ) );
if ( nextSeparator == static_cast<size_t>( -1 ) ) {
break;
}
separatorPos = nextSeparator + separatorSize;
}
// Handle a separator at the end.
// This is not a valid spec, but we want to do validation in a
// centralized place
if ( separatorPos == reporterSpec.size() ) {
parts.emplace_back();
}
return parts;
}
Optional<ColourMode> stringToColourMode( StringRef colourMode ) {
if ( colourMode == "default" ) {
return ColourMode::PlatformDefault;
} else if ( colourMode == "ansi" ) {
return ColourMode::ANSI;
} else if ( colourMode == "win32" ) {
return ColourMode::Win32;
} else if ( colourMode == "none" ) {
return ColourMode::None;
} else {
return {};
}
}
} // namespace Detail
bool operator==( ReporterSpec const& lhs, ReporterSpec const& rhs ) {
return lhs.m_name == rhs.m_name &&
lhs.m_outputFileName == rhs.m_outputFileName &&
lhs.m_colourMode == rhs.m_colourMode &&
lhs.m_customOptions == rhs.m_customOptions;
}
Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ) {
auto parts = Detail::splitReporterSpec( reporterSpec );
assert( parts.size() > 0 && "Split should never return empty vector" );
std::map<std::string, std::string> kvPairs;
Optional<std::string> outputFileName;
Optional<ColourMode> colourMode;
// First part is always reporter name, so we skip it
for ( size_t i = 1; i < parts.size(); ++i ) {
auto kv = splitKVPair( parts[i] );
auto key = kv.key, value = kv.value;
if ( key.empty() || value.empty() ) {
return {};
} else if ( key[0] == 'X' ) {
// This is a reporter-specific option, we don't check these
// apart from basic sanity checks
if ( key.size() == 1 ) {
return {};
}
auto ret = kvPairs.emplace( kv.key, kv.value );
if ( !ret.second ) {
// Duplicated key. We might want to handle this differently,
// e.g. by overwriting the existing value?
return {};
}
} else if ( key == "out" ) {
// Duplicated key
if ( outputFileName ) {
return {};
}
outputFileName = static_cast<std::string>( value );
} else if ( key == "colour-mode" ) {
// Duplicated key
if ( colourMode ) {
return {};
}
colourMode = Detail::stringToColourMode( value );
// Parsing failed
if ( !colourMode ) {
return {};
}
} else {
// Unrecognized option
return {};
}
}
return ReporterSpec{ CATCH_MOVE( parts[0] ),
CATCH_MOVE( outputFileName ),
CATCH_MOVE( colourMode ),
CATCH_MOVE( kvPairs ) };
}
ReporterSpec::ReporterSpec(
std::string name,
Optional<std::string> outputFileName,
Optional<ColourMode> colourMode,
std::map<std::string, std::string> customOptions ):
m_name( CATCH_MOVE( name ) ),
m_outputFileName( CATCH_MOVE( outputFileName ) ),
m_colourMode( CATCH_MOVE( colourMode ) ),
m_customOptions( CATCH_MOVE( customOptions ) ) {}
} // namespace Catch

View File

@@ -0,0 +1,85 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <map>
#include <string>
#include <vector>
namespace Catch {
enum class ColourMode : std::uint8_t;
namespace Detail {
//! Splits the reporter spec into reporter name and kv-pair options
std::vector<std::string> splitReporterSpec( StringRef reporterSpec );
Optional<ColourMode> stringToColourMode( StringRef colourMode );
}
/**
* Structured reporter spec that a reporter can be created from
*
* Parsing has been validated, but semantics have not. This means e.g.
* that the colour mode is known to Catch2, but it might not be
* compiled into the binary, and the output filename might not be
* openable.
*/
class ReporterSpec {
std::string m_name;
Optional<std::string> m_outputFileName;
Optional<ColourMode> m_colourMode;
std::map<std::string, std::string> m_customOptions;
friend bool operator==( ReporterSpec const& lhs,
ReporterSpec const& rhs );
friend bool operator!=( ReporterSpec const& lhs,
ReporterSpec const& rhs ) {
return !( lhs == rhs );
}
public:
ReporterSpec(
std::string name,
Optional<std::string> outputFileName,
Optional<ColourMode> colourMode,
std::map<std::string, std::string> customOptions );
std::string const& name() const { return m_name; }
Optional<std::string> const& outputFile() const {
return m_outputFileName;
}
Optional<ColourMode> const& colourMode() const { return m_colourMode; }
std::map<std::string, std::string> const& customOptions() const {
return m_customOptions;
}
};
/**
* Parses provided reporter spec string into
*
* Returns empty optional on errors, e.g.
* * field that is not first and not a key+value pair
* * duplicated keys in kv pair
* * unknown catch reporter option
* * empty key/value in an custom kv pair
* * ...
*/
Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec );
}
#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED

View File

@@ -0,0 +1,62 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <cstdio>
#include <sstream>
#include <vector>
namespace Catch {
// This class encapsulates the idea of a pool of ostringstreams that can be reused.
struct StringStreams {
std::vector<Detail::unique_ptr<std::ostringstream>> m_streams;
std::vector<std::size_t> m_unused;
std::ostringstream m_referenceStream; // Used for copy state/ flags from
auto add() -> std::size_t {
if( m_unused.empty() ) {
m_streams.push_back( Detail::make_unique<std::ostringstream>() );
return m_streams.size()-1;
}
else {
auto index = m_unused.back();
m_unused.pop_back();
return index;
}
}
void release( std::size_t index ) {
m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
m_unused.push_back(index);
}
};
ReusableStringStream::ReusableStringStream()
: m_index( Singleton<StringStreams>::getMutable().add() ),
m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
{}
ReusableStringStream::~ReusableStringStream() {
static_cast<std::ostringstream*>( m_oss )->str("");
m_oss->clear();
Singleton<StringStreams>::getMutable().release( m_index );
}
std::string ReusableStringStream::str() const {
return static_cast<std::ostringstream*>( m_oss )->str();
}
void ReusableStringStream::str( std::string const& str ) {
static_cast<std::ostringstream*>( m_oss )->str( str );
}
}

View File

@@ -5,11 +5,10 @@
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_STREAM_HPP_INCLUDED
#define CATCH_STREAM_HPP_INCLUDED
#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <iosfwd>
#include <cstddef>
@@ -18,17 +17,6 @@
namespace Catch {
std::ostream& cout();
std::ostream& cerr();
std::ostream& clog();
struct IStream {
virtual ~IStream(); // = default
virtual std::ostream& stream() const = 0;
};
auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream const>;
class ReusableStringStream : Detail::NonCopyable {
std::size_t m_index;
std::ostream* m_oss;
@@ -66,4 +54,4 @@ namespace Catch {
};
}
#endif // CATCH_STREAM_HPP_INCLUDED
#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED

View File

@@ -7,6 +7,7 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_run_context.hpp>
#include <catch2/catch_user_config.hpp>
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
@@ -159,7 +160,7 @@ namespace Catch {
GeneratorTracker::~GeneratorTracker() = default;
}
RunContext::RunContext(IConfig const* _config, IStreamingReporterPtr&& reporter)
RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
: m_runInfo(_config->name()),
m_context(getCurrentMutableContext()),
m_config(_config),

View File

@@ -24,9 +24,9 @@
namespace Catch {
struct IMutableContext;
struct IGeneratorTracker;
struct IConfig;
class IMutableContext;
class IGeneratorTracker;
class IConfig;
///////////////////////////////////////////////////////////////////////////
@@ -36,7 +36,7 @@ namespace Catch {
RunContext( RunContext const& ) = delete;
RunContext& operator =( RunContext const& ) = delete;
explicit RunContext( IConfig const* _config, IStreamingReporterPtr&& reporter );
explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter );
~RunContext() override;
@@ -130,7 +130,7 @@ namespace Catch {
IConfig const* m_config;
Totals m_totals;
IStreamingReporterPtr m_reporter;
IEventListenerPtr m_reporter;
std::vector<MessageInfo> m_messages;
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
AssertionInfo m_lastAssertionInfo;

View File

@@ -0,0 +1,24 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_stdstreams.hpp>
#include <catch2/catch_user_config.hpp>
#include <iostream>
namespace Catch {
// If you #define this you must implement these functions
#if !defined( CATCH_CONFIG_NOSTDOUT )
std::ostream& cout() { return std::cout; }
std::ostream& cerr() { return std::cerr; }
std::ostream& clog() { return std::clog; }
#endif
} // namespace Catch

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