Compare commits

...

155 Commits

Author SHA1 Message Date
Martin Hořeňovský
605a34765a v3.0.1 2022-05-17 22:13:36 +02:00
Martin Hořeňovský
abb669d4fd Extend project call for Catch2
This provides some extra metadata for CPack and related tools.
2022-05-17 22:12:44 +02:00
Martin Hořeňovský
dcafc605f3 Only reseed the internal RNG when a test is first entered
This fixes multiple issues with random generators, with the most
important one being that multiple nested generators could return
values from the same sequence, due to internal implementation
details of `GENERATE`, and how they interact with test case
paths.

The cost of doing this is that given this simple `TEST_CASE`,
```cpp
TEST_CASE("foo") {
    auto i = GENERATE(take(10, random(0, 100));
    SECTION("A") {
        auto j = GENERATE(take(10, random(0, 100));
    }
    SECTION("B") {
        auto k = GENERATE(take(10, random(0, 100));
    }
}
```

`k` will have different values between running the test as
a whole, e.g. with `./tests "foo"`, and running only the "B"
section with `./tests "foo" -c "B"`.

I consider this an acceptable cost, because the only alternative
would be very messy to implement, and add a lot of brittle and
complex code for relatively little benefit.

If this calculation changes, we will need to instead walk
the current tracker tree whenever a random generator is being
constructed, check for random generators on the path to root,
and take a seed from them.
2022-05-17 21:49:26 +02:00
Martin Hořeňovský
7a2a6c632f Make Random*Generators be seedable
This is a necessary step to fix issue with combining multiple
random generators in one test case, with different section nesting.
2022-05-17 17:57:21 +02:00
Martin Hořeňovský
359cd6187d Rename global rng() to sharedRng() 2022-05-17 15:43:23 +02:00
Martin Hořeňovský
9c72b303d9 Reseed global rng instance unconditionally 2022-05-17 12:35:34 +02:00
Martin Hořeňovský
6044f021cf Don't reseed std::srand when resetting rng state
We no longer use `std::rand` anywhere, so there is no point,
and it might even interfere with our users use of `std::(s)rand`.
2022-05-17 11:54:19 +02:00
Martin Hořeňovský
5d7883b551 Remove leftover comment in tests 2022-05-16 21:50:52 +02:00
Martin Hořeňovský
04a54b0e87 Fix release automation script 2022-05-16 18:39:01 +02:00
Martin Hořeňovský
48f3226974 Add support for retrieving generator's element as string 2022-05-16 16:34:06 +02:00
Martin Hořeňovský
af8b54ecd5 Generators now keep track of the index of current element
This might become potentially useful in the future, when we want
to provide the ability to forward jump generators, to be able to
simply reproduce specific input to a test.

I am not yet sure how it would work, but the basic idea is that
it could be similar to the `-c` switch for selecting specific
`SECTION` in a test case.
2022-05-16 11:56:21 +02:00
Martin Hořeňovský
07bec74096 Use better instruction for CATCH_TRAP on ARM Macs
The old instruction would cause the debugger to be stuck at the
triggering source line forever, while the new one should have the
expected semantics, where the debugger can then single-step,
continue. or generally do things, afterwards.

Closes #2422
2022-05-15 23:22:00 +02:00
Martin Hořeňovský
316025a0d8 Properly handle startup reporter registration errors 2022-05-15 10:35:12 +02:00
Martin Hořeňovský
33aeb603fe Add check for registering multiple reporters under same name 2022-05-15 09:54:27 +02:00
Martin Hořeňovský
fc3d11b1d1 Add Wfloat-equal to default-enabled warnings
This is kinda messy, because there is no good way to signal to
the compiler that some code uses direct comparison of floating
point numbers intentionally, so instead we have to use diagnostic
pragmas.

We also have to over-suppress the test files, because Clang (and
possibly GCC) still issue warnings from template instantiation
even if the instantion site is under warning suppression, so the
template definition has to be under warning suppression as well.

Closes #2406
2022-05-14 15:47:20 +02:00
Martin Hořeňovský
1ef65d60f1 Tiny fixup in Misc.tests.cpp 2022-05-11 22:56:30 +02:00
Martin Hořeňovský
ed6b38b096 Specialize XML reporter's listener listing 2022-05-10 20:58:02 +02:00
Martin Hořeňovský
5a49285e9c Add --list-listeners option 2022-05-10 20:57:59 +02:00
Martin Hořeňovský
ae475a3c19 Optional support for listener descriptions 2022-05-10 20:57:53 +02:00
Martin Hořeňovský
d60fbe49be Slight improvement for reporter test 2022-05-10 20:57:50 +02:00
Martin Hořeňovský
a733b58cd2 Replace C++23-deprecated aligned_storage_t 2022-05-10 00:07:22 +02:00
Martin Hořeňovský
d9b0a38f81 Report Catch2's version in the xml reporter output 2022-05-03 19:46:35 +02:00
Martin Hořeňovský
40c8909a49 Rename useColourOnPlatform => useImplementationForStream 2022-05-03 19:04:43 +02:00
Martin Hořeňovský
91ea25e51a Fix use of u8-literal that would break in C++20 2022-05-03 13:54:07 +02:00
Martin Hořeňovský
e2d07d35f4 Add -Wmissing-prototypes to common warnings 2022-05-03 13:54:05 +02:00
Martin Hořeňovský
d2cb934d28 Add -Wmissing-variable-declarations to common warnings 2022-05-03 13:54:03 +02:00
Martin Hořeňovský
7752229105 Add -Wsuggest-destructor-override to enabled warnings 2022-05-03 13:54:02 +02:00
Martin Hořeňovský
722c197855 Enable a bunch of extra warnings 2022-05-03 13:54:00 +02:00
Martin Hořeňovský
198808a24e Misc cleanups from exploring Clang warnings 2022-05-03 13:53:55 +02:00
Martin Hořeňovský
198713e5dc Cleanup of unused functions
The cleanup also found out that custom translation for std-derived
exceptions test wasn't running properly, and fixed that.
We cannot enable the warning globally, because the tests contain
some functions that are unused by design -- e.g. when checking
stringification priority of StringMaker vs range fallback and so
on.
2022-05-02 21:32:24 +02:00
Martin Hořeňovský
b84067ea6f Clean up .gitignore 2022-05-01 23:10:37 +02:00
Martin Hořeňovský
332de39cd4 Remove some useless casts 2022-04-28 14:56:33 +02:00
Martin Hořeňovský
c410e2596c Add some extra warnings 2022-04-28 14:56:31 +02:00
Martin Hořeňovský
4c1cf4aa67 Sorted and removed duplicates from the compiler warning list
The duplicates were '-Wreturn-std-move' and '-Wunreachable-code'.
2022-04-28 11:06:53 +02:00
Martin Hořeňovský
745cc82cd3 Remove some old commented out CMake code 2022-04-28 10:53:03 +02:00
Martin Hořeňovský
07dfb4b070 Update PARENT_SCOPE cmake module path with path to extras/
This allows projects including us directly to do e.g.
`include(Catch)` and get access to the test autoregistration
CMake scripts. Note that this inclusion can be done directly
through `add_subdirectory`, or indirectly via `FetchContent`.

Closes #1805
Closes #2026
Closes #2130
2022-04-28 10:52:16 +02:00
Martin Hořeňovský
5e86ead366 Exclude doxygen docs from documentation install step
We might want to keep them in at some point, but currently the
doxygen docs are very incomplete and unfinished.
2022-04-27 14:57:59 +02:00
Martin Hořeňovský
9dc229693d Document the stability guarantees of '--order rand' option 2022-04-25 21:45:50 +02:00
Martin Hořeňovský
db57a4956f Fixup ToC in command-line.md 2022-04-25 21:39:48 +02:00
Martin Hořeňovský
48177831ee Add version placeholder to the example doc in contributing.md 2022-04-25 21:36:03 +02:00
Martin Hořeňovský
ee3bbecf51 Improve include guard docs in contributing.md 2022-04-25 21:33:05 +02:00
Martin Hořeňovský
431dcf36ea Document Catch2's API/ABI stability policies 2022-04-25 18:58:50 +02:00
Martin Hořeňovský
e882cb8eb1 Document the new --skip-benchmarks flag 2022-04-25 18:36:40 +02:00
Martin Hořeňovský
c2bc321607 Add pipeline running tests under Valgrind to GitHub Action 2022-04-24 13:34:50 +02:00
Martin Hořeňovský
ea9029c478 Fix pkg list name in CMake config workflow 2022-04-24 13:34:36 +02:00
Martin Hořeňovský
c65e5b6514 Add 'uses-python' label to tests using Python 2022-04-24 13:31:28 +02:00
Martin Hořeňovský
880285b433 Tiny cleanup in catch_clara.cpp 2022-04-24 13:31:25 +02:00
Martin Hořeňovský
07cdef2096 Fix uninit memory in Clara tests 2022-04-24 13:31:19 +02:00
Martin Hořeňovský
5baa29b6b9 Add test for %debug stream name 2022-04-23 23:34:27 +02:00
Daniel Feist
291b35b389 Added --skip-benchmarks command-line option. (#2408)
Closes #2392

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2022-04-23 23:14:49 +02:00
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
272 changed files with 9301 additions and 3969 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,23 @@ jobs:
other_pkgs: clang-10 other_pkgs: clang-10
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON 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_pkgs: clang-10
cmake_configurations: -DCATCH_ENABLE_CONFIGURE_TESTS=ON
# Valgrind test Clang-10
- cxx: clang++-10
build_description: Valgrind tests
build_type: Debug
std: 14
other_pkgs: clang-10 valgrind
cmake_configurations: -DMEMORYCHECK_COMMAND=`which valgrind` -DMEMORYCHECK_COMMAND_OPTIONS="-q --track-origins=yes --leak-check=full --num-callers=50 --show-leak-kinds=definite --error-exitcode=1"
other_ctest_args: -T memcheck -LE uses-python
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -83,4 +100,4 @@ jobs:
CTEST_OUTPUT_ON_FAILURE: 1 CTEST_OUTPUT_ON_FAILURE: 1
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
# Hardcode 2 cores we know are there # Hardcode 2 cores we know are there
run: ctest -C ${{matrix.build_type}} -j 2 run: ctest -C ${{matrix.build_type}} -j 2 ${{matrix.other_ctest_args}}

10
.gitignore vendored
View File

@@ -11,11 +11,6 @@ Release
xcuserdata xcuserdata
CatchSelfTest.xcscheme CatchSelfTest.xcscheme
Breakpoints.xcbkptlist Breakpoints.xcbkptlist
projects/VS2010/TestCatch/_UpgradeReport_Files/
projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters
projects/VisualStudio/TestCatch/UpgradeLog.XML
projects/CMake/.idea
projects/CMake/cmake-build-debug
UpgradeLog.XML UpgradeLog.XML
Resources/DWARF Resources/DWARF
projects/Generated projects/Generated
@@ -31,3 +26,8 @@ benchmark-dir
bazel-* bazel-*
build-fuzzers build-fuzzers
debug-build debug-build
.vscode
msvc-sln*
# Currently we use Doxygen for dep graphs and the full docs are only slowly
# being filled in, so we definitely do not want git to deal with the docs.
docs/doxygen

View File

@@ -1,25 +1,91 @@
# Load the cc_library rule. # Load the cc_library rule.
load("@rules_cc//cc:defs.bzl", "cc_library") 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. # Static library, without main.
cc_library( cc_library(
name = "catch2", name = "catch2",
srcs = glob(
["src/catch2/**/*.cpp"],
exclude = ["src/catch2/internal/catch_main.cpp"],
),
hdrs = glob(["src/catch2/**/*.hpp"]), 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/"], includes = ["src/"],
linkstatic = True,
visibility = ["//visibility:public"],
deps = [":catch2_generated"],
) )
# Static library, with main. # Static library, with main.
cc_library( cc_library(
name = "catch2_main", name = "catch2_main",
srcs = ["src/catch2/internal/catch_main.cpp"], srcs = ["src/catch2/internal/catch_main.cpp"],
deps = [":catch2"],
visibility = ["//visibility:public"],
linkstatic = True,
copts = ["-std=c++14"],
includes = ["src/"], 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) include(CheckCXXCompilerFlag)
function(add_cxx_flag_if_supported_to_targets flagname targets) function(add_cxx_flag_if_supported_to_targets flagname targets)
check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flagname}) check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flagname})
@@ -35,35 +43,58 @@ function(add_warnings_to_targets targets)
if (NOT MSVC) if (NOT MSVC)
set(CHECKED_WARNING_FLAGS set(CHECKED_WARNING_FLAGS
"-Wall"
"-Wextra"
"-Wpedantic"
"-Wweak-vtables"
"-Wunreachable-code"
"-Wmissing-declarations"
"-Wexit-time-destructors"
"-Wglobal-constructors"
"-Wmissing-noreturn"
"-Wparentheses"
"-Wextra-semi"
"-Wunreachable-code"
"-Wstrict-aliasing"
"-Wreturn-std-move"
"-Wmissing-braces"
"-Wdeprecated"
"-Wvla"
"-Wundef"
"-Wmisleading-indentation"
"-Wcatch-value"
"-Wabsolute-value" "-Wabsolute-value"
"-Wreturn-std-move" "-Wall"
"-Wunused-parameter" "-Wc++20-compat"
"-Wunused-function"
"-Wcall-to-pure-virtual-from-ctor-dtor" "-Wcall-to-pure-virtual-from-ctor-dtor"
"-Wcast-align"
"-Wcatch-value"
"-Wdangling"
"-Wdeprecated"
"-Wdeprecated-register" "-Wdeprecated-register"
"-Wsuggest-override" "-Wexceptions"
"-Wshadow" "-Wexit-time-destructors"
"-Wextra"
"-Wextra-semi"
"-Wfloat-equal"
"-Wglobal-constructors"
"-Winit-self"
"-Wmisleading-indentation"
"-Wmismatched-new-delete"
"-Wmismatched-return-types"
"-Wmismatched-tags"
"-Wmissing-braces"
"-Wmissing-declarations"
"-Wmissing-noreturn"
"-Wmissing-prototypes"
"-Wmissing-variable-declarations"
"-Wnull-dereference"
"-Wold-style-cast" "-Wold-style-cast"
"-Woverloaded-virtual"
"-Wparentheses"
"-Wpedantic"
"-Wreorder"
"-Wreturn-std-move"
"-Wshadow"
"-Wstrict-aliasing"
"-Wsuggest-destructor-override"
"-Wsuggest-override"
"-Wundef"
"-Wuninitialized"
"-Wunneeded-internal-declaration"
"-Wunreachable-code"
"-Wunused"
"-Wunused-function"
"-Wunused-parameter"
"-Wvla"
"-Wweak-vtables"
# This is a useful warning, but our tests sometimes rely on
# functions being present, but not picked (e.g. various checks
# for stringification implementation ordering).
# Ergo, we should use it every now and then, but we cannot
# enable it by default.
# "-Wunused-member-function"
) )
foreach(warning ${CHECKED_WARNING_FLAGS}) foreach(warning ${CHECKED_WARNING_FLAGS})
add_cxx_flag_if_supported_to_targets(${warning} "${targets}") add_cxx_flag_if_supported_to_targets(${warning} "${targets}")

View File

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

View File

@@ -9,7 +9,7 @@ else()
endif() endif()
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON) 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) option(CATCH_DEVELOPMENT_BUILD "Build tests, enable warnings, enable Werror, etc" OFF)
include(CMakeDependentOption) 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_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_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_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 # Catch2's build breaks if done in-tree. You probably should not build
@@ -35,12 +36,27 @@ if(CMAKE_VERSION VERSION_GREATER 3.8)
endif() endif()
project(Catch2 LANGUAGES CXX VERSION 3.0.0) project(Catch2
VERSION 3.0.1 # CML version placeholder, don't delete
LANGUAGES CXX
HOMEPAGE_URL "https://github.com/catchorg/Catch2"
DESCRIPTION "A modern, C++-native, unit test framework."
)
# Provide path for scripts
# Provide path for scripts. We first add path to the scripts we don't use,
# but projects including us might, and set the path up to parent scope.
# Then we also add path that we use to configure the project, but is of
# no use to top level projects.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/extras")
if (NOT NOT_SUBPROJECT)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
include(GNUInstallDirs) include(GNUInstallDirs)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
include(CatchConfigOptions)
if(CATCH_DEVELOPMENT_BUILD) if(CATCH_DEVELOPMENT_BUILD)
include(CTest) include(CTest)
endif() endif()
@@ -93,16 +109,6 @@ if (CATCH_DEVELOPMENT_BUILD)
add_warnings_to_targets("${CATCH_WARNING_TARGETS}") add_warnings_to_targets("${CATCH_WARNING_TARGETS}")
endif() 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)
#
#
#
#
#
# Only perform the installation steps when Catch is not being used as # Only perform the installation steps when Catch is not being used as
# a subproject via `add_subdirectory`, or the destinations will break, # a subproject via `add_subdirectory`, or the destinations will break,
# see https://github.com/catchorg/Catch2/issues/1373 # see https://github.com/catchorg/Catch2/issues/1373
@@ -135,6 +141,7 @@ if (NOT_SUBPROJECT)
docs/ docs/
DESTINATION DESTINATION
"${CMAKE_INSTALL_DOCDIR}" "${CMAKE_INSTALL_DOCDIR}"
PATTERN "doxygen" EXCLUDE
) )
endif() endif()

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. # build explicitly.
environment: environment:
matrix: matrix:
- FLAVOR: VS 2019 x64 Debug Surrogates - FLAVOR: VS 2019 x64 Debug Surrogates Configure Tests
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
surrogates: 1 surrogates: 1
configure_tests: 1
platform: x64 platform: x64
configuration: Debug configuration: Debug

View File

@@ -20,7 +20,7 @@ class CatchConan(ConanFile):
cmake = CMake(self) cmake = CMake(self)
cmake.definitions["BUILD_TESTING"] = "OFF" cmake.definitions["BUILD_TESTING"] = "OFF"
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF" cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
cmake.definitions["CATCH_INSTALL_HELPERS"] = "ON" cmake.definitions["CATCH_INSTALL_EXTRAS"] = "ON"
cmake.configure(build_folder="build") cmake.configure(build_folder="build")
return cmake return cmake
@@ -42,16 +42,18 @@ conan_basic_setup()'''.format(line_to_replace, self.install_folder.replace("\\",
cmake.install() cmake.install()
def package_info(self): 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"] = "Catch2"
self.cpp_info.names["cmake_find_package_multi"] = "Catch2" self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
# Catch2 # Catch2
self.cpp_info.components["catch2base"].names["cmake_find_package"] = "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["cmake_find_package_multi"] = "Catch2"
self.cpp_info.components["catch2base"].names["pkg_config"] = "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 # Catch2WithMain
self.cpp_info.components["catch2main"].names["cmake_find_package"] = "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["cmake_find_package_multi"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["pkg_config"] = "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"] 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`. Catch2's test binary will be built. Defaults to `ON`.
* `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be * `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be
included in the installation. Defaults to `ON`. included in the installation. Defaults to `ON`.
* `CATCH_INSTALL_HELPERS` -- When `ON`, Catch2's extras folder will be * `CATCH_INSTALL_EXTRAS` -- When `ON`, Catch2's extras folder (the CMake
included in the installation. Defaults to `ON`. scripts mentioned above, debugger helpers) will be included in the
installation. Defaults to `ON`.
* `CATCH_DEVELOPMENT_BUILD` -- When `ON`, configures the build for development * `CATCH_DEVELOPMENT_BUILD` -- When `ON`, configures the build for development
of Catch2. This means enabling test projects, warnings and so on. of Catch2. This means enabling test projects, warnings and so on.
Defaults to `OFF`. Defaults to `OFF`.

View File

@@ -15,11 +15,11 @@
[Warnings](#warnings)<br> [Warnings](#warnings)<br>
[Reporting timings](#reporting-timings)<br> [Reporting timings](#reporting-timings)<br>
[Load test names to run from a file](#load-test-names-to-run-from-a-file)<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 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> [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> [Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard)<br>
[Wait for key before continuing](#wait-for-key-before-continuing)<br> [Wait for key before continuing](#wait-for-key-before-continuing)<br>
[Skip all benchmarks](#skip-all-benchmarks)<br>
[Specify the number of benchmark samples to collect](#specify-the-number-of-benchmark-samples-to-collect)<br> [Specify the number of benchmark samples to collect](#specify-the-number-of-benchmark-samples-to-collect)<br>
[Specify the number of resamples for bootstrapping](#specify-the-number-of-resamples-for-bootstrapping)<br> [Specify the number of resamples for bootstrapping](#specify-the-number-of-resamples-for-bootstrapping)<br>
[Specify the confidence-interval for bootstrapping](#specify-the-confidence-interval-for-bootstrapping)<br> [Specify the confidence-interval for bootstrapping](#specify-the-confidence-interval-for-bootstrapping)<br>
@@ -31,6 +31,7 @@
[Override output colouring](#override-output-colouring)<br> [Override output colouring](#override-output-colouring)<br>
[Test Sharding](#test-sharding)<br> [Test Sharding](#test-sharding)<br>
[Allow running the binary without tests](#allow-running-the-binary-without-tests)<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. 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. Click one of the following links to take you straight to that option - or scroll on to browse the available options.
@@ -58,16 +59,18 @@ Click one of the following links to take you straight to that option - or scroll
<a href="#listing-available-tests-tags-or-reporters"> ` --list-tests`</a><br /> <a href="#listing-available-tests-tags-or-reporters"> ` --list-tests`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-tags`</a><br /> <a href="#listing-available-tests-tags-or-reporters"> ` --list-tags`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br /> <a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-listeners`</a><br />
<a href="#order"> ` --order`</a><br /> <a href="#order"> ` --order`</a><br />
<a href="#rng-seed"> ` --rng-seed`</a><br /> <a href="#rng-seed"> ` --rng-seed`</a><br />
<a href="#libidentify"> ` --libidentify`</a><br /> <a href="#libidentify"> ` --libidentify`</a><br />
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br /> <a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
<a href="#skip-benchmarks"> ` --skip-benchmarks`</a><br />
<a href="#benchmark-samples"> ` --benchmark-samples`</a><br /> <a href="#benchmark-samples"> ` --benchmark-samples`</a><br />
<a href="#benchmark-resamples"> ` --benchmark-resamples`</a><br /> <a href="#benchmark-resamples"> ` --benchmark-resamples`</a><br />
<a href="#benchmark-confidence-interval"> ` --benchmark-confidence-interval`</a><br /> <a href="#benchmark-confidence-interval"> ` --benchmark-confidence-interval`</a><br />
<a href="#benchmark-no-analysis"> ` --benchmark-no-analysis`</a><br /> <a href="#benchmark-no-analysis"> ` --benchmark-no-analysis`</a><br />
<a href="#benchmark-warmup-time"> ` --benchmark-warmup-time`</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-count`</a><br />
<a href="#test-sharding"> ` --shard-index`</a><br /> <a href="#test-sharding"> ` --shard-index`</a><br />
<a href=#no-tests-override> ` --allow-running-no-tests`</a><br /> <a href=#no-tests-override> ` --allow-running-no-tests`</a><br />
@@ -123,22 +126,33 @@ Test names containing special characters, such as `,` or `[` can specify them on
<a id="choosing-a-reporter-to-use"></a> <a id="choosing-a-reporter-to-use"></a>
## Choosing a reporter to use ## Choosing a reporter to use
<pre>-r, --reporter &lt;reporter[::output-file]&gt;</pre> <pre>-r, --reporter &lt;reporter[::key=value]*&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
Reporters are how the output from Catch2 (results of assertions, tests, Reporters are how the output from Catch2 (results of assertions, tests,
benchmarks and so on) is formatted and written out. The default reporter benchmarks and so on) is formatted and written out. The default reporter
is called the "Console" reporter and is intended to provide relatively is called the "Console" reporter and is intended to provide relatively
verbose and human-friendly output. 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 3.0.1
There are multiple built-in reporters, you can see what they do by using the 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) [`--list-reporter`](command-line.md#listing-available-tests-tags-or-reporters)
flag. If you need a reporter providing custom format outside of the already 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 provided ones, look at the ["write your own reporter" part of the reporter
documentation](reporters.md#writing-your-own-reporter). documentation](reporters.md#writing-your-own-reporter).
This option may be passed multiple times to use multiple (different) This option may be passed multiple times to use multiple (different)
reporters at the same time. See the [reporter documentation](reporters.md#multiple-reporters) 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 for details on what the resulting behaviour is. Also note that at most one
@@ -146,15 +160,14 @@ reporter can be provided without the output-file part of reporter spec.
This reporter will use the "default" output destination, based on This reporter will use the "default" output destination, based on
the [`-o`, `--out`](#sending-output-to-a-file) option. 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 > Support for using multiple different reporters at the same time was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 3.0.1
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, _Note: There is currently no way to escape `::` in the reporter spec,
and thus reporter/file names with `::` in them will not work properly. and thus the reporter names, or configuration keys and values, cannot
As `::` in paths is relatively obscure (unlike `:`), we do not consider contain `::`. As `::` in paths is relatively obscure (unlike ':'), we do
this an issue._ not consider this an issue._
<a id="breaking-into-the-debugger"></a> <a id="breaking-into-the-debugger"></a>
## Breaking into the debugger ## Breaking into the debugger
@@ -188,9 +201,12 @@ Sometimes this results in a flood of failure messages and you'd rather just see
--list-tests --list-tests
--list-tags --list-tags
--list-reporters --list-reporters
--list-listeners
``` ```
> The `--list*` options became customizable through reporters in Catch2 X.Y.Z > The `--list*` options became customizable through reporters in Catch2 3.0.1
> The `--list-listeners` option was added in Catch2 3.0.1
`--list-tests` lists all registered tests matching specified test spec. `--list-tests` lists all registered tests matching specified test spec.
Usually this listing also includes tags, and potentially also other Usually this listing also includes tags, and potentially also other
@@ -202,17 +218,31 @@ similar information.
`--list-reporters` lists all available reporters and their descriptions. `--list-reporters` lists all available reporters and their descriptions.
`--list-listeners` lists all registered listeners and their descriptions.
<a id="sending-output-to-a-file"></a> <a id="sending-output-to-a-file"></a>
## Sending output to a file ## Sending output to a file
<pre>-o, --out &lt;filename&gt; <pre>-o, --out &lt;filename&gt;
</pre> </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). 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).
Using `-` as the filename sends the output to stdout. > Support for `-` as the filename was introduced in Catch2 3.0.1
> 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 3.0.1
<a id="naming-a-test-run"></a> <a id="naming-a-test-run"></a>
@@ -260,7 +290,7 @@ There are currently two warnings implemented:
// not match any tests. // not match any tests.
``` ```
> `UnmatchedTestSpec` was introduced in Catch2 X.Y.Z. > `UnmatchedTestSpec` was introduced in Catch2 3.0.1.
<a id="reporting-timings"></a> <a id="reporting-timings"></a>
@@ -310,13 +340,19 @@ Lexicographic order. Tests are sorted by their name, their tags are ignored.
### rand ### rand
Randomly sorted. The order is dependent on Catch2's random seed (see Randomly ordered. The order is dependent on Catch2's random seed (see
[`--rng-seed`](#rng-seed)), and is subset invariant. What this means [`--rng-seed`](#rng-seed)), and is subset invariant. What this means
is that as long as the random seed is fixed, running only some tests is that as long as the random seed is fixed, running only some tests
(e.g. via tag) does not change their relative order. (e.g. via tag) does not change their relative order.
> The subset stability was introduced in Catch2 v2.12.0 > The subset stability was introduced in Catch2 v2.12.0
Since the random order was made subset stable, we promise that given
the same random seed, the order of test cases will be the same across
different platforms, as long as the tests were compiled against identical
version of Catch2. We reserve the right to change the relative order
of tests cases between Catch2 versions, but it is unlikely to happen often.
<a id="rng-seed"></a> <a id="rng-seed"></a>
## Specify a seed for the Random Number Generator ## Specify a seed for the Random Number Generator
@@ -348,6 +384,16 @@ See [The LibIdentify repo for more information and examples](https://github.com/
Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing - Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing -
either before running any tests, after running all tests - or both, depending on the argument. either before running any tests, after running all tests - or both, depending on the argument.
<a id="skip-benchmarks"></a>
## Skip all benchmarks
<pre>--skip-benchmarks</pre>
> [Introduced](https://github.com/catchorg/Catch2/issues/2408) in Catch2 3.0.1.
This flag tells Catch2 to skip running all benchmarks. Benchmarks in this
case mean code blocks in `BENCHMARK` and `BENCHMARK_ADVANCED` macros, not
test cases with the `[!benchmark]` tag.
<a id="benchmark-samples"></a> <a id="benchmark-samples"></a>
## Specify the number of benchmark samples to collect ## Specify the number of benchmark samples to collect
<pre>--benchmark-samples &lt;# of samples&gt;</pre> <pre>--benchmark-samples &lt;# of samples&gt;</pre>
@@ -457,22 +503,35 @@ filename it is found in, with any extension stripped, prefixed with the `#` char
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`. So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
<a id="use-colour"></a> <a id="colour-mode"></a>
## Override output colouring ## 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 > The `--colour-mode` option replaced the old `--colour` option in Catch2 3.0.1
output is being sent to a pipe. This is done to avoid interfering with automated
processing of output.
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> <a id="test-sharding"></a>
## Test Sharding ## Test Sharding
<pre>--shard-count <#number of shards>, --shard-index <#shard index to run></pre> <pre>--shard-count <#number of shards>, --shard-index <#shard index to run></pre>
> [Introduced](https://github.com/catchorg/Catch2/pull/2257) in Catch2 X.Y.Z. > [Introduced](https://github.com/catchorg/Catch2/pull/2257) in Catch2 3.0.1.
When `--shard-count <#number of shards>` is used, the tests to execute will be split evenly in to the given number of sets, When `--shard-count <#number of shards>` is used, the tests to execute will be split evenly in to the given number of sets,
identified by indicies starting at 0. The tests in the set given by `--shard-index <#shard index to run>` will be executed. identified by indicies starting at 0. The tests in the set given by `--shard-index <#shard index to run>` will be executed.
@@ -485,7 +544,7 @@ This is useful when you want to split test execution across multiple processes,
## Allow running the binary without tests ## Allow running the binary without tests
<pre>--allow-running-no-tests</pre> <pre>--allow-running-no-tests</pre>
> Introduced in Catch2 X.Y.Z. > Introduced in Catch2 3.0.1.
By default, Catch2 test binaries return non-0 exit code if no tests were By default, Catch2 test binaries return non-0 exit code if no tests were
run, e.g. if the binary was compiled with no tests, or the provided test run, e.g. if the binary was compiled with no tests, or the provided test

View File

@@ -8,17 +8,19 @@
[stdout](#stdout)<br> [stdout](#stdout)<br>
[Fallback stringifier](#fallback-stringifier)<br> [Fallback stringifier](#fallback-stringifier)<br>
[Default reporter](#default-reporter)<br> [Default reporter](#default-reporter)<br>
[Bazel support](#bazel-support)<br>
[C++11 toggles](#c11-toggles)<br> [C++11 toggles](#c11-toggles)<br>
[C++17 toggles](#c17-toggles)<br> [C++17 toggles](#c17-toggles)<br>
[Other toggles](#other-toggles)<br> [Other toggles](#other-toggles)<br>
[Windows header clutter](#windows-header-clutter)<br>
[Enabling stringification](#enabling-stringification)<br> [Enabling stringification](#enabling-stringification)<br>
[Disabling exceptions](#disabling-exceptions)<br> [Disabling exceptions](#disabling-exceptions)<br>
[Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<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```). Catch2 is designed to "just work" as much as possible, and most of the
configuration options below are changed automatically during compilation,
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. 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 ## Prefixing Catch macros
@@ -30,19 +32,18 @@ To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TE
## Terminal colour ## Terminal colour
CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring CATCH_CONFIG_COLOUR_WIN32 // Force enables compiling colouring impl based on Win32 console API
CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used CATCH_CONFIG_NO_COLOUR_WIN32 // Force disables ...
CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used
Yes, I am English, so I will continue to spell "colour" with a 'u'. Yes, 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 ## 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. 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 3.0.1.
## C++11 toggles ## C++11 toggles
CATCH_CONFIG_CPP11_TO_STRING // Use `std::to_string` 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`_ _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 ## 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, using CTest, either as a direct command invocation + pass/fail regex,
or by delegating the check to a Python script. 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 Examples present a small and self-contained snippets of code that
use Catch2's facilities for specific purpose. Currently they are assumed use Catch2's facilities for specific purpose. Currently they are assumed
passing if they compile. ExtraTests then are expensive tests, that we passing if they compile.
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.
Examples and ExtraTests are not compiled by default. To compile them, ExtraTests then are expensive tests, that we do not want to run all the
add `-DCATCH_BUILD_EXAMPLES=ON` and `-DCATCH_BUILD_EXTRA_TESTS=ON` to time. This can be either because they take a long time to run, or because
the invocation of CMake configuration step. 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, Bringing this all together, the steps below should configure, build,
and run all tests in the `Debug` compilation. and run all tests in the `Debug` compilation.
@@ -85,7 +90,7 @@ and run all tests in the `Debug` compilation.
./tools/scripts/generateAmalgamatedFiles.py ./tools/scripts/generateAmalgamatedFiles.py
# 2. Configure the full test build # 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 # 3. Run the actual build
cmake --build debug-build cmake --build debug-build
@@ -131,6 +136,8 @@ should use. It provides you with the top anchor mentioned to link to
<a id="top"></a> <a id="top"></a>
# Cool feature # Cool feature
> [Introduced](https://github.com/catchorg/Catch2/pull/123456) in Catch2 X.Y.Z
Text that explains how to use the cool feature. Text that explains how to use the cool feature.
@@ -291,9 +298,9 @@ Specifically, every source file should start with the licence header:
``` ```
The include guards for header files should follow the pattern `{FILENAME}_INCLUDED`. The include guards for header files should follow the pattern `{FILENAME}_INCLUDED`.
This means that for file `catch_matchers_foo`, the include guard should This means that for file `catch_matchers_foo.hpp`, the include guard should
be `CATCH_MATCHERS_FOO_INCLUDED`, for `catch_generators_bar`, the include be `CATCH_MATCHERS_FOO_HPP_INCLUDED`, for `catch_generators_bar.hpp`, the include
guard should be `CATCH_GENERATORS_BAR_INCLUDED`, and so on. guard should be `CATCH_GENERATORS_BAR_HPP_INCLUDED`, and so on.
## CoC ## CoC

View File

@@ -1,6 +1,13 @@
<a id="top"></a> <a id="top"></a>
# Frequently Asked Questions (FAQ) # Frequently Asked Questions (FAQ)
**Contents**<br>
[How do I run global setup/teardown only if tests will be run?](#how-do-i-run-global-setupteardown-only-if-tests-will-be-run)<br>
[How do I clean up global state between running different tests?](#how-do-i-clean-up-global-state-between-running-different-tests)<br>
[Why cannot I derive from the built-in reporters?](#why-cannot-i-derive-from-the-built-in-reporters)<br>
[What is Catch2's ABI stability policy?](#what-is-catch2s-abi-stability-policy)<br>
[What is Catch2's API stability policy?](#what-is-catch2s-api-stability-policy)<br>
## How do I run global setup/teardown only if tests will be run? ## How do I run global setup/teardown only if tests will be run?
Write a custom [event listener](event-listeners.md#top) and place the Write a custom [event listener](event-listeners.md#top) and place the
@@ -22,6 +29,23 @@ forbidding users from using them as a base class, we can refactor them
as needed later. as needed later.
## What is Catch2's ABI stability policy?
Catch2 provides no ABI stability guarantees whatsoever. Catch2 provides
rich C++ interface, and trying to freeze its ABI would take a lot of
pointless work.
Catch2 is not designed to be distributed as dynamic library, and you
should really be able to compile everything with the same compiler binary.
## What is Catch2's API stability policy?
Catch2 follows [semver](https://semver.org/) to the best of our ability.
This means that we will not knowingly make backwards-incompatible changes
without incrementing the major version number.
--- ---
[Home](Readme.md#top) [Home](Readme.md#top)

View File

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

View File

@@ -248,7 +248,7 @@ Note that `DerivedException` in the example above has to derive from
### Generic range Matchers ### Generic range Matchers
> Generic range matchers were introduced in Catch2 X.Y.Z > Generic range matchers were introduced in Catch2 3.0.1
Catch2 also provides some matchers that use the new style matchers Catch2 also provides some matchers that use the new style matchers
definitions to handle generic range-like types. These are: definitions to handle generic range-like types. These are:
@@ -350,7 +350,7 @@ style matchers arbitrarily.
## Writing custom matchers (new style) ## Writing custom matchers (new style)
> New style matchers were introduced in Catch2 X.Y.Z > New style matchers were introduced in Catch2 3.0.1
To create a new-style matcher, you have to create your own type that To create a new-style matcher, you have to create your own type that
derives from `Catch::Matchers::MatcherGenericBase`. Your type has to derives from `Catch::Matchers::MatcherGenericBase`. Your type has to

View File

@@ -17,6 +17,9 @@ maintainer's explicit consent._
## Libraries & Frameworks ## Libraries & Frameworks
### [accessorpp](https://github.com/wqking/accessorpp)
C++ library for implementing property and data binding.
### [alpaka](https://github.com/alpaka-group/alpaka) ### [alpaka](https://github.com/alpaka-group/alpaka)
A header-only C++14 abstraction library for accelerator development. 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) ### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
A High-performance Cluster Computing Engine. 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) ### [forest](https://github.com/xorz57/forest)
Template Library of Tree Data Structures. 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) ### [Nonius](https://github.com/libnonius/nonius)
A header-only framework for benchmarking small snippets of C++ code. 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) ### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
A polymorphic value-type for C++. A polymorphic value-type for C++.

View File

@@ -15,7 +15,7 @@ stringification machinery to the _expr_ and records the result. As with
evaluates to `true`. `CHECKED_ELSE( expr )` work similarly, but the block evaluates to `true`. `CHECKED_ELSE( expr )` work similarly, but the block
is entered only if the _expr_ evaluated to `false`. is entered only if the _expr_ evaluated to `false`.
> `CHECKED_X` macros were changed to not count as failure in Catch2 X.Y.Z. > `CHECKED_X` macros were changed to not count as failure in Catch2 3.0.1.
Example: Example:
```cpp ```cpp
@@ -77,7 +77,7 @@ TEST_CASE("STATIC_REQUIRE showcase", "[traits]") {
} }
``` ```
> `STATIC_CHECK` was [introduced](https://github.com/catchorg/Catch2/pull/2318) in Catch2 X.Y.Z. > `STATIC_CHECK` was [introduced](https://github.com/catchorg/Catch2/pull/2318) in Catch2 3.0.1.
`STATIC_CHECK( expr )` is equivalent to `STATIC_REQUIRE( expr )`, with the `STATIC_CHECK( expr )` is equivalent to `STATIC_REQUIRE( expr )`, with the
difference that when `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE` is defined, it difference that when `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE` is defined, it

View File

@@ -2,7 +2,7 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[3.0.1 (in progress)](#301-in-progress)<br> [3.0.1](#301)<br>
[2.13.7](#2137)<br> [2.13.7](#2137)<br>
[2.13.6](#2136)<br> [2.13.6](#2136)<br>
[2.13.5](#2135)<br> [2.13.5](#2135)<br>
@@ -49,25 +49,15 @@
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 3.0.1 (in progress) ## 3.0.1
**Catch2 now uses statically compiled library as its distribution model. **Catch2 now uses statically compiled library as its distribution model.
This also means that to get all of Catch2's functionality in a test file, This also means that to get all of Catch2's functionality in a test file,
you have to include multiple headers.** you have to include multiple headers.**
For quick'n'dirty migration, you can replace the old `#include <catch2/catch.hpp>` You probably want to look into the [migration docs](migrate-v2-to-v3.md#top),
with `#include <catch2/catch_all.hpp>`. This is a (one of) convenience which were written to help people coming from v2.x.x versions to the
header(s) that brings in _all_ of headers in Catch2. By doing this, v3 releases.
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.
### FAQ ### FAQ
@@ -132,11 +122,14 @@ new design.
* With the exception of the XmlReporter, the outputs of first party reporters should remain the same * With the exception of the XmlReporter, the outputs of first party reporters should remain the same
* New pair of events were added * New pair of events were added
* One obsolete event was removed * 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 * Catch2 generates a random seed if one hasn't been specified by the user
* The short flag for `--list-tests`, `-l`, has been removed. * 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. * 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. * 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. * 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 ### Improvements
@@ -188,6 +181,18 @@ new design.
* Multiple reporters can now run at the same time and write to different files (#1712, #2183) * 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 * 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 * 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.
* Added `--skip-benchmarks` flag to run tests without any `BENCHMARK`s (#2392, #2408)
* Added option to list all listeners in the binary via `--list-listeners`
### Fixes ### Fixes
@@ -200,6 +205,8 @@ new design.
* Previously it forced lower cased name, which would fail for reporters with upper case characters in name * 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 * The cumulative reporter base stores benchmark results alongside assertion results
* Catch2's SE handling should no longer interferes with ASan on Windows (#2334) * Catch2's SE handling should no longer interferes with ASan on Windows (#2334)
* Fixed Windows console colour handling for tests that redirect stdout (#2345)
* Fixed issue with the `random` generators returning the same value over and over again
### Other changes ### Other changes
@@ -217,6 +224,11 @@ new design.
* Running 0 tests (e.g. due to empty binary, or test spec not matching anything) returns non-0 exit code * 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. * Flag `--allow-running-no-tests` overrides this behaviour.
* `NoTests` warning has been removed because it is fully subsumed by this change. * `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)

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. After pushing changes to GitHub, GitHub release *needs* to be created.
Tag version and release title should be same as the new version, Tag version and release title should be same as the new version,
description should contain the release notes for the current release. description should contain the release notes for the current release.
Single header version of `catch.hpp` *needs* to be attached as a binary, We also attach the two amalgamated files as "binaries".
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.
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP Since 2.5.0, the release tag and the "binaries" (amalgamated files) should
signed. be PGP signed.
#### Signing a tag #### 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 Use the version name as the short message and the release notes as
the body (long) message. the body (long) message.
#### Signing the headers #### Signing the amalgamated files
This will create ASCII-armored signatures for the headers that are This will create ASCII-armored signatures for the two amalgamated files
uploaded to the GitHub release: that are uploaded to the GitHub release:
``` ```
$ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp gpg --armor --output extras/catch_amalgamated.hpp.asc --detach-sig extras/catch_amalgamated.hpp
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp gpg --armor --output extras/catch_amalgamated.cpp.asc --detach-sig extras/catch_amalgamated.cpp
$ 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 does not support signing multiple files in single invocation._ _GPG does not support signing multiple files in single invocation._

View File

@@ -56,7 +56,7 @@ are handled by a different event.
### `testCasePartial` events ### `testCasePartial` events
> Introduced in Catch2 X.Y.Z > Introduced in Catch2 3.0.1
```cpp ```cpp
void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ); void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber );
@@ -135,7 +135,7 @@ benchmarking itself fails.
## Listings events ## Listings events
> Introduced in Catch2 X.Y.Z. > Introduced in Catch2 3.0.1.
Listings events are events that correspond to the test binary being Listings events are events that correspond to the test binary being
invoked with `--list-foo` flag. invoked with `--list-foo` flag.

View File

@@ -30,7 +30,7 @@ reporters](#multiple-reporters) to avoid any surprises from doing so.
<a id="multiple-reporters"></a> <a id="multiple-reporters"></a>
## Using multiple reporters ## Using multiple reporters
> Support for having multiple parallel reporters was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 X.Y.Z > Support for having multiple parallel reporters was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 3.0.1
Catch2 supports using multiple reporters at the same time while having Catch2 supports using multiple reporters at the same time while having
them write into different destinations. The two main uses of this are them write into different destinations. The two main uses of this are
@@ -43,9 +43,14 @@ them write into different destinations. The two main uses of this are
Specifying multiple reporter looks like this: 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 Using multiple reporters (or one reporter and one-or-more [event
listeners](event-listener.md#top)) can have surprisingly complex semantics listeners](event-listener.md#top)) can have surprisingly complex semantics
when using customization points provided to reporters by Catch2, namely 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. You can also write your own custom reporter and tell Catch2 to use it.
When writing your reporter, you have two options: 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). to provide handling for all [reporter events](reporter-events.md#top).
* Derive from one of the provided [utility reporter bases in * Derive from one of the provided [utility reporter bases in
Catch2](#utility-reporter-bases). Catch2](#utility-reporter-bases).
@@ -162,6 +167,26 @@ Currently there are two customization options:
format includes passing assertions even without the `-s` flag. format includes passing assertions even without the `-s` flag.
### Per-reporter configuration
> Per-reporter configuration was introduced in Catch2 3.0.1
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 ### Other expected functionality of a reporter
When writing a custom reporter, there are few more things that you should 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. // - REQUIRE_FALSE() stops at first failure.
// - CHECK_FALSE() continues after failure. // - CHECK_FALSE() continues after failure.
// main() provided in 000-CatchMain.cpp // main() provided by linkage to Catch2WithMain
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
@@ -53,8 +53,8 @@ TEST_CASE( "Assert that something is false (continue after failure)", "[check-fa
} }
// Compile & run: // 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 // - 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 000-CatchMain.obj && 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): // Expected compact output (all assertions):
// //

View File

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

View File

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

View File

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

View File

@@ -308,7 +308,7 @@ struct MyListener : Catch::EventListenerBase {
using EventListenerBase::EventListenerBase; // inherit constructor using EventListenerBase::EventListenerBase; // inherit constructor
// Get rid of Wweak-tables // Get rid of Wweak-tables
~MyListener(); ~MyListener() override;
// The whole test run starting // The whole test run starting
void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override { void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
@@ -420,8 +420,8 @@ TEST_CASE_METHOD( Fixture, "3: Testcase with class-based fixture", "[tag-C][tag-
} }
// Compile & run: // 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 // - 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 000-CatchMain.obj && 210-Evt-EventListeners --success // - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
// Expected compact output (all assertions): // 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 # Please keep these ordered alphabetically
set(BENCHMARK_HEADERS set(BENCHMARK_HEADERS
@@ -31,6 +38,8 @@ set(BENCHMARK_SOURCES
SOURCE_GROUP("benchmark" FILES ${BENCHMARK_HEADERS} ${BENCHMARK_SOURCES}) SOURCE_GROUP("benchmark" FILES ${BENCHMARK_HEADERS} ${BENCHMARK_SOURCES})
set(INTERNAL_HEADERS 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}/catch_all.hpp
${SOURCES_DIR}/matchers/catch_matchers_all.hpp ${SOURCES_DIR}/matchers/catch_matchers_all.hpp
${SOURCES_DIR}/generators/catch_generators_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_exception_translator_registry.hpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp
${SOURCES_DIR}/internal/catch_floating_point_helpers.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_unique_name.hpp
${SOURCES_DIR}/internal/catch_sharding.hpp ${SOURCES_DIR}/internal/catch_sharding.hpp
${SOURCES_DIR}/generators/catch_generator_exception.hpp ${SOURCES_DIR}/generators/catch_generator_exception.hpp
@@ -107,18 +117,20 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_platform.hpp ${SOURCES_DIR}/internal/catch_platform.hpp
${SOURCES_DIR}/internal/catch_polyfills.hpp ${SOURCES_DIR}/internal/catch_polyfills.hpp
${SOURCES_DIR}/internal/catch_preprocessor.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_number_generator.hpp
${SOURCES_DIR}/internal/catch_random_seed_generation.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_registry.hpp
${SOURCES_DIR}/internal/catch_reporter_spec_parser.hpp
${SOURCES_DIR}/internal/catch_result_type.hpp ${SOURCES_DIR}/internal/catch_result_type.hpp
${SOURCES_DIR}/internal/catch_run_context.hpp ${SOURCES_DIR}/internal/catch_run_context.hpp
${SOURCES_DIR}/internal/catch_section.hpp ${SOURCES_DIR}/internal/catch_section.hpp
${SOURCES_DIR}/internal/catch_stdstreams.hpp
${SOURCES_DIR}/catch_section_info.hpp ${SOURCES_DIR}/catch_section_info.hpp
${SOURCES_DIR}/catch_session.hpp ${SOURCES_DIR}/catch_session.hpp
${SOURCES_DIR}/internal/catch_singletons.hpp ${SOURCES_DIR}/internal/catch_singletons.hpp
${SOURCES_DIR}/internal/catch_startup_exception_registry.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_stream_end_stop.hpp
${SOURCES_DIR}/internal/catch_string_manip.hpp ${SOURCES_DIR}/internal/catch_string_manip.hpp
${SOURCES_DIR}/internal/catch_stringref.hpp ${SOURCES_DIR}/internal/catch_stringref.hpp
@@ -148,6 +160,7 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_wildcard_pattern.hpp ${SOURCES_DIR}/internal/catch_wildcard_pattern.hpp
${SOURCES_DIR}/internal/catch_windows_h_proxy.hpp ${SOURCES_DIR}/internal/catch_windows_h_proxy.hpp
${SOURCES_DIR}/internal/catch_xmlwriter.hpp ${SOURCES_DIR}/internal/catch_xmlwriter.hpp
${SOURCES_DIR}/internal/catch_test_case_info_hasher.hpp
) )
set(IMPL_SOURCES set(IMPL_SOURCES
${SOURCES_DIR}/catch_approx.cpp ${SOURCES_DIR}/catch_approx.cpp
@@ -168,8 +181,10 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp ${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
${SOURCES_DIR}/internal/catch_floating_point_helpers.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}/generators/internal/catch_generators_combined_tu.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_combined_tu.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_combined_tu.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp
${SOURCES_DIR}/internal/catch_list.cpp ${SOURCES_DIR}/internal/catch_list.cpp
${SOURCES_DIR}/matchers/catch_matchers_floating_point.cpp ${SOURCES_DIR}/matchers/catch_matchers_floating_point.cpp
@@ -182,12 +197,14 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_random_number_generator.cpp ${SOURCES_DIR}/internal/catch_random_number_generator.cpp
${SOURCES_DIR}/internal/catch_random_seed_generation.cpp ${SOURCES_DIR}/internal/catch_random_seed_generation.cpp
${SOURCES_DIR}/internal/catch_reporter_registry.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_result_type.cpp
${SOURCES_DIR}/internal/catch_run_context.cpp ${SOURCES_DIR}/internal/catch_run_context.cpp
${SOURCES_DIR}/internal/catch_section.cpp ${SOURCES_DIR}/internal/catch_section.cpp
${SOURCES_DIR}/internal/catch_stdstreams.cpp
${SOURCES_DIR}/catch_session.cpp ${SOURCES_DIR}/catch_session.cpp
${SOURCES_DIR}/internal/catch_singletons.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_stringref.cpp
${SOURCES_DIR}/internal/catch_string_manip.cpp ${SOURCES_DIR}/internal/catch_string_manip.cpp
${SOURCES_DIR}/internal/catch_tag_alias_registry.cpp ${SOURCES_DIR}/internal/catch_tag_alias_registry.cpp
@@ -204,6 +221,8 @@ set(IMPL_SOURCES
${SOURCES_DIR}/catch_version.cpp ${SOURCES_DIR}/catch_version.cpp
${SOURCES_DIR}/internal/catch_wildcard_pattern.cpp ${SOURCES_DIR}/internal/catch_wildcard_pattern.cpp
${SOURCES_DIR}/internal/catch_xmlwriter.cpp ${SOURCES_DIR}/internal/catch_xmlwriter.cpp
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
${SOURCES_DIR}/generators/catch_generators_random.cpp
) )
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS}) set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
@@ -211,13 +230,15 @@ set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
set(REPORTER_HEADERS set(REPORTER_HEADERS
${SOURCES_DIR}/reporters/catch_reporters_all.hpp ${SOURCES_DIR}/reporters/catch_reporters_all.hpp
${SOURCES_DIR}/reporters/catch_reporter_automake.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_compact.hpp
${SOURCES_DIR}/reporters/catch_reporter_console.hpp ${SOURCES_DIR}/reporters/catch_reporter_console.hpp
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.hpp ${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_event_listener.hpp ${SOURCES_DIR}/reporters/catch_reporter_event_listener.hpp
${SOURCES_DIR}/reporters/catch_reporter_helpers.hpp ${SOURCES_DIR}/reporters/catch_reporter_helpers.hpp
${SOURCES_DIR}/reporters/catch_reporter_junit.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_registrars.hpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.hpp ${SOURCES_DIR}/reporters/catch_reporter_sonarqube.hpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.hpp ${SOURCES_DIR}/reporters/catch_reporter_streaming_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_tap.hpp ${SOURCES_DIR}/reporters/catch_reporter_tap.hpp
@@ -227,11 +248,13 @@ set(REPORTER_HEADERS
set(REPORTER_SOURCES set(REPORTER_SOURCES
${SOURCES_DIR}/reporters/catch_reporter_automake.cpp ${SOURCES_DIR}/reporters/catch_reporter_automake.cpp
${SOURCES_DIR}/reporters/catch_reporter_combined_tu.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_compact.cpp
${SOURCES_DIR}/reporters/catch_reporter_console.cpp ${SOURCES_DIR}/reporters/catch_reporter_console.cpp
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.cpp ${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_junit.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_registrars.cpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.cpp ${SOURCES_DIR}/reporters/catch_reporter_sonarqube.cpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.cpp ${SOURCES_DIR}/reporters/catch_reporter_streaming_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_tap.cpp ${SOURCES_DIR}/reporters/catch_reporter_tap.cpp
@@ -282,9 +305,15 @@ target_compile_features(Catch2
cxx_variadic_macros 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 target_include_directories(Catch2
PUBLIC PUBLIC
$<BUILD_INTERFACE:${SOURCES_DIR}/..> $<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-includes>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
@@ -323,7 +352,15 @@ if (NOT_SUBPROJECT)
${CATCH_CMAKE_CONFIG_DESTINATION} ${CATCH_CMAKE_CONFIG_DESTINATION}
) )
# Install the headers # 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() endif()
# Some tests require a full recompilation of Catch2 lib with different # Some tests require a full recompilation of Catch2 lib with different
@@ -342,6 +379,7 @@ if (CATCH_BUILD_EXAMPLES OR CATCH_BUILD_EXTRA_TESTS)
target_include_directories(Catch2_buildall_interface target_include_directories(Catch2_buildall_interface
INTERFACE INTERFACE
$<BUILD_INTERFACE:${SOURCES_DIR}/..> $<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-includes>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
target_compile_features(Catch2_buildall_interface target_compile_features(Catch2_buildall_interface

View File

@@ -95,8 +95,11 @@ namespace Catch {
// sets lambda to be used in fun *and* executes benchmark! // sets lambda to be used in fun *and* executes benchmark!
template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0> template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0>
Benchmark & operator=(Fun func) { Benchmark & operator=(Fun func) {
fun = Detail::BenchmarkFunction(func); auto const* cfg = getCurrentContext().getConfig();
run(); if (!cfg->skipBenchmarks()) {
fun = Detail::BenchmarkFunction(func);
run();
}
return *this; return *this;
} }

View File

@@ -20,9 +20,7 @@ namespace Catch {
template <typename T, bool Destruct> template <typename T, bool Destruct>
struct ObjectStorage struct ObjectStorage
{ {
using TStorage = std::aligned_storage_t<sizeof(T), std::alignment_of<T>::value>; ObjectStorage() = default;
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other) ObjectStorage(const ObjectStorage& other)
{ {
@@ -31,7 +29,7 @@ namespace Catch {
ObjectStorage(ObjectStorage&& other) ObjectStorage(ObjectStorage&& other)
{ {
new(&data) T(CATCH_MOVE(other.stored_object())); new(data) T(CATCH_MOVE(other.stored_object()));
} }
~ObjectStorage() { destruct_on_exit<T>(); } ~ObjectStorage() { destruct_on_exit<T>(); }
@@ -39,7 +37,7 @@ namespace Catch {
template <typename... Args> template <typename... Args>
void construct(Args&&... args) void construct(Args&&... args)
{ {
new (&data) T(CATCH_FORWARD(args)...); new (data) T(CATCH_FORWARD(args)...);
} }
template <bool AllowManualDestruction = !Destruct> template <bool AllowManualDestruction = !Destruct>
@@ -51,21 +49,21 @@ namespace Catch {
private: private:
// If this is a constructor benchmark, destruct the underlying object // If this is a constructor benchmark, destruct the underlying object
template <typename U> template <typename U>
void destruct_on_exit(std::enable_if_t<Destruct, U>* = 0) { destruct<true>(); } void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); }
// Otherwise, don't // Otherwise, don't
template <typename U> template <typename U>
void destruct_on_exit(std::enable_if_t<!Destruct, U>* = 0) { } void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
T& stored_object() { T& stored_object() {
return *static_cast<T*>(static_cast<void*>(&data)); return *static_cast<T*>(static_cast<void*>(data));
} }
T const& stored_object() const { T const& stored_object() const {
return *static_cast<T*>(static_cast<void*>(&data)); return *static_cast<T*>(static_cast<void*>(data));
} }
TStorage data; alignas( T ) unsigned char data[sizeof( T )]{};
}; };
} // namespace Detail } // namespace Detail

View File

@@ -12,6 +12,7 @@
#include <catch2/internal/catch_compiler_capabilities.hpp> #include <catch2/internal/catch_compiler_capabilities.hpp>
#include <cassert> #include <cassert>
#include <cstddef>
#include <iterator> #include <iterator>
#include <random> #include <random>
@@ -119,11 +120,15 @@ using Catch::Benchmark::Detail::sample;
double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) { double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) {
auto m = Catch::Benchmark::Detail::mean(first, last); auto m = Catch::Benchmark::Detail::mean(first, last);
double variance = std::accumulate(first, last, 0., [m](double a, double b) { double variance = std::accumulate( first,
double diff = b - m; last,
return a + diff * diff; 0.,
}) / (last - first); [m]( double a, double b ) {
return std::sqrt(variance); double diff = b - m;
return a + diff * diff;
} ) /
( last - first );
return std::sqrt( variance );
} }
} }
@@ -132,6 +137,15 @@ namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
bool directCompare( double lhs, double rhs ) { return lhs == rhs; }
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic pop
#endif
double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) { double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) {
auto count = last - first; auto count = last - first;
double idx = (count - 1) * k / static_cast<double>(q); double idx = (count - 1) * k / static_cast<double>(q);
@@ -139,7 +153,9 @@ namespace Catch {
double g = idx - j; double g = idx - j;
std::nth_element(first, first + j, last); std::nth_element(first, first + j, last);
auto xj = first[j]; auto xj = first[j];
if (g == 0) return xj; if ( directCompare( g, 0 ) ) {
return xj;
}
auto xj1 = *std::min_element(first + (j + 1), last); auto xj1 = *std::min_element(first + (j + 1), last);
return xj + g * (xj1 - xj); return xj + g * (xj1 - xj);

View File

@@ -24,6 +24,10 @@ namespace Catch {
namespace Detail { namespace Detail {
using sample = std::vector<double>; using sample = std::vector<double>;
// Used when we know we want == comparison of two doubles
// to centralize warning suppression
bool directCompare( double lhs, double rhs );
double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last); double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
template <typename Iterator> template <typename Iterator>
@@ -54,7 +58,7 @@ namespace Catch {
double mean(Iterator first, Iterator last) { double mean(Iterator first, Iterator last) {
auto count = last - first; auto count = last - first;
double sum = std::accumulate(first, last, 0.); double sum = std::accumulate(first, last, 0.);
return sum / count; return sum / static_cast<double>(count);
} }
template <typename Estimator, typename Iterator> template <typename Estimator, typename Iterator>
@@ -100,22 +104,25 @@ namespace Catch {
}); });
double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
int n = static_cast<int>(resample.size()); long n = static_cast<long>(resample.size());
double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast<double>(n); double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast<double>(n);
// degenerate case with uniform samples // degenerate case with uniform samples
if (prob_n == 0) return { point, point, point, confidence_level }; if ( directCompare( prob_n, 0. ) ) {
return { point, point, point, confidence_level };
}
double bias = normal_quantile(prob_n); double bias = normal_quantile(prob_n);
double z1 = normal_quantile((1. - confidence_level) / 2.); double z1 = normal_quantile((1. - confidence_level) / 2.);
auto cumn = [n](double x) -> int { auto cumn = [n]( double x ) -> long {
return std::lround(normal_cdf(x) * n); }; return std::lround( normal_cdf( x ) * n );
};
auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
double b1 = bias + z1; double b1 = bias + z1;
double b2 = bias - z1; double b2 = bias - z1;
double a1 = a(b1); double a1 = a(b1);
double a2 = a(b2); double a2 = a(b2);
auto lo = static_cast<size_t>((std::max)(cumn(a1), 0)); auto lo = static_cast<size_t>((std::max)(cumn(a1), 0l));
auto hi = static_cast<size_t>((std::min)(cumn(a2), n - 1)); auto hi = static_cast<size_t>((std::min)(cumn(a2), n - 1));
return { point, resample[lo], resample[hi], confidence_level }; return { point, resample[lo], resample[hi], confidence_level };

View File

@@ -67,6 +67,7 @@
#include <catch2/internal/catch_exception_translator_registry.hpp> #include <catch2/internal/catch_exception_translator_registry.hpp>
#include <catch2/internal/catch_fatal_condition_handler.hpp> #include <catch2/internal/catch_fatal_condition_handler.hpp>
#include <catch2/internal/catch_floating_point_helpers.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_lazy_expr.hpp>
#include <catch2/internal/catch_leak_detector.hpp> #include <catch2/internal/catch_leak_detector.hpp>
#include <catch2/internal/catch_list.hpp> #include <catch2/internal/catch_list.hpp>
@@ -79,22 +80,26 @@
#include <catch2/internal/catch_platform.hpp> #include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_polyfills.hpp> #include <catch2/internal/catch_polyfills.hpp>
#include <catch2/internal/catch_preprocessor.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_number_generator.hpp>
#include <catch2/internal/catch_random_seed_generation.hpp> #include <catch2/internal/catch_random_seed_generation.hpp>
#include <catch2/internal/catch_reporter_registry.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_result_type.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_run_context.hpp> #include <catch2/internal/catch_run_context.hpp>
#include <catch2/internal/catch_section.hpp> #include <catch2/internal/catch_section.hpp>
#include <catch2/internal/catch_sharding.hpp> #include <catch2/internal/catch_sharding.hpp>
#include <catch2/internal/catch_singletons.hpp> #include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_source_line_info.hpp> #include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_startup_exception_registry.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_stream_end_stop.hpp>
#include <catch2/internal/catch_string_manip.hpp> #include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp> #include <catch2/internal/catch_tag_alias_registry.hpp>
#include <catch2/internal/catch_template_test_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_registry_impl.hpp>
#include <catch2/internal/catch_test_case_tracker.hpp> #include <catch2/internal/catch_test_case_tracker.hpp>
#include <catch2/internal/catch_test_failure_exception.hpp> #include <catch2/internal/catch_test_failure_exception.hpp>

View File

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

View File

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

View File

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

View File

@@ -6,46 +6,25 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_config.hpp> #include <catch2/catch_config.hpp>
#include <catch2/catch_user_config.hpp>
#include <catch2/internal/catch_enforce.hpp> #include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_string_manip.hpp> #include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_test_spec_parser.hpp> #include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/interfaces/catch_interfaces_tag_alias_registry.hpp> #include <catch2/interfaces/catch_interfaces_tag_alias_registry.hpp>
#include <ostream>
namespace Catch { namespace Catch {
namespace Detail {
namespace {
class RDBufStream : public IStream {
mutable std::ostream m_os;
public: bool operator==( ProcessedReporterSpec const& lhs,
//! The streambuf `sb` must outlive the constructed object. ProcessedReporterSpec const& rhs ) {
RDBufStream( std::streambuf* sb ): m_os( sb ) {} return lhs.name == rhs.name &&
~RDBufStream() override = default; lhs.outputFilename == rhs.outputFilename &&
lhs.colourMode == rhs.colourMode &&
public: // IStream lhs.customOptions == rhs.customOptions;
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 << " }";
} }
Config::Config( ConfigData const& data ): Config::Config( ConfigData const& data ):
m_data( data ), m_data( data ) {
m_defaultStream( openStream( data.defaultOutputFilename ) ) {
// We need to trim filter specs to avoid trouble with superfluous // We need to trim filter specs to avoid trouble with superfluous
// whitespace (esp. important for bdd macros, as those are manually // whitespace (esp. important for bdd macros, as those are manually
// aligned with whitespace). // aligned with whitespace).
@@ -57,6 +36,7 @@ namespace Catch {
elem = trim(elem); elem = trim(elem);
} }
TestSpecParser parser(ITagAliasRegistry::get()); TestSpecParser parser(ITagAliasRegistry::get());
if (!m_data.testsOrTags.empty()) { if (!m_data.testsOrTags.empty()) {
m_hasTestFilters = true; m_hasTestFilters = true;
@@ -66,15 +46,62 @@ namespace Catch {
} }
m_testSpec = parser.testSpec(); m_testSpec = parser.testSpec();
m_reporterStreams.reserve( m_data.reporterSpecifications.size() );
for ( auto const& reporterAndFile : m_data.reporterSpecifications ) { // Insert the default reporter if user hasn't asked for a specfic one
if ( reporterAndFile.outputFileName.none() ) { if ( m_data.reporterSpecifications.empty() ) {
m_reporterStreams.emplace_back( new Detail::RDBufStream( m_data.reporterSpecifications.push_back( {
m_defaultStream->stream().rdbuf() ) ); #if defined( CATCH_CONFIG_DEFAULT_REPORTER )
} else { CATCH_CONFIG_DEFAULT_REPORTER,
m_reporterStreams.emplace_back( #else
openStream( *reporterAndFile.outputFileName ) ); "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() } );
} }
} }
@@ -84,16 +111,18 @@ namespace Catch {
bool Config::listTests() const { return m_data.listTests; } bool Config::listTests() const { return m_data.listTests; }
bool Config::listTags() const { return m_data.listTags; } bool Config::listTags() const { return m_data.listTags; }
bool Config::listReporters() const { return m_data.listReporters; } bool Config::listReporters() const { return m_data.listReporters; }
bool Config::listListeners() const { return m_data.listListeners; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
std::vector<ConfigData::ReporterAndFile> const& Config::getReportersAndOutputFiles() const { std::vector<ReporterSpec> const& Config::getReporterSpecs() const {
return m_data.reporterSpecifications; return m_data.reporterSpecifications;
} }
std::ostream& Config::getReporterOutputStream(std::size_t reporterIdx) const { std::vector<ProcessedReporterSpec> const&
return m_reporterStreams.at(reporterIdx)->stream(); Config::getProcessedReporterSpecs() const {
return m_processedReporterSpecs;
} }
TestSpec const& Config::testSpec() const { return m_testSpec; } TestSpec const& Config::testSpec() const { return m_testSpec; }
@@ -103,7 +132,6 @@ namespace Catch {
// IConfig interface // IConfig interface
bool Config::allowThrows() const { return !m_data.noThrow; } 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; } 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::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const { bool Config::warnAboutMissingAssertions() const {
@@ -119,20 +147,17 @@ namespace Catch {
uint32_t Config::rngSeed() const { return m_data.rngSeed; } uint32_t Config::rngSeed() const { return m_data.rngSeed; }
unsigned int Config::shardCount() const { return m_data.shardCount; } unsigned int Config::shardCount() const { return m_data.shardCount; }
unsigned int Config::shardIndex() const { return m_data.shardIndex; } 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; } bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
int Config::abortAfter() const { return m_data.abortAfter; } int Config::abortAfter() const { return m_data.abortAfter; }
bool Config::showInvisibles() const { return m_data.showInvisibles; } bool Config::showInvisibles() const { return m_data.showInvisibles; }
Verbosity Config::verbosity() const { return m_data.verbosity; } Verbosity Config::verbosity() const { return m_data.verbosity; }
bool Config::skipBenchmarks() const { return m_data.skipBenchmarks; }
bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
unsigned int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } unsigned int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); } 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 } // end namespace Catch

View File

@@ -12,32 +12,43 @@
#include <catch2/interfaces/catch_interfaces_config.hpp> #include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_optional.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_random_seed_generation.hpp>
#include <catch2/internal/catch_reporter_spec_parser.hpp>
#include <iosfwd> #include <chrono>
#include <vector> #include <map>
#include <string> #include <string>
#include <vector>
namespace Catch { 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 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 listTests = false;
bool listTags = false; bool listTags = false;
bool listReporters = false; bool listReporters = false;
bool listListeners = false;
bool showSuccessfulTests = false; bool showSuccessfulTests = false;
bool shouldDebugBreak = false; bool shouldDebugBreak = false;
@@ -54,6 +65,7 @@ namespace Catch {
unsigned int shardCount = 1; unsigned int shardCount = 1;
unsigned int shardIndex = 0; unsigned int shardIndex = 0;
bool skipBenchmarks = false;
bool benchmarkNoAnalysis = false; bool benchmarkNoAnalysis = false;
unsigned int benchmarkSamples = 100; unsigned int benchmarkSamples = 100;
double benchmarkConfidenceInterval = 0.95; double benchmarkConfidenceInterval = 0.95;
@@ -65,21 +77,13 @@ namespace Catch {
ShowDurations showDurations = ShowDurations::DefaultForReporter; ShowDurations showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1; double minDuration = -1;
TestRunOrder runOrder = TestRunOrder::Declared; TestRunOrder runOrder = TestRunOrder::Declared;
UseColour useColour = UseColour::Auto; ColourMode defaultColourMode = ColourMode::PlatformDefault;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
std::string defaultOutputFilename; std::string defaultOutputFilename;
std::string name; std::string name;
std::string processName; std::string processName;
#ifndef CATCH_CONFIG_DEFAULT_REPORTER std::vector<ReporterSpec> reporterSpecifications;
#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<std::string> testsOrTags; std::vector<std::string> testsOrTags;
std::vector<std::string> sectionsToRun; std::vector<std::string> sectionsToRun;
@@ -96,9 +100,11 @@ namespace Catch {
bool listTests() const; bool listTests() const;
bool listTags() const; bool listTags() const;
bool listReporters() const; bool listReporters() const;
bool listListeners() const;
std::vector<ConfigData::ReporterAndFile> const& getReportersAndOutputFiles() const; std::vector<ReporterSpec> const& getReporterSpecs() const;
std::ostream& getReporterOutputStream(std::size_t reporterIdx) const; std::vector<ProcessedReporterSpec> const&
getProcessedReporterSpecs() const;
std::vector<std::string> const& getTestsOrTags() const override; std::vector<std::string> const& getTestsOrTags() const override;
std::vector<std::string> const& getSectionsToRun() const override; std::vector<std::string> const& getSectionsToRun() const override;
@@ -110,7 +116,6 @@ namespace Catch {
// IConfig interface // IConfig interface
bool allowThrows() const override; bool allowThrows() const override;
std::ostream& defaultStream() const override;
StringRef name() const override; StringRef name() const override;
bool includeSuccessfulResults() const override; bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override; bool warnAboutMissingAssertions() const override;
@@ -122,11 +127,12 @@ namespace Catch {
uint32_t rngSeed() const override; uint32_t rngSeed() const override;
unsigned int shardCount() const override; unsigned int shardCount() const override;
unsigned int shardIndex() const override; unsigned int shardIndex() const override;
UseColour useColour() const override; ColourMode defaultColourMode() const override;
bool shouldDebugBreak() const override; bool shouldDebugBreak() const override;
int abortAfter() const override; int abortAfter() const override;
bool showInvisibles() const override; bool showInvisibles() const override;
Verbosity verbosity() const override; Verbosity verbosity() const override;
bool skipBenchmarks() const override;
bool benchmarkNoAnalysis() const override; bool benchmarkNoAnalysis() const override;
unsigned int benchmarkSamples() const override; unsigned int benchmarkSamples() const override;
double benchmarkConfidenceInterval() const override; double benchmarkConfidenceInterval() const override;
@@ -134,11 +140,8 @@ namespace Catch {
std::chrono::milliseconds benchmarkWarmupTime() const override; std::chrono::milliseconds benchmarkWarmupTime() const override;
private: private:
Detail::unique_ptr<IStream const> openStream(std::string const& outputFileName);
ConfigData m_data; ConfigData m_data;
std::vector<ProcessedReporterSpec> m_processedReporterSpecs;
Detail::unique_ptr<IStream const> m_defaultStream;
std::vector<Detail::unique_ptr<IStream const>> m_reporterStreams;
TestSpec m_testSpec; TestSpec m_testSpec;
bool m_hasTestFilters = false; bool m_hasTestFilters = false;
}; };

View File

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

View File

@@ -7,8 +7,6 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_case_info.hpp> #include <catch2/catch_test_case_info.hpp>
#include <catch2/internal/catch_enforce.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_string_manip.hpp>
#include <catch2/internal/catch_case_insensitive_comparisons.hpp> #include <catch2/internal/catch_case_insensitive_comparisons.hpp>
@@ -60,7 +58,7 @@ namespace Catch {
else if( tag == "!nonportable"_sr ) else if( tag == "!nonportable"_sr )
return TestCaseProperties::NonPortable; return TestCaseProperties::NonPortable;
else if( tag == "!benchmark"_sr ) else if( tag == "!benchmark"_sr )
return static_cast<TestCaseProperties>(TestCaseProperties::Benchmark | TestCaseProperties::IsHidden ); return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
else else
return TestCaseProperties::None; return TestCaseProperties::None;
} }

View File

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

View File

@@ -10,7 +10,7 @@
#include <catch2/internal/catch_test_macro_impl.hpp> #include <catch2/internal/catch_test_macro_impl.hpp>
#include <catch2/catch_message.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_section.hpp>
#include <catch2/internal/catch_test_registry.hpp> #include <catch2/internal/catch_test_registry.hpp>
#include <catch2/internal/catch_unique_name.hpp> #include <catch2/internal/catch_unique_name.hpp>

View File

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

View File

@@ -17,7 +17,7 @@
#include <catch2/internal/catch_compiler_capabilities.hpp> #include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_config_wchar.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/internal/catch_void_type.hpp>
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp> #include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>

View File

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

View File

@@ -81,4 +81,4 @@ namespace Catch {
#endif #endif
#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED #endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED

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() { Version const& libraryVersion() {
static Version version( 3, 0, 0, "preview", 4 ); static Version version( 3, 0, 1, "", 0 );
return version; return version;
} }

View File

@@ -10,6 +10,6 @@
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 0 #define CATCH_VERSION_MINOR 0
#define CATCH_VERSION_PATCH 0 #define CATCH_VERSION_PATCH 1
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED

View File

@@ -8,10 +8,13 @@
#ifndef CATCH_GENERATORS_HPP_INCLUDED #ifndef CATCH_GENERATORS_HPP_INCLUDED
#define CATCH_GENERATORS_HPP_INCLUDED #define CATCH_GENERATORS_HPP_INCLUDED
#include <catch2/catch_tostring.hpp>
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp> #include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
#include <catch2/internal/catch_source_line_info.hpp> #include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_move_and_forward.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 <vector>
#include <tuple> #include <tuple>
@@ -29,7 +32,12 @@ namespace Detail {
} // end namespace detail } // end namespace detail
template<typename T> template<typename T>
struct IGenerator : GeneratorUntypedBase { class IGenerator : public GeneratorUntypedBase {
std::string stringifyImpl() const override {
return ::Catch::Detail::stringify( get() );
}
public:
~IGenerator() override = default; ~IGenerator() override = default;
IGenerator() = default; IGenerator() = default;
IGenerator(IGenerator const&) = default; IGenerator(IGenerator const&) = default;
@@ -61,7 +69,7 @@ namespace Detail {
return m_generator->get(); return m_generator->get();
} }
bool next() { bool next() {
return m_generator->next(); return m_generator->countedNext();
} }
}; };

View File

@@ -0,0 +1,13 @@
// 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/generators/catch_generators_random.hpp>
#include <catch2/internal/catch_context.hpp>
std::uint32_t Catch::Generators::Detail::getSeed() { return sharedRng()(); }

View File

@@ -16,16 +16,21 @@
namespace Catch { namespace Catch {
namespace Generators { namespace Generators {
namespace Detail {
// Returns a suitable seed for a random floating generator based off
// the primary internal rng. It does so by taking current value from
// the rng and returning it as the seed.
std::uint32_t getSeed();
}
template <typename Float> template <typename Float>
class RandomFloatingGenerator final : public IGenerator<Float> { class RandomFloatingGenerator final : public IGenerator<Float> {
Catch::SimplePcg32& m_rng; Catch::SimplePcg32 m_rng;
std::uniform_real_distribution<Float> m_dist; std::uniform_real_distribution<Float> m_dist;
Float m_current_number; Float m_current_number;
public: public:
RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
RandomFloatingGenerator(Float a, Float b): m_rng(seed),
m_rng(rng()),
m_dist(a, b) { m_dist(a, b) {
static_cast<void>(next()); static_cast<void>(next());
} }
@@ -41,13 +46,12 @@ public:
template <typename Integer> template <typename Integer>
class RandomIntegerGenerator final : public IGenerator<Integer> { class RandomIntegerGenerator final : public IGenerator<Integer> {
Catch::SimplePcg32& m_rng; Catch::SimplePcg32 m_rng;
std::uniform_int_distribution<Integer> m_dist; std::uniform_int_distribution<Integer> m_dist;
Integer m_current_number; Integer m_current_number;
public: public:
RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
RandomIntegerGenerator(Integer a, Integer b): m_rng(seed),
m_rng(rng()),
m_dist(a, b) { m_dist(a, b) {
static_cast<void>(next()); static_cast<void>(next());
} }
@@ -68,7 +72,7 @@ std::enable_if_t<std::is_integral<T>::value && !std::is_same<T, bool>::value,
GeneratorWrapper<T>> GeneratorWrapper<T>>
random(T a, T b) { random(T a, T b) {
return GeneratorWrapper<T>( return GeneratorWrapper<T>(
Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b) Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
); );
} }
@@ -77,7 +81,7 @@ std::enable_if_t<std::is_floating_point<T>::value,
GeneratorWrapper<T>> GeneratorWrapper<T>>
random(T a, T b) { random(T a, T b) {
return GeneratorWrapper<T>( return GeneratorWrapper<T>(
Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b) Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
); );
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,32 @@
// 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/interfaces/catch_interfaces_generatortracker.hpp>
#include <string>
namespace Catch {
namespace Generators {
bool GeneratorUntypedBase::countedNext() {
auto ret = next();
if ( ret ) {
m_stringReprCache.clear();
++m_currentElementIndex;
}
return ret;
}
StringRef GeneratorUntypedBase::currentElementAsString() const {
if ( m_stringReprCache.empty() ) {
m_stringReprCache = stringifyImpl();
}
return m_stringReprCache;
}
} // namespace Generators
} // namespace Catch

View File

@@ -9,11 +9,32 @@
#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED #define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <string>
namespace Catch { namespace Catch {
namespace Generators { namespace Generators {
class GeneratorUntypedBase { class GeneratorUntypedBase {
// Caches result from `toStringImpl`, assume that when it is an
// empty string, the cache is invalidated.
mutable std::string m_stringReprCache;
// Counts based on `next` returning true
std::size_t m_currentElementIndex = 0;
/**
* Attempts to move the generator to the next element
*
* Returns true iff the move succeeded (and a valid element
* can be retrieved).
*/
virtual bool next() = 0;
//! Customization point for `currentElementAsString`
virtual std::string stringifyImpl() const = 0;
public: public:
GeneratorUntypedBase() = default; GeneratorUntypedBase() = default;
// Generation of copy ops is deprecated (and Clang will complain) // Generation of copy ops is deprecated (and Clang will complain)
@@ -23,17 +44,41 @@ namespace Catch {
virtual ~GeneratorUntypedBase(); // = default; virtual ~GeneratorUntypedBase(); // = default;
// Attempts to move the generator to the next element /**
// * Attempts to move the generator to the next element
// Returns true iff the move succeeded (and a valid element *
// can be retrieved). * Serves as a non-virtual interface to `next`, so that the
virtual bool next() = 0; * top level interface can provide sanity checking and shared
* features.
*
* As with `next`, returns true iff the move succeeded and
* the generator has new valid element to provide.
*/
bool countedNext();
std::size_t currentElementIndex() const { return m_currentElementIndex; }
/**
* Returns generator's current element as user-friendly string.
*
* By default returns string equivalent to calling
* `Catch::Detail::stringify` on the current element, but generators
* can customize their implementation as needed.
*
* Not thread-safe due to internal caching.
*
* The returned ref is valid only until the generator instance
* is destructed, or it moves onto the next element, whichever
* comes first.
*/
StringRef currentElementAsString() const;
}; };
using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>; using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
} // namespace Generators } // namespace Generators
struct IGeneratorTracker { class IGeneratorTracker {
public:
virtual ~IGeneratorTracker(); // = default; virtual ~IGeneratorTracker(); // = default;
virtual auto hasGenerator() const -> bool = 0; virtual auto hasGenerator() const -> bool = 0;
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;

View File

@@ -16,21 +16,23 @@ namespace Catch {
class TestCaseHandle; class TestCaseHandle;
struct TestCaseInfo; struct TestCaseInfo;
struct ITestCaseRegistry; class ITestCaseRegistry;
struct IExceptionTranslatorRegistry; class IExceptionTranslatorRegistry;
struct IExceptionTranslator; class IExceptionTranslator;
struct IReporterRegistry; class IReporterRegistry;
struct IReporterFactory; class IReporterFactory;
struct ITagAliasRegistry; class ITagAliasRegistry;
struct ITestInvoker; class ITestInvoker;
struct IMutableEnumValuesRegistry; class IMutableEnumValuesRegistry;
struct SourceLineInfo; struct SourceLineInfo;
class StartupExceptionRegistry; class StartupExceptionRegistry;
class EventListenerFactory;
using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
struct IRegistryHub { class IRegistryHub {
public:
virtual ~IRegistryHub(); // = default virtual ~IRegistryHub(); // = default
virtual IReporterRegistry const& getReporterRegistry() const = 0; virtual IReporterRegistry const& getReporterRegistry() const = 0;
@@ -42,10 +44,11 @@ namespace Catch {
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
}; };
struct IMutableRegistryHub { class IMutableRegistryHub {
public:
virtual ~IMutableRegistryHub(); // = default virtual ~IMutableRegistryHub(); // = default
virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0; 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 registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0;
virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 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; 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/internal/catch_string_manip.hpp>
#include <catch2/catch_test_case_info.hpp> #include <catch2/catch_test_case_info.hpp>
#include <catch2/reporters/catch_reporter_helpers.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 <algorithm>
#include <cassert>
#include <iomanip> #include <iomanip>
namespace Catch { namespace Catch {
ReporterConfig::ReporterConfig( IConfig const* _fullConfig, std::ostream& _stream ) ReporterConfig::ReporterConfig(
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {} 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; } 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, AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages, std::vector<MessageInfo> const& _infoMessages,
@@ -78,6 +99,6 @@ namespace Catch {
aborting( _aborting ) aborting( _aborting )
{} {}
IStreamingReporter::~IStreamingReporter() = default; IEventListener::~IEventListener() = default;
} // end namespace Catch } // end namespace Catch

View File

@@ -19,6 +19,7 @@
#include <catch2/benchmark/catch_outlier_classification.hpp> #include <catch2/benchmark/catch_outlier_classification.hpp>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iosfwd> #include <iosfwd>
@@ -26,20 +27,34 @@
namespace Catch { namespace Catch {
struct ReporterDescription; struct ReporterDescription;
struct ListenerDescription;
struct TagInfo; struct TagInfo;
struct TestCaseInfo; struct TestCaseInfo;
class TestCaseHandle; class TestCaseHandle;
struct IConfig; class IConfig;
class IStream;
enum class ColourMode : std::uint8_t;
struct ReporterConfig { 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; IConfig const* fullConfig() const;
ColourMode colourMode() const;
std::map<std::string, std::string> const& customOptions() const;
private: private:
std::ostream* m_stream; Detail::unique_ptr<IStream> m_stream;
IConfig const* m_fullConfig; IConfig const* m_fullConfig;
ColourMode m_colourMode;
std::map<std::string, std::string> m_customOptions;
}; };
struct TestRunInfo { struct TestRunInfo {
@@ -149,8 +164,19 @@ namespace Catch {
bool shouldReportAllAssertions = false; 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: protected:
//! Derived classes can set up their preferences here //! Derived classes can set up their preferences here
ReporterPreferences m_preferences; ReporterPreferences m_preferences;
@@ -158,9 +184,9 @@ namespace Catch {
IConfig const* m_config; IConfig const* m_config;
public: 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: // Implementing class must also provide the following static methods:
// static std::string getDescription(); // static std::string getDescription();
@@ -224,13 +250,14 @@ namespace Catch {
//! Writes out information about provided reporters using reporter-specific format //! Writes out information about provided reporters using reporter-specific format
virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0; virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
//! Writes out the provided listeners descriptions using reporter-specific format
virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
//! Writes out information about provided tests using reporter-specific format //! Writes out information about provided tests using reporter-specific format
virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0; virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
//! Writes out information about the provided tags using reporter-specific format //! Writes out information about the provided tags using reporter-specific format
virtual void listTags(std::vector<TagInfo> const& tags) = 0; virtual void listTags(std::vector<TagInfo> const& tags) = 0;
}; };
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>; using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
} // end namespace Catch } // end namespace Catch

View File

@@ -9,24 +9,37 @@
#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED #define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <string> #include <string>
namespace Catch { namespace Catch {
struct ReporterConfig; struct ReporterConfig;
struct IStreamingReporter; class IConfig;
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>; class IEventListener;
using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
struct IReporterFactory { class IReporterFactory {
public:
virtual ~IReporterFactory(); // = default virtual ~IReporterFactory(); // = default
virtual IStreamingReporterPtr virtual IEventListenerPtr
create( ReporterConfig const& config ) const = 0; create( ReporterConfig&& config ) const = 0;
virtual std::string getDescription() const = 0; virtual std::string getDescription() const = 0;
}; };
using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
class EventListenerFactory {
public:
virtual ~EventListenerFactory(); // = default
virtual IEventListenerPtr create( IConfig const* config ) const = 0;
//! Return a meaningful name for the listener, e.g. its type name
virtual StringRef getName() const = 0;
//! Return listener's description if available
virtual std::string getDescription() const = 0;
};
} // namespace Catch } // namespace Catch
#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED #endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,13 +5,16 @@
// https://www.boost.org/LICENSE_1_0.txt) // https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <algorithm>
#include <catch2/internal/catch_clara.hpp> #include <catch2/internal/catch_clara.hpp>
#include <catch2/internal/catch_console_width.hpp> #include <catch2/internal/catch_console_width.hpp>
#include <catch2/internal/catch_platform.hpp> #include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_string_manip.hpp> #include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_textflow.hpp> #include <catch2/internal/catch_textflow.hpp>
#include <algorithm>
#include <ostream>
namespace { namespace {
bool isOptPrefix( char c ) { bool isOptPrefix( char c ) {
return c == '-' return c == '-'
@@ -230,7 +233,7 @@ namespace Catch {
return Detail::InternalParseResult::runtimeError( return Detail::InternalParseResult::runtimeError(
"Expected argument following " + "Expected argument following " +
token.token); token.token);
auto result = valueRef->setValue(argToken.token); const auto result = valueRef->setValue(argToken.token);
if (!result) if (!result)
return Detail::InternalParseResult(result); return Detail::InternalParseResult(result);
if (result.value() == if (result.value() ==

View File

@@ -34,7 +34,6 @@
#include <catch2/internal/catch_void_type.hpp> #include <catch2/internal/catch_void_type.hpp>
#include <cassert> #include <cassert>
#include <cctype>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
@@ -589,12 +588,6 @@ namespace Catch {
std::shared_ptr<std::string> m_name; std::shared_ptr<std::string> m_name;
std::shared_ptr<Detail::BoundValueRefBase> m_ref; 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: public:
ExeName(); ExeName();
explicit ExeName(std::string& ref); explicit ExeName(std::string& ref);

View File

@@ -12,9 +12,9 @@
#include <catch2/internal/catch_string_manip.hpp> #include <catch2/internal/catch_string_manip.hpp>
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp> #include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_registry.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 <fstream>
#include <string> #include <string>
@@ -95,19 +95,23 @@ namespace Catch {
return ParserResult::runtimeError("Could not parse '" + seed + "' as seed"); return ParserResult::runtimeError("Could not parse '" + seed + "' as seed");
} }
}; };
auto const setColourUsage = [&]( std::string const& useColour ) { auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
auto mode = toLower( useColour ); Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
if ( !maybeMode ) {
if( mode == "yes" ) return ParserResult::runtimeError(
config.useColour = UseColour::Yes; "colour mode must be one of: default, ansi, win32, "
else if( mode == "no" ) "or none. '" +
config.useColour = UseColour::No; colourMode + "' is not recognised" );
else if( mode == "auto" ) }
config.useColour = UseColour::Auto; auto mode = *maybeMode;
else if ( !isColourImplAvailable( mode ) ) {
return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); return ParserResult::runtimeError(
return ParserResult::ok( ParseResultType::Matched ); "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 const setWaitForKeypress = [&]( std::string const& keypress ) {
auto keypressLc = toLower( keypress ); auto keypressLc = toLower( keypress );
if (keypressLc == "never") if (keypressLc == "never")
@@ -134,64 +138,42 @@ namespace Catch {
return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' ); return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' );
return ParserResult::ok( ParseResultType::Matched ); return ParserResult::ok( ParseResultType::Matched );
}; };
auto const setReporter = [&]( std::string const& reporterSpec ) { auto const setReporter = [&]( std::string const& userReporterSpec ) {
if ( reporterSpec.empty() ) { if ( userReporterSpec.empty() ) {
return ParserResult::runtimeError( "Received empty reporter spec." ); 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 auto const& reporterSpec = *parsed;
if (!config._nonDefaultReporterSpecifications) {
config.reporterSpecifications.clear(); IReporterRegistry::FactoryMap const& factories =
config._nonDefaultReporterSpecifications = true; 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 const bool hadOutputFile = reporterSpec.outputFile().some();
// file, in which case it defaults to the output specified by "-o" config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
// (or standard output). // It would be enough to check this only once at the very end, but
static constexpr auto separator = "::"; // there is not a place where we could call this check, so do it
static constexpr size_t separatorSize = 2; // every time it could fail. For valid inputs, this is still called
auto fileNameSeparatorPos = reporterSpec.find( separator ); // at most once.
const bool containsFileName = fileNameSeparatorPos != reporterSpec.npos; if (!hadOutputFile) {
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) {
int n_reporters_without_file = 0; int n_reporters_without_file = 0;
for (auto const& spec : config.reporterSpecifications) { for (auto const& spec : config.reporterSpecifications) {
if (spec.outputFileName.none()) { if (spec.outputFile().none()) {
n_reporters_without_file++; n_reporters_without_file++;
} }
} }
@@ -257,7 +239,7 @@ namespace Catch {
| Opt( config.defaultOutputFilename, "filename" ) | Opt( config.defaultOutputFilename, "filename" )
["-o"]["--out"] ["-o"]["--out"]
( "default output filename" ) ( "default output filename" )
| Opt( accept_many, setReporter, "name[:output-file]" ) | Opt( accept_many, setReporter, "name[::key=value]*" )
["-r"]["--reporter"] ["-r"]["--reporter"]
( "reporter to use (defaults to console)" ) ( "reporter to use (defaults to console)" )
| Opt( config.name, "name" ) | Opt( config.name, "name" )
@@ -298,22 +280,28 @@ namespace Catch {
( "list all/matching tags" ) ( "list all/matching tags" )
| Opt( config.listReporters ) | Opt( config.listReporters )
["--list-reporters"] ["--list-reporters"]
( "list all reporters" ) ( "list all available reporters" )
| Opt( config.listListeners )
["--list-listeners"]
( "list all listeners" )
| Opt( setTestOrder, "decl|lex|rand" ) | Opt( setTestOrder, "decl|lex|rand" )
["--order"] ["--order"]
( "test case order (defaults to decl)" ) ( "test case order (defaults to decl)" )
| Opt( setRngSeed, "'time'|'random-device'|number" ) | Opt( setRngSeed, "'time'|'random-device'|number" )
["--rng-seed"] ["--rng-seed"]
( "set a specific seed for random numbers" ) ( "set a specific seed for random numbers" )
| Opt( setColourUsage, "yes|no" ) | Opt( setDefaultColourMode, "ansi|win32|none|default" )
["--use-colour"] ["--colour-mode"]
( "should output be colourised" ) ( "what color mode should be used as default" )
| Opt( config.libIdentify ) | Opt( config.libIdentify )
["--libidentify"] ["--libidentify"]
( "report name and version according to libidentify standard" ) ( "report name and version according to libidentify standard" )
| Opt( setWaitForKeypress, "never|start|exit|both" ) | Opt( setWaitForKeypress, "never|start|exit|both" )
["--wait-for-keypress"] ["--wait-for-keypress"]
( "waits for a keypress before exiting" ) ( "waits for a keypress before exiting" )
| Opt( config.skipBenchmarks)
["--skip-benchmarks"]
( "disable running benchmarks")
| Opt( config.benchmarkSamples, "samples" ) | Opt( config.benchmarkSamples, "samples" )
["--benchmark-samples"] ["--benchmark-samples"]
( "number of samples to collect (default: 100)" ) ( "number of samples to collect (default: 100)" )

View File

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

View File

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

View File

@@ -15,59 +15,114 @@
#include <catch2/internal/catch_enforce.hpp> #include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_errno_guard.hpp> #include <catch2/internal/catch_errno_guard.hpp>
#include <catch2/interfaces/catch_interfaces_config.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_context.hpp>
#include <catch2/internal/catch_platform.hpp> #include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_debugger.hpp> #include <catch2/internal/catch_debugger.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp> #include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <cassert>
#include <ostream> #include <ostream>
#include <utility>
namespace Catch { 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 { 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 ) {}
struct IColourImpl { private:
virtual ~IColourImpl() = default; void use( Colour::Code ) const override {}
virtual void use( Colour::Code _colourCode ) = 0;
}; };
} // namespace
struct NoColourImpl : IColourImpl {
void use( Colour::Code ) override {}
static IColourImpl* instance() {
static NoColourImpl s_instance;
return &s_instance;
}
};
} // anon namespace
} // namespace Catch } // 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_WIN32 ) /////////////////////////////////////////
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
namespace Catch { namespace Catch {
namespace { namespace {
class Win32ColourImpl : public IColourImpl { class Win32ColourImpl : public ColourImpl {
public: public:
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) Win32ColourImpl(IStream* stream):
{ ColourImpl(stream) {
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 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 ); originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
} }
void use( Colour::Code _colourCode ) override { static bool useImplementationForStream(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 ) { switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -91,45 +146,63 @@ namespace {
} }
} }
private: void setTextAttribute( WORD _textAttribute ) const {
void setTextAttribute( WORD _textAttribute ) { SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ),
SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); _textAttribute |
originalBackgroundAttributes );
} }
HANDLE stdoutHandle;
WORD originalForegroundAttributes; WORD originalForegroundAttributes;
WORD originalBackgroundAttributes; 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 anon namespace
} // end namespace Catch } // 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 Catch {
namespace { namespace {
// use POSIX/ ANSI console terminal codes class ANSIColourImpl : public ColourImpl {
// Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
public: public:
void use( Colour::Code _colourCode ) override { ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {}
static bool useImplementationForStream(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 ) { switch( _colourCode ) {
case Colour::None: case Colour::None:
case Colour::White: return setColour( "[0m" ); case Colour::White: return setColour( "[0m" );
@@ -150,89 +223,59 @@ namespace {
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); 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 anon namespace
} // end namespace Catch } // end namespace Catch
#else // not Windows or ANSI ///////////////////////////////////////////////
namespace Catch { 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::useImplementationForStream( *stream ) ) {
return Detail::make_unique<Win32ColourImpl>( stream );
} else {
return Detail::make_unique<NoColourImpl>( stream );
}
#endif
if ( ANSIColourImpl::useImplementationForStream( *stream ) ) {
return Detail::make_unique<ANSIColourImpl>( stream );
}
return Detail::make_unique<NoColourImpl>( stream );
}
#endif // Windows/ ANSI/ None CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(implSelection) );
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;
} }
Colour::~Colour(){ if( !m_moved ) use( None ); } bool isColourImplAvailable( ColourMode colourSelection ) {
switch ( colourSelection ) {
void Colour::use( Code _colourCode ) { #if defined( CATCH_CONFIG_COLOUR_WIN32 )
static IColourImpl* impl = platformColourInstance(); case ColourMode::Win32:
// Strictly speaking, this cannot possibly happen. #endif
// However, under some conditions it does happen (see #1626), case ColourMode::ANSI:
// and this change is small enough that we can let practicality case ColourMode::None:
// triumph over purity in this case. case ColourMode::PlatformDefault:
if (impl != nullptr) { return true;
impl->use( _colourCode ); default:
return false;
} }
} }
std::ostream& operator << ( std::ostream& os, Colour const& ) {
return os;
}
} // end namespace Catch } // end namespace Catch

View File

@@ -8,10 +8,16 @@
#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED #ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED #define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
#include <catch2/internal/catch_unique_ptr.hpp>
#include <iosfwd> #include <iosfwd>
#include <cstdint>
namespace Catch { namespace Catch {
enum class ColourMode : std::uint8_t;
class IStream;
struct Colour { struct Colour {
enum Code { enum Code {
None = 0, None = 0,
@@ -48,22 +54,86 @@ namespace Catch {
SecondaryText = LightGrey, SecondaryText = LightGrey,
Headers = White 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 } // end namespace Catch

View File

@@ -12,4 +12,4 @@
#define CATCH_CONFIG_CONSOLE_WIDTH 80 #define CATCH_CONFIG_CONSOLE_WIDTH 80
#endif #endif
#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED #endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED

View File

@@ -55,7 +55,7 @@ namespace Catch {
Context::~Context() = default; Context::~Context() = default;
SimplePcg32& rng() { SimplePcg32& sharedRng() {
static SimplePcg32 s_rng; static SimplePcg32 s_rng;
return s_rng; return s_rng;
} }

View File

@@ -10,20 +10,20 @@
namespace Catch { namespace Catch {
struct IResultCapture; class IResultCapture;
struct IConfig; class IConfig;
struct IContext class IContext {
{ public:
virtual ~IContext(); // = default virtual ~IContext(); // = default
virtual IResultCapture* getResultCapture() = 0; virtual IResultCapture* getResultCapture() = 0;
virtual IConfig const* getConfig() const = 0; virtual IConfig const* getConfig() const = 0;
}; };
struct IMutableContext : IContext class IMutableContext : public IContext {
{ public:
virtual ~IMutableContext(); // = default ~IMutableContext() override; // = default
virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
virtual void setConfig( IConfig const* config ) = 0; virtual void setConfig( IConfig const* config ) = 0;
@@ -50,7 +50,7 @@ namespace Catch {
void cleanUpContext(); void cleanUpContext();
class SimplePcg32; class SimplePcg32;
SimplePcg32& rng(); SimplePcg32& sharedRng();
} }
#endif // CATCH_CONTEXT_HPP_INCLUDED #endif // CATCH_CONTEXT_HPP_INCLUDED

View File

@@ -5,11 +5,16 @@
// https://www.boost.org/LICENSE_1_0.txt) // https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_debug_console.hpp> #include <catch2/internal/catch_debug_console.hpp>
#include <catch2/internal/catch_config_android_logwrite.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_platform.hpp>
#include <catch2/internal/catch_windows_h_proxy.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) #if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
#include <android/log.h> #include <android/log.h>

View File

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

View File

@@ -19,7 +19,7 @@ namespace Catch {
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__) #elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000") #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
#endif #endif
#elif defined(CATCH_PLATFORM_IPHONE) #elif defined(CATCH_PLATFORM_IPHONE)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,6 +10,7 @@
#include <catch2/internal/catch_polyfills.hpp> #include <catch2/internal/catch_polyfills.hpp>
#include <cassert>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <utility> #include <utility>
@@ -24,6 +25,15 @@ namespace Catch {
} // end namespace Detail } // end namespace Detail
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic push
// We do a bunch of direct compensations of floating point numbers,
// because we know what we are doing and actually do want the direct
// comparison behaviour.
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
/** /**
* Calculates the ULP distance between two floating point numbers * Calculates the ULP distance between two floating point numbers
* *
@@ -83,6 +93,11 @@ namespace Catch {
return lc - rc; return lc - rc;
} }
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic pop
#endif
} // end namespace Catch } // end namespace Catch
#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED #endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED

View File

@@ -5,15 +5,14 @@
// https://www.boost.org/LICENSE_1_0.txt) // https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_istream.hpp>
#include <catch2/internal/catch_enforce.hpp> #include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_debug_console.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_unique_ptr.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <cstdio> #include <cstdio>
#include <iostream>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
@@ -34,7 +33,7 @@ namespace Detail {
setp( data, data + sizeof(data) ); setp( data, data + sizeof(data) );
} }
~StreamBufImpl() noexcept { ~StreamBufImpl() noexcept override {
StreamBufImpl::sync(); StreamBufImpl::sync();
} }
@@ -74,7 +73,7 @@ namespace Detail {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
class FileStream : public IStream { class FileStream : public IStream {
mutable std::ofstream m_ofs; std::ofstream m_ofs;
public: public:
FileStream( std::string const& filename ) { FileStream( std::string const& filename ) {
m_ofs.open( filename.c_str() ); m_ofs.open( filename.c_str() );
@@ -82,7 +81,7 @@ namespace Detail {
} }
~FileStream() override = default; ~FileStream() override = default;
public: // IStream public: // IStream
std::ostream& stream() const override { std::ostream& stream() override {
return m_ofs; return m_ofs;
} }
}; };
@@ -90,7 +89,7 @@ namespace Detail {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
class CoutStream : public IStream { class CoutStream : public IStream {
mutable std::ostream m_os; std::ostream m_os;
public: public:
// Store the streambuf from cout up-front because // Store the streambuf from cout up-front because
// cout may get redirected when running tests // cout may get redirected when running tests
@@ -98,14 +97,29 @@ namespace Detail {
~CoutStream() override = default; ~CoutStream() override = default;
public: // IStream 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 { class DebugOutStream : public IStream {
Detail::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf; Detail::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
mutable std::ostream m_os; std::ostream m_os;
public: public:
DebugOutStream() DebugOutStream()
: m_streamBuf( Detail::make_unique<StreamBufImpl<OutputDebugWriter>>() ), : m_streamBuf( Detail::make_unique<StreamBufImpl<OutputDebugWriter>>() ),
@@ -115,7 +129,7 @@ namespace Detail {
~DebugOutStream() override = default; ~DebugOutStream() override = default;
public: // IStream public: // IStream
std::ostream& stream() const override { return m_os; } std::ostream& stream() override { return m_os; }
}; };
} // unnamed namespace } // 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 == "-" ) { if ( filename.empty() || filename == "-" ) {
return Detail::make_unique<Detail::CoutStream>(); return Detail::make_unique<Detail::CoutStream>();
} }
else if( filename[0] == '%' ) { if( filename[0] == '%' ) {
if( filename == "%debug" ) if ( filename == "%debug" ) {
return Detail::make_unique<Detail::DebugOutStream>(); 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 << '\'' ); 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;
} }
} }
return Detail::make_unique<Detail::FileStream>( filename );
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 );
}
///////////////////////////////////////////////////////////////////////////
#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 { namespace Catch {
struct ITransientExpression; class ITransientExpression;
class LazyExpression { class LazyExpression {
friend class AssertionHandler; friend class AssertionHandler;

View File

@@ -23,13 +23,13 @@
namespace Catch { namespace Catch {
namespace { namespace {
void listTests(IStreamingReporter& reporter, IConfig const& config) { void listTests(IEventListener& reporter, IConfig const& config) {
auto const& testSpec = config.testSpec(); auto const& testSpec = config.testSpec();
auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config); auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
reporter.listTests(matchedTestCases); reporter.listTests(matchedTestCases);
} }
void listTags(IStreamingReporter& reporter, IConfig const& config) { void listTags(IEventListener& reporter, IConfig const& config) {
auto const& testSpec = config.testSpec(); auto const& testSpec = config.testSpec();
std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config); std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
@@ -51,7 +51,7 @@ namespace Catch {
reporter.listTags(infos); reporter.listTags(infos);
} }
void listReporters(IStreamingReporter& reporter) { void listReporters(IEventListener& reporter) {
std::vector<ReporterDescription> descriptions; std::vector<ReporterDescription> descriptions;
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
@@ -63,6 +63,19 @@ namespace Catch {
reporter.listReporters(descriptions); reporter.listReporters(descriptions);
} }
void listListeners(IEventListener& reporter) {
std::vector<ListenerDescription> descriptions;
auto const& factories =
getRegistryHub().getReporterRegistry().getListeners();
descriptions.reserve( factories.size() );
for ( auto const& fac : factories ) {
descriptions.push_back( { fac->getName(), fac->getDescription() } );
}
reporter.listListeners( descriptions );
}
} // end anonymous namespace } // end anonymous namespace
void TagInfo::add( StringRef spelling ) { void TagInfo::add( StringRef spelling ) {
@@ -86,7 +99,7 @@ namespace Catch {
return out; return out;
} }
bool list( IStreamingReporter& reporter, Config const& config ) { bool list( IEventListener& reporter, Config const& config ) {
bool listed = false; bool listed = false;
if (config.listTests()) { if (config.listTests()) {
listed = true; listed = true;
@@ -100,6 +113,10 @@ namespace Catch {
listed = true; listed = true;
listReporters(reporter); listReporters(reporter);
} }
if ( config.listListeners() ) {
listed = true;
listListeners( reporter );
}
return listed; return listed;
} }

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