Compare commits

..

5 Commits

Author SHA1 Message Date
Martin Hořeňovský
73b5c7eed3 Fix priority 2019-07-19 20:57:40 +02:00
Martin Hořeňovský
48772027ea Fix check instead 2019-07-19 20:53:12 +02:00
Martin Hořeňovský
e96dc2d22d remove pointless check 2019-07-19 20:45:40 +02:00
Martin Hořeňovský
61a315b622 Try using Python 3 on Windows 2019-07-19 19:36:06 +02:00
Martin Hořeňovský
0e805512e5 Brute force casing 2019-07-19 13:29:16 +02:00
56 changed files with 398 additions and 1204 deletions

View File

@@ -276,7 +276,7 @@ matrix:
- "3.7"
dist: xenial
install:
- pip install conan conan-package-tools
- pip install conan==1.10.2 conan-package-tools
env:
- CONAN_GCC_VERSIONS=8
- CONAN_DOCKER_IMAGE=conanio/gcc8

View File

@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.9.2)
project(Catch2 LANGUAGES CXX VERSION 2.9.1)
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
@@ -42,8 +42,8 @@ if(USE_WMAIN)
endif()
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
find_package(PythonInterp)
if (NOT PYTHONINTERP_FOUND)
find_package(Python COMPONENTS Interpreter)
if (NOT Python_Interpreter_FOUND)
message(FATAL_ERROR "Python not found, but required for tests")
endif()
add_subdirectory(projects)

View File

@@ -5,11 +5,11 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/8YrGVqYqqSC4Sc5R)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/5icuqPwk9miJLAL1)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.9.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.9.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!

View File

@@ -51,11 +51,8 @@ string(REPLACE "\n" ";" output "${output}")
# Parse output
foreach(line ${output})
set(test ${line})
# Escape characters in test case names that would be parsed by Catch2
set(test_name ${test})
foreach(char , [ ])
string(REPLACE ${char} "\\${char}" test_name ${test_name})
endforeach(char)
# use escape commas to handle properly test cases with commans inside the name
string(REPLACE "," "\\," test_name ${test})
# ...and add to script
add_command(add_test
"${prefix}${test}${suffix}"

View File

@@ -136,7 +136,7 @@ REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" );
* **REQUIRE_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** and
* **CHECK_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)**
Expects that exception of _exception type_ is thrown and it matches provided matcher (see the [documentation for Matchers](matchers.md#top)).
Expects that exception of _exception type_ is thrown and it matches provided matcher (see next section for Matchers).
_Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function._

View File

@@ -1,8 +1,6 @@
<a id="top"></a>
# Authoring benchmarks
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
_Note that benchmarking support is disabled by default and to enable it,
you need to define `CATCH_CONFIG_ENABLE_BENCHMARKING`. For more details,
see the [compile-time configuration documentation](configuration.md#top)._

View File

@@ -277,8 +277,6 @@ either before running any tests, after running all tests - or both, depending on
## Specify the number of benchmark samples to collect
<pre>--benchmark-samples &lt;# of samples&gt;</pre>
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
When running benchmarks a number of "samples" is collected. This is the base data for later statistical analysis.
Per sample a clock resolution dependent number of iterations of the user code is run, which is independent of the number of samples. Defaults to 100.
@@ -286,8 +284,6 @@ Per sample a clock resolution dependent number of iterations of the user code is
## Specify the number of resamples for bootstrapping
<pre>--benchmark-resamples &lt;# of resamples&gt;</pre>
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
After the measurements are performed, statistical [bootstrapping] is performed
on the samples. The number of resamples for that bootstrapping is configurable
but defaults to 100000. Due to the bootstrapping it is possible to give
@@ -301,8 +297,6 @@ defaults to 95%).
## Specify the confidence-interval for bootstrapping
<pre>--benchmark-confidence-interval &lt;confidence-interval&gt;</pre>
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
The confidence-interval is used for statistical bootstrapping on the samples to
calculate the upper and lower bounds of mean and standard deviation.
Must be between 0 and 1 and defaults to 0.95.
@@ -311,8 +305,6 @@ Must be between 0 and 1 and defaults to 0.95.
## Disable statistical analysis of collected benchmark samples
<pre>--benchmark-no-analysis</pre>
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
When this flag is specified no bootstrapping or any other statistical analysis is performed.
Instead the user code is only measured and the plain mean from the samples is reported.

View File

@@ -127,12 +127,8 @@ Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
## C++17 toggles
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception
CATCH_CONFIG_CPP17_STRING_VIEW // Override std::string_view support detection(Catch provides a StringMaker specialization by default)
CATCH_CONFIG_CPP17_VARIANT // Override std::variant support detection (checked by CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER)
CATCH_CONFIG_CPP17_OPTIONAL // Override std::optional support detection (checked by CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER)
CATCH_CONFIG_CPP17_BYTE // Override std::byte support detection (Catch provides a StringMaker specialization by default)
> `CATCH_CONFIG_CPP17_STRING_VIEW` was [introduced](https://github.com/catchorg/Catch2/issues/1376) in Catch 2.4.1.
CATCH_CONFIG_CPP17_STRING_VIEW // Provide StringMaker specialization for std::string_view
CATCH_CONFIG_CPP17_VARIANT // Override C++17 detection for CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
Catch contains basic compiler/standard detection and attempts to use
some C++17 features whenever appropriate. This automatic detection
@@ -213,14 +209,9 @@ By default, Catch does not stringify some types from the standard library. This
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (on C++17)
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
> `CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER` was [introduced](https://github.com/catchorg/Catch2/issues/1380) in Catch 2.4.1.
> `CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER` was [introduced](https://github.com/catchorg/Catch2/issues/1510) in Catch 2.6.0.
## Disabling exceptions
> Introduced in Catch 2.4.0.
By default, Catch2 uses exceptions to signal errors and to abort tests
when an assertion from the `REQUIRE` family of assertions fails. We also
provide an experimental support for disabling exceptions. Catch2 should

View File

@@ -5,7 +5,6 @@
[Branches](#branches)<br>
[Directory structure](#directory-structure)<br>
[Testing your changes](#testing-your-changes)<br>
[Documenting your code](#documenting-your-code)<br>
[Code constructs to watch out for](#code-constructs-to-watch-out-for)<br>
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
@@ -82,59 +81,6 @@ before you do so, you need to check that the introduced changes are indeed
intentional.
## Documenting your code
If you have added new feature to Catch2, it needs documentation, so that
other people can use it as well. This section collects some technical
information that you will need for updating Catch2's documentation, and
possibly some generic advise as well.
First, the technicalities:
* We introduced version tags to the documentation, which show users in
which version a specific feature was introduced. This means that newly
written documentation should be tagged with a placeholder, that will
be replaced with the actual version upon release. There are 2 styles
of placeholders used through the documentation, you should pick one that
fits your text better (if in doubt, take a look at the existing version
tags for other features).
* `> [Introduced](link-to-issue-or-PR) in Catch X.Y.Z` - this
placeholder is usually used after a section heading
* `> X (Y and Z) was [introduced](link-to-issue-or-PR) in Catch X.Y.Z`
- this placeholder is used when you need to tag a subpart of something,
e.g. list
* Crosslinks to different pages should target the `top` anchor, like this
`[link to contributing](contributing.md#top)`.
* If you have introduced a new document, there is a simple template you
should use. It provides you with the top anchor mentioned above, and also
with a backlink to the top of the documentation:
```markdown
<a id="top"></a>
# Cool feature
Text that explains how to use the cool feature.
---
[Home](Readme.md#top)
```
* For pages with more than 4 subheadings, we provide a table of contents
(ToC) at the top of the page. Because GitHub markdown does not support
automatic generation of ToC, it has to be handled semi-manually. Thus,
if you've added a new subheading to some page, you should add it to the
ToC. This can be done either manually, or by running the
`updateDocumentToC.py` script in the `scripts/` folder.
Now, for the generic tips:
* Usage examples are good
* Don't be afraid to introduce new pages
* Try to be reasonably consistent with the surrounding documentation
## Code constructs to watch out for
This section is a (sadly incomplete) listing of various constructs that

View File

@@ -1,8 +1,6 @@
<a id="top"></a>
# Data Generators
> Introduced in Catch 2.6.0.
Data generators (also known as _data driven/parametrized test cases_)
let you reuse the same set of assertions across different input values.
In Catch2, this means that they respect the ordering and nesting
@@ -51,8 +49,6 @@ a test case,
* `RandomFloatGenerator<Float>` -- generates random Floats from range
* `RangeGenerator<T>` -- generates all values inside a specific range
> `ChunkGenerator<T>`, `RandomIntegerGenerator<Integral>`, `RandomFloatGenerator<Float>` and `RangeGenerator<T>` were introduced in Catch 2.7.0.
The generators also have associated helper functions that infer their
type, making their usage much nicer. These are
@@ -68,7 +64,6 @@ type, making their usage much nicer. These are
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
> `chunk()`, `random()` and both `range()` functions were introduced in Catch 2.7.0.
And can be used as shown in the example below to create a generator
that returns 100 odd random number:
@@ -101,8 +96,6 @@ scope and thus capturing references is dangerous. If you need to use
variables inside the generator expression, make sure you thought through
the lifetime implications and use `GENERATE_COPY` or `GENERATE_REF`.**
> `GENERATE_COPY` and `GENERATE_REF` were introduced in Catch 2.7.1.
You can also override the inferred type by using `as<type>` as the first
argument to the macro. This can be useful when dealing with string literals,
if you want them to come out as `std::string`:

View File

@@ -30,8 +30,6 @@ When the last `CHECK` fails in the "Bar" test case, then only one message will b
## Logging without local scope
> [Introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch 2.7.0.
`UNSCOPED_INFO` is similar to `INFO` with two key differences:
- Lifetime of an unscoped message is not tied to its own scope.
@@ -106,8 +104,6 @@ This semicolon will be removed with next major version. It is highly advised to
**UNSCOPED_INFO(** _message expression_ **)**
> [Introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch 2.7.0.
Similar to `INFO`, but messages are not limited to their own scope: They are removed from the buffer after each assertion, section or test case, whichever comes first.
**WARN(** _message expression_ **)**

View File

@@ -45,16 +45,7 @@ Each of the provided `std::string` matchers also takes an optional second argume
### Vector matchers
Catch2 currently provides 5 built-in matchers that work on `std::vector`.
These are
* `Contains` which checks whether a specified vector is present in the result
* `VectorContains` which checks whether a specified element is present in the result
* `Equals` which checks whether the result is exactly equal (order matters) to a specific vector
* `UnorderedEquals` which checks whether the result is equal to a specific vector under a permutation
* `Approx` which checks whether the result is "approx-equal" (order matters, but comparison is done via `Approx`) to a specific vector
> Approx matcher was [introduced](https://github.com/catchorg/Catch2/issues/1499) in Catch 2.7.2.
The vector matchers are `Contains`, `VectorContains` and `Equals`. `VectorContains` looks for a single element in the matched vector, `Contains` looks for a set (vector) of elements inside the matched vector.
### Floating point matchers
The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts floating point numbers that are within a certain margin of target. `WithinULP` performs an [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place)-based comparison of two floating point numbers and accepts them if they are less than certain number of ULPs apart.

View File

@@ -112,9 +112,6 @@ SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gr
### [Standardese](https://github.com/foonathan/standardese)
Standardese aims to be a nextgen Doxygen.
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
A 2D, Zombie, RPG game which is being made on our own engine.
---
[Home](Readme.md#top)

View File

@@ -59,8 +59,6 @@ TEST_CASE( "SUCCEED showcase" ) {
* `STATIC_REQUIRE`
> [Introduced](https://github.com/catchorg/Catch2/issues/1362) in Catch 2.4.2.
`STATIC_REQUIRE( expr )` is a macro that can be used the same way as a
`static_assert`, but also registers the success with Catch2, so it is
reported as a success at runtime. The whole check can also be deferred
@@ -134,8 +132,6 @@ ANON_TEST_CASE() {
* `DYNAMIC_SECTION`
> Introduced in Catch 2.3.0.
`DYNAMIC_SECTION` is a `SECTION` where the user can use `operator<<` to
create the final name for that section. This can be useful with e.g.
generators, or when creating a `SECTION` dynamically, within a loop.

View File

@@ -2,7 +2,6 @@
# Release notes
**Contents**<br>
[2.9.2](#292)<br>
[2.9.1](#291)<br>
[2.9.0](#290)<br>
[2.8.0](#280)<br>
@@ -27,42 +26,6 @@
[Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br>
## 2.9.2
### Fixes
* `ChunkGenerator` can now be used with chunks of size 0 (#1671)
* Nested subsections are now run properly when specific section is run via the `-c` argument (#1670, #1673)
* Catch2 now consistently uses `_WIN32` to detect Windows platform (#1676)
* `TEMPLATE_LIST_TEST_CASE` now support non-default constructible type lists (#1697)
* Fixed a crash in the XMLReporter when a benchmark throws exception during warmup (#1706)
* Fixed a possible infinite loop in CompactReporter (#1715)
* Fixed `-w NoTests` returning 0 even when no tests were matched (#1449, #1683, #1684)
* Fixed matcher compilation under Obj-C++ (#1661)
### Improvements
* `RepeatGenerator` and `FixedValuesGenerator` now fail to compile when used with `bool` (#1692)
* Previously they would fail at runtime.
* Catch2 now supports Android's debug logging for its debug output (#1710)
* Catch2 now detects and configures itself for the RTX platform (#1693)
* You still need to pass `--benchmark-no-analysis` if you are using benchmarking under RTX
* Removed a "storage class is not first" warning when compiling Catch2 with PGI compiler (#1717)
### Miscellaneous
* Documentation now contains indication when a specific feature was introduced (#1695)
* These start with Catch2 v2.3.0, (a bit over a year ago).
* `docs/contributing.md` has been updated to provide contributors guidance on how to add these to newly written documentation
* Various other documentation improvements
* ToC fixes
* Documented `--order` and `--rng-seed` command line options
* Benchmarking documentation now clearly states that it requires opt-in
* Documented `CATCH_CONFIG_CPP17_OPTIONAL` and `CATCH_CONFIG_CPP17_BYTE` macros
* Properly documented built-in vector matchers
* Improved `*_THROWS_MATCHES` documentation a bit
* CMake config file is now arch-independent even if `CMAKE_SIZEOF_VOID_P` is in CMake cache (#1660)
* `CatchAddTests` now properly escapes `[` and `]` in test names (#1634, #1698)
## 2.9.1
### Fixes
@@ -125,7 +88,7 @@
### Improvements
* Reporters now print out the filters applied to test cases (#1550, #1585)
* Added `GENERATE_COPY` and `GENERATE_REF` macros that can use variables inside the generator expression
* Added `GENERATE_COPY` and `GENERATE_VAR` macros that can use variables inside the generator expression
* Because of the significant danger of lifetime issues, the default `GENERATE` macro still does not allow variables
* The `map` generator helper now deduces the mapped return type (#1576)

View File

@@ -84,13 +84,10 @@ This macro maps onto ```TEST_CASE``` and works in the same way, except that the
These macros map onto ```SECTION```s except that the section names are the _something_s prefixed by "given: ", "when: " or "then: " respectively.
* **AND_GIVEN(** _something_ **)**
* **AND_WHEN(** _something_ **)**
* **AND_THEN(** _something_ **)**
Similar to ```GIVEN```, ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```GIVEN```s, ```WHEN```s and ```THEN```s together.
> `AND_GIVEN` was [introduced](https://github.com/catchorg/Catch2/issues/1360) in Catch 2.4.0.
Similar to ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```WHEN```s and ```THEN```s together.
When any of these macros are used the console reporter recognises them and formats the test case header such that the Givens, Whens and Thens are aligned to aid readability.
@@ -104,8 +101,6 @@ by types, in the form of `TEMPLATE_TEST_CASE`,
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
> [Introduced](https://github.com/catchorg/Catch2/issues/1437) in Catch 2.5.0.
_test name_ and _tag_ are exactly the same as they are in `TEST_CASE`,
with the difference that the tag string must be provided (however, it
can be empty). _type1_ through _typen_ is the list of types for which
@@ -156,8 +151,6 @@ TEMPLATE_TEST_CASE( "vectors can be sized and resized", "[vector][template]", in
* **TEMPLATE_PRODUCT_TEST_CASE(** _test name_ , _tags_, (_template-type1_, _template-type2_, ..., _template-typen_), (_template-arg1_, _template-arg2_, ..., _template-argm_) **)**
> [Introduced](https://github.com/catchorg/Catch2/issues/1468) in Catch 2.6.0.
_template-type1_ through _template-typen_ is list of template template
types which should be combined with each of _template-arg1_ through
_template-argm_, resulting in _n * m_ test cases. Inside the test case,
@@ -201,8 +194,6 @@ is very high and should not be encountered in practice._
* **TEMPLATE_LIST_TEST_CASE(** _test name_, _tags_, _type list_ **)**
> [Introduced](https://github.com/catchorg/Catch2/issues/1627) in Catch 2.9.0.
_type list_ is a generic list of types on which test case should be instantiated.
List can be `std::tuple`, `boost::mpl::list`, `boost::mp11::mp_list` or anything with
`template <typename...>` signature.
@@ -221,8 +212,6 @@ TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside std
## Signature based parametrised test cases
> [Introduced](https://github.com/catchorg/Catch2/issues/1609) in Catch 2.8.0.
In addition to [type parametrised test cases](#type-parametrised-test-cases) Catch2 also supports
signature base parametrised test cases, in form of `TEMPLATE_TEST_CASE_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_SIG`.
These test cases have similar syntax like [type parametrised test cases](#type-parametrised-test-cases), with one

View File

@@ -1,8 +1,6 @@
<a id="top"></a>
# Test fixtures
## Defining test fixtures
Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
```c++
@@ -86,9 +84,6 @@ _While there is an upper limit on the number of types you can specify
in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
the limit is very high and should not be encountered in practice._
## Signature-based parametrised test fixtures
> [Introduced](https://github.com/catchorg/Catch2/issues/1609) in Catch 2.8.0.
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG` to support
fixtures using non-type template parameters. These test cases work similar to `TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
@@ -105,13 +100,6 @@ TEMPLATE_TEST_CASE_METHOD_SIG(Nttp_Fixture, "A TEMPLATE_TEST_CASE_METHOD_SIG bas
REQUIRE(Nttp_Fixture<V>::value > 0);
}
template<typename T>
struct Template_Fixture_2 {
Template_Fixture_2() {}
T m_a;
};
template< typename T, size_t V>
struct Template_Foo_2 {
size_t size() { return V; }
@@ -123,8 +111,6 @@ TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(Template_Fixture_2, "A TEMPLATE_PRODUCT_TE
}
```
## Template fixtures with types specified in template type lists
Catch2 also provides `TEMPLATE_LIST_TEST_CASE_METHOD` to support template fixtures with types specified in
template type lists like `std::tuple`, `boost::mpl::list` or `boost::mp11::mp_list`. This test case works the same as `TEMPLATE_TEST_CASE_METHOD`,
only difference is the source of types. This allows you to reuse the template type list in multiple test cases.

View File

@@ -71,8 +71,6 @@ CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
## Enums
> Introduced in Catch 2.8.0.
Enums that already have a `<<` overload for `std::ostream` will convert to strings as expected.
If you only need to convert enums to strings for test reporting purposes you can provide a `StringMaker` specialisations as any other type.
However, as a convenience, Catch provides the `REGISTER_ENUM` helper macro that will generate the `StringMaker` specialiation for you with minimal code.
@@ -110,8 +108,6 @@ TEST_CASE() {
## Floating point precision
> [Introduced](https://github.com/catchorg/Catch2/issues/1614) in Catch 2.8.0.
Catch provides a built-in `StringMaker` specialization for both `float`
and `double`. By default, it uses what we think is a reasonable precision,
but you can customize it by modifying the `precision` static variable

View File

@@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 9
#define CATCH_VERSION_PATCH 2
#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header

View File

@@ -184,18 +184,6 @@
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
////////////////////////////////////////////////////////////////////////////////
// RTX is a special version of Windows that is real time.
// This means that it is detected as Windows, but does not provide
// the same set of capabilities as real Windows does.
#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
#define CATCH_INTERNAL_CONFIG_NO_ASYNC
#define CATCH_CONFIG_COLOUR_NONE
#endif
////////////////////////////////////////////////////////////////////////////////
// Check if string_view is available and usable
// The check is split apart to work around v140 (VS2015) preprocessor issue...
@@ -297,7 +285,7 @@
# define CATCH_CONFIG_POLYFILL_ISNAN
#endif
#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
# define CATCH_CONFIG_USE_ASYNC
#endif

View File

@@ -11,16 +11,7 @@
#include "catch_platform.h"
#include "catch_windows_h_proxy.h"
#if defined(__ANDROID__)
#include <android/log.h>
namespace Catch {
void writeToDebugConsole( std::string const& text ) {
__android_log_print( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
}
}
#elif defined(CATCH_PLATFORM_WINDOWS)
#ifdef CATCH_PLATFORM_WINDOWS
namespace Catch {
void writeToDebugConsole( std::string const& text ) {

View File

@@ -97,7 +97,7 @@ namespace Catch {
// 32kb for the alternate stack seems to be sufficient. However, this value
// is experimentally determined, so that's not guaranteed.
static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
static SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },

View File

@@ -28,7 +28,6 @@ namespace Catch {
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
};
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );

View File

@@ -84,18 +84,9 @@ namespace Catch {
}
std::string TagInfo::all() const {
size_t size = 0;
for (auto const& spelling : spellings) {
// Add 2 for the brackes
size += spelling.size() + 2;
}
std::string out; out.reserve(size);
for (auto const& spelling : spellings) {
out += '[';
out += spelling;
out += ']';
}
std::string out;
for( auto const& spelling : spellings )
out += "[" + spelling + "]";
return out;
}

View File

@@ -44,15 +44,6 @@ namespace Matchers {
virtual bool match( ObjectT const& arg ) const = 0;
};
#if defined(__OBJC__)
// Hack to fix Catch GH issue #1661. Could use id for generic Object support.
// use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
template<>
struct MatcherMethod<NSString*> {
virtual bool match( NSString* arg ) const = 0;
};
#endif
#ifdef __clang__
# pragma clang diagnostic pop
#endif

View File

@@ -116,7 +116,7 @@ namespace Catch {
arcSafeRelease( m_substr );
}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return false;
}
@@ -126,7 +126,7 @@ namespace Catch {
struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr];
}
@@ -139,7 +139,7 @@ namespace Catch {
struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound;
}
@@ -152,7 +152,7 @@ namespace Catch {
struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0;
}
@@ -164,7 +164,7 @@ namespace Catch {
struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
}

View File

@@ -25,8 +25,6 @@
#include <cstdlib>
#include <iomanip>
#include <set>
#include <iterator>
namespace Catch {
@@ -60,53 +58,46 @@ namespace Catch {
return ret;
}
class TestGroup {
public:
explicit TestGroup(std::shared_ptr<Config> const& config)
: m_config{config}
, m_context{config, makeReporter(config)}
{
auto const& allTestCases = getAllTestCasesSorted(*m_config);
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
if (m_matches.empty()) {
for (auto const& test : allTestCases)
if (!test.isHidden())
m_tests.emplace(&test);
} else {
for (auto const& match : m_matches)
m_tests.insert(match.tests.begin(), match.tests.end());
}
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
auto reporter = makeReporter(config);
RunContext context(config, std::move(reporter));
Totals totals;
context.testGroupStarting(config->name(), 1, 1);
TestSpec testSpec = config->testSpec();
auto const& allTestCases = getAllTestCasesSorted(*config);
for (auto const& testCase : allTestCases) {
bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
(testSpec.hasFilters() && matchTest(testCase, testSpec, *config));
if (!context.aborting() && matching)
totals += context.runTest(testCase);
else
context.reporter().skipTest(testCase);
}
Totals execute() {
Totals totals;
m_context.testGroupStarting(m_config->name(), 1, 1);
for (auto const& testCase : m_tests) {
if (!m_context.aborting())
totals += m_context.runTest(*testCase);
else
m_context.reporter().skipTest(*testCase);
if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
ReusableStringStream testConfig;
bool first = true;
for (const auto& input : config->getTestsOrTags()) {
if (!first) { testConfig << ' '; }
first = false;
testConfig << input;
}
for (auto const& match : m_matches) {
if (match.tests.empty()) {
m_context.reporter().noMatchingTestCases(match.name);
totals.error = -1;
}
}
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
return totals;
context.reporter().noMatchingTestCases(testConfig.str());
totals.error = -1;
}
private:
using Tests = std::set<TestCase const*>;
std::shared_ptr<Config> m_config;
RunContext m_context;
Tests m_tests;
TestSpec::Matches m_matches;
};
context.testGroupEnded(config->name(), totals, 1, 1);
return totals;
}
void applyFilenamesAsTags(Catch::IConfig const& config) {
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
@@ -283,12 +274,7 @@ namespace Catch {
if( Option<std::size_t> listed = list( m_config ) )
return static_cast<int>( *listed );
TestGroup tests { m_config };
auto const totals = tests.execute();
if( m_config->warnAboutNoTests() && totals.error == -1 )
return 2;
auto totals = runTests( m_config );
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed

View File

@@ -36,13 +36,8 @@ namespace Catch {
}
return sorted;
}
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
return !testCase.throws() || config.allowThrows();
}
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
return testSpec.matches( testCase ) && isThrowSafe( testCase, config );
return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
}
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {

View File

@@ -23,8 +23,6 @@ namespace Catch {
struct IConfig;
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );

View File

@@ -247,7 +247,7 @@ struct AutoReg : NonCopyable {
} \
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
using TestInit = decltype(convert<TestName>(std::declval<TmplList>())); \
using TestInit = decltype(convert<TestName>(TmplList {})); \
TestInit t; \
t.reg_tests(); \
return 0; \
@@ -374,7 +374,7 @@ struct AutoReg : NonCopyable {
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
using TestInit = decltype(convert<TestNameClass>(std::declval<TmplList>()));\
using TestInit = decltype(convert<TestNameClass>(TmplList {}));\
TestInit t;\
t.reg_tests();\
return 0;\

View File

@@ -7,7 +7,6 @@
#include "catch_test_spec.h"
#include "catch_string_manip.h"
#include "catch_interfaces_config.h"
#include <algorithm>
#include <string>
@@ -16,80 +15,45 @@
namespace Catch {
TestSpec::Pattern::Pattern( std::string const& name )
: m_name( name )
{}
TestSpec::Pattern::~Pattern() = default;
TestSpec::NamePattern::~NamePattern() = default;
TestSpec::TagPattern::~TagPattern() = default;
TestSpec::ExcludedPattern::~ExcludedPattern() = default;
std::string const& TestSpec::Pattern::name() const {
return m_name;
}
TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
: Pattern( filterString )
, m_wildcardPattern( toLower( name ), CaseSensitive::No )
TestSpec::NamePattern::NamePattern( std::string const& name )
: m_wildcardPattern( toLower( name ), CaseSensitive::No )
{}
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
return m_wildcardPattern.matches( toLower( testCase.name ) );
}
TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
: Pattern( filterString )
, m_tag( toLower( tag ) )
{}
TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
return std::find(begin(testCase.lcaseTags),
end(testCase.lcaseTags),
m_tag) != end(testCase.lcaseTags);
}
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern )
: Pattern( underlyingPattern->name() )
, m_underlyingPattern( underlyingPattern )
{}
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const {
return !m_underlyingPattern->matches( testCase );
}
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } );
// All patterns in a filter must match for the filter to be a match
for( auto const& pattern : m_patterns ) {
if( !pattern->matches( testCase ) )
return false;
}
return true;
}
std::string TestSpec::Filter::name() const {
std::string name;
for( auto const& p : m_patterns )
name += p->name();
return name;
}
bool TestSpec::hasFilters() const {
return !m_filters.empty();
}
bool TestSpec::matches( TestCaseInfo const& testCase ) const {
return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
// A TestSpec matches if any filter matches
for( auto const& filter : m_filters )
if( filter.matches( testCase ) )
return true;
return false;
}
TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
{
Matches matches( m_filters.size() );
std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
std::vector<TestCase const*> currentMatches;
for( auto const& test : testCases )
if( isThrowSafe( test, config ) && filter.matches( test ) )
currentMatches.emplace_back( &test );
return FilterMatch{ filter.name(), currentMatches };
} );
return matches;
}
}

View File

@@ -22,23 +22,17 @@
namespace Catch {
struct IConfig;
class TestSpec {
class Pattern {
public:
explicit Pattern( std::string const& name );
struct Pattern {
virtual ~Pattern();
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
std::string const& name() const;
private:
std::string const m_name;
};
using PatternPtr = std::shared_ptr<Pattern>;
class NamePattern : public Pattern {
public:
explicit NamePattern( std::string const& name, std::string const& filterString );
NamePattern( std::string const& name );
virtual ~NamePattern();
bool matches( TestCaseInfo const& testCase ) const override;
private:
WildcardPattern m_wildcardPattern;
@@ -46,7 +40,8 @@ namespace Catch {
class TagPattern : public Pattern {
public:
explicit TagPattern( std::string const& tag, std::string const& filterString );
TagPattern( std::string const& tag );
virtual ~TagPattern();
bool matches( TestCaseInfo const& testCase ) const override;
private:
std::string m_tag;
@@ -54,7 +49,8 @@ namespace Catch {
class ExcludedPattern : public Pattern {
public:
explicit ExcludedPattern( PatternPtr const& underlyingPattern );
ExcludedPattern( PatternPtr const& underlyingPattern );
virtual ~ExcludedPattern();
bool matches( TestCaseInfo const& testCase ) const override;
private:
PatternPtr m_underlyingPattern;
@@ -64,19 +60,11 @@ namespace Catch {
std::vector<PatternPtr> m_patterns;
bool matches( TestCaseInfo const& testCase ) const;
std::string name() const;
};
public:
struct FilterMatch {
std::string name;
std::vector<TestCase const*> tests;
};
using Matches = std::vector<FilterMatch>;
bool hasFilters() const;
bool matches( TestCaseInfo const& testCase ) const;
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
private:
std::vector<Filter> m_filters;

View File

@@ -14,125 +14,64 @@ namespace Catch {
TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
m_mode = None;
m_exclusion = false;
m_start = std::string::npos;
m_arg = m_tagAliases->expandAliases( arg );
m_escapeChars.clear();
m_substring.reserve(m_arg.size());
m_patternName.reserve(m_arg.size());
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
visitChar( m_arg[m_pos] );
endMode();
if( m_mode == Name )
addPattern<TestSpec::NamePattern>();
return *this;
}
TestSpec TestSpecParser::testSpec() {
addFilter();
return m_testSpec;
}
void TestSpecParser::visitChar( char c ) {
if( c == ',' ) {
endMode();
addFilter();
return;
if( m_mode == None ) {
switch( c ) {
case ' ': return;
case '~': m_exclusion = true; return;
case '[': return startNewMode( Tag, ++m_pos );
case '"': return startNewMode( QuotedName, ++m_pos );
case '\\': return escape();
default: startNewMode( Name, m_pos ); break;
}
}
switch( m_mode ) {
case None:
if( processNoneChar( c ) )
return;
break;
case Name:
processNameChar( c );
break;
case EscapedName:
endMode();
break;
default:
case Tag:
case QuotedName:
if( processOtherChar( c ) )
return;
break;
if( m_mode == Name ) {
if( c == ',' ) {
addPattern<TestSpec::NamePattern>();
addFilter();
}
else if( c == '[' ) {
if( subString() == "exclude:" )
m_exclusion = true;
else
addPattern<TestSpec::NamePattern>();
startNewMode( Tag, ++m_pos );
}
else if( c == '\\' )
escape();
}
m_substring += c;
if( !isControlChar( c ) )
m_patternName += c;
else if( m_mode == EscapedName )
m_mode = Name;
else if( m_mode == QuotedName && c == '"' )
addPattern<TestSpec::NamePattern>();
else if( m_mode == Tag && c == ']' )
addPattern<TestSpec::TagPattern>();
}
// Two of the processing methods return true to signal the caller to return
// without adding the given character to the current pattern strings
bool TestSpecParser::processNoneChar( char c ) {
switch( c ) {
case ' ':
return true;
case '~':
m_exclusion = true;
return false;
case '[':
startNewMode( Tag );
return false;
case '"':
startNewMode( QuotedName );
return false;
case '\\':
escape();
return true;
default:
startNewMode( Name );
return false;
}
}
void TestSpecParser::processNameChar( char c ) {
if( c == '[' ) {
if( m_substring == "exclude:" )
m_exclusion = true;
else
endMode();
startNewMode( Tag );
}
}
bool TestSpecParser::processOtherChar( char c ) {
if( !isControlChar( c ) )
return false;
m_substring += c;
endMode();
return true;
}
void TestSpecParser::startNewMode( Mode mode ) {
void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
m_mode = mode;
}
void TestSpecParser::endMode() {
switch( m_mode ) {
case Name:
case QuotedName:
return addPattern<TestSpec::NamePattern>();
case Tag:
return addPattern<TestSpec::TagPattern>();
case EscapedName:
return startNewMode( Name );
case None:
default:
return startNewMode( None );
}
m_start = start;
}
void TestSpecParser::escape() {
if( m_mode == None )
m_start = m_pos;
m_mode = EscapedName;
m_escapeChars.push_back( m_pos );
}
bool TestSpecParser::isControlChar( char c ) const {
switch( m_mode ) {
default:
return false;
case None:
return c == '~';
case Name:
return c == '[';
case EscapedName:
return true;
case QuotedName:
return c == '"';
case Tag:
return c == '[' || c == ']';
}
}
std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
void TestSpecParser::addFilter() {
if( !m_currentFilter.m_patterns.empty() ) {

View File

@@ -23,10 +23,8 @@ namespace Catch {
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Mode m_mode = None;
bool m_exclusion = false;
std::size_t m_pos = 0;
std::size_t m_start = std::string::npos, m_pos = 0;
std::string m_arg;
std::string m_substring;
std::string m_patternName;
std::vector<std::size_t> m_escapeChars;
TestSpec::Filter m_currentFilter;
TestSpec m_testSpec;
@@ -40,32 +38,26 @@ namespace Catch {
private:
void visitChar( char c );
void startNewMode( Mode mode );
bool processNoneChar( char c );
void processNameChar( char c );
bool processOtherChar( char c );
void endMode();
void startNewMode( Mode mode, std::size_t start );
void escape();
bool isControlChar( char c ) const;
std::string subString() const;
template<typename T>
void addPattern() {
std::string token = m_patternName;
std::string token = subString();
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
token = token.substr( 8 );
}
if( !token.empty() ) {
TestSpec::PatternPtr pattern = std::make_shared<T>( token, m_substring );
TestSpec::PatternPtr pattern = std::make_shared<T>( token );
if( m_exclusion )
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
m_currentFilter.m_patterns.push_back( pattern );
}
m_substring.clear();
m_patternName.clear();
m_exclusion = false;
m_mode = None;
}

View File

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

View File

@@ -209,25 +209,24 @@ private:
if (itMessage == messages.end())
return;
const auto itEnd = messages.cend();
const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
// using messages.end() directly yields (or auto) compilation error:
std::vector<MessageInfo>::const_iterator itEnd = messages.end();
const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
{
Colour colourGuard(colour);
stream << " with " << pluralise(N, "message") << ':';
}
while (itMessage != itEnd) {
for (; itMessage != itEnd; ) {
// If this assertion is a warning ignore any INFO messages
if (printInfoMessages || itMessage->type != ResultWas::Info) {
printMessage();
if (itMessage != itEnd) {
stream << " '" << itMessage->message << '\'';
if (++itMessage != itEnd) {
Colour colourGuard(dimColour());
stream << " and";
}
continue;
}
++itMessage;
}
}

View File

@@ -220,13 +220,10 @@ namespace Catch {
}
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void XmlReporter::benchmarkPreparing(std::string const& name) {
m_xml.startElement("BenchmarkResults")
.writeAttribute("name", name);
}
void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
m_xml.writeAttribute("samples", info.samples)
m_xml.startElement("BenchmarkResults")
.writeAttribute("name", info.name)
.writeAttribute("samples", info.samples)
.writeAttribute("resamples", info.resamples)
.writeAttribute("iterations", info.iterations)
.writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution))

View File

@@ -51,7 +51,6 @@ namespace Catch {
void testRunEnded(TestRunStats const& testRunStats) override;
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void benchmarkPreparing(std::string const& name) override;
void benchmarkStarting(BenchmarkInfo const&) override;
void benchmarkEnded(BenchmarkStats<> const&) override;
void benchmarkFailed(std::string const&) override;

View File

@@ -4,6 +4,6 @@ import glob
import subprocess
if __name__ == '__main__':
cov_files = list(glob.glob('projects/cov-report*.bin'))
cov_files = list(glob.glob('cov-report*.bin'))
base_cmd = ['OpenCppCoverage', '--quiet', '--export_type=cobertura:cobertura.xml'] + ['--input_coverage={}'.format(f) for f in cov_files]
subprocess.check_call(base_cmd)
subprocess.call(base_cmd)

View File

@@ -89,30 +89,27 @@ std::string windowsify_path(std::string path) {
return path;
}
int exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
std::array<char, 128> buffer;
#if defined(_WIN32)
// cmd has already been escaped outside this function.
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
+ ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
auto pipe = _popen(real_cmd.c_str(), "r");
std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
#else // Just for testing, in the real world we will always work under WIN32
(void)log_num; (void)path;
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
#endif
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (!feof(pipe)) {
if (fgets(buffer.data(), 128, pipe) != nullptr) {
while (!feof(pipe.get())) {
if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
std::cout << buffer.data();
}
}
auto ret = _pclose(pipe);
if (ret == -1) {
throw std::runtime_error("underlying error in pclose()");
}
return ret;
}
// argv should be:

View File

@@ -393,19 +393,8 @@ set_tests_properties(ListTestNamesOnly PROPERTIES
add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> Tracker, "___nonexistent_test___")
set_tests_properties(NoTest PROPERTIES
PASS_REGULAR_EXPRESSION "No test cases matched '___nonexistent_test___'"
FAIL_REGULAR_EXPRESSION "No tests ran"
)
add_test(NAME WarnAboutNoTests COMMAND ${CMAKE_COMMAND} -P ${CATCH_DIR}/projects/SelfTest/WarnAboutNoTests.cmake $<TARGET_FILE:SelfTest>)
add_test(NAME UnmatchedOutputFilter COMMAND $<TARGET_FILE:SelfTest> [this-tag-does-not-exist] -w NoTests)
set_tests_properties(UnmatchedOutputFilter
PROPERTIES
PASS_REGULAR_EXPRESSION "No test cases matched '\\[this-tag-does-not-exist\\]'"
)
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
@@ -413,16 +402,12 @@ add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
add_test(NAME ApprovalTests COMMAND ${Python_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
add_test(NAME RegressionCheck-1670 COMMAND $<TARGET_FILE:SelfTest> "#1670 regression check" -c A -r compact)
set_tests_properties(RegressionCheck-1670 PROPERTIES PASS_REGULAR_EXPRESSION "Passed 1 test case with 2 assertions.")
add_test(NAME VersionCheck COMMAND $<TARGET_FILE:SelfTest> -h)
set_tests_properties(VersionCheck PROPERTIES PASS_REGULAR_EXPRESSION "Catch v${PROJECT_VERSION}")
if (CATCH_USE_VALGRIND)
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)

View File

@@ -3,8 +3,6 @@ Decomposition.tests.cpp:<line number>: passed: fptr == 0 for: 0 == 0
Decomposition.tests.cpp:<line number>: passed: fptr == 0l for: 0 == 0
Compilation.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
Compilation.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
Compilation.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
Compilation.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
Compilation.tests.cpp:<line number>: passed: t1 == t2 for: {?} == {?}
Compilation.tests.cpp:<line number>: passed: t1 != t2 for: {?} != {?}
Compilation.tests.cpp:<line number>: passed: t1 < t2 for: {?} < {?}
@@ -246,6 +244,8 @@ Tricky.tests.cpp:<line number>: passed: true
Approx.tests.cpp:<line number>: passed: INFINITY == Approx(INFINITY) for: inff == Approx( inf )
Approx.tests.cpp:<line number>: passed: NAN != Approx(NAN) for: nanf != Approx( nan )
Approx.tests.cpp:<line number>: passed: !(NAN == Approx(NAN)) for: !(nanf == Approx( nan ))
Tricky.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
Tricky.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
Message.tests.cpp:<line number>: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
Message.tests.cpp:<line number>: passed: with 7 messages: 'std::vector<int>{1, 2, 3}[0, 1, 2] := 3' and 'std::vector<int>{1, 2, 3}[(0, 1)] := 2' and 'std::vector<int>{1, 2, 3}[0] := 1' and '(helper_1436<int, int>{12, -12}) := { 12, -12 }' and '(helper_1436<int, int>(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3'
Message.tests.cpp:<line number>: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{''
@@ -1084,9 +1084,6 @@ Tag.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end",
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 1
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0

View File

@@ -1380,6 +1380,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 298 | 224 passed | 70 failed | 4 failed as expected
assertions: 1553 | 1401 passed | 131 failed | 21 failed as expected
test cases: 295 | 221 passed | 70 failed | 4 failed as expected
assertions: 1550 | 1398 passed | 131 failed | 21 failed as expected

View File

@@ -39,22 +39,6 @@ with expansion:
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( y.v == 0 )
with expansion:
0 == 0
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( 0 == y.v )
with expansion:
0 == 0
-------------------------------------------------------------------------------
#1027: Bitfields can be captured
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( y.v == 0 )
with expansion:
@@ -1960,6 +1944,22 @@ Approx.tests.cpp:<line number>: PASSED:
with expansion:
!(nanf == Approx( nan ))
-------------------------------------------------------------------------------
Bitfields can be captured (#1027)
-------------------------------------------------------------------------------
Tricky.tests.cpp:<line number>
...............................................................................
Tricky.tests.cpp:<line number>: PASSED:
REQUIRE( y.v == 0 )
with expansion:
0 == 0
Tricky.tests.cpp:<line number>: PASSED:
REQUIRE( 0 == y.v )
with expansion:
0 == 0
-------------------------------------------------------------------------------
CAPTURE can deal with complex expressions
-------------------------------------------------------------------------------
@@ -8022,42 +8022,6 @@ Class.tests.cpp:<line number>: PASSED:
with expansion:
1.0 == 1
-------------------------------------------------------------------------------
Template test case with test types specified inside non-default-constructible
std::tuple - MyNonDefaultConstructibleTypes - 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
REQUIRE( sizeof(TestType) > 0 )
with expansion:
1 > 0
-------------------------------------------------------------------------------
Template test case with test types specified inside non-default-constructible
std::tuple - MyNonDefaultConstructibleTypes - 1
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
REQUIRE( sizeof(TestType) > 0 )
with expansion:
1 > 0
-------------------------------------------------------------------------------
Template test case with test types specified inside non-default-constructible
std::tuple - MyNonDefaultConstructibleTypes - 2
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
REQUIRE( sizeof(TestType) > 0 )
with expansion:
4 > 0
-------------------------------------------------------------------------------
Template test case with test types specified inside std::tuple - MyTypes - 0
-------------------------------------------------------------------------------
@@ -12409,6 +12373,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 298 | 208 passed | 86 failed | 4 failed as expected
assertions: 1570 | 1401 passed | 148 failed | 21 failed as expected
test cases: 295 | 205 passed | 86 failed | 4 failed as expected
assertions: 1567 | 1398 passed | 148 failed | 21 failed as expected

View File

@@ -39,22 +39,6 @@ with expansion:
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( y.v == 0 )
with expansion:
0 == 0
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( 0 == y.v )
with expansion:
0 == 0
-------------------------------------------------------------------------------
#1027: Bitfields can be captured
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( y.v == 0 )
with expansion:
@@ -368,6 +352,6 @@ Condition.tests.cpp:<line number>: FAILED:
CHECK( true != true )
===============================================================================
test cases: 19 | 14 passed | 3 failed | 2 failed as expected
assertions: 42 | 35 passed | 4 failed | 3 failed as expected
test cases: 18 | 13 passed | 3 failed | 2 failed as expected
assertions: 40 | 33 passed | 4 failed | 3 failed as expected

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="132" tests="1571" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="132" tests="1568" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/>
@@ -9,7 +9,6 @@
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027: Bitfields can be captured" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1147" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1175 - Hidden Test" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
@@ -233,6 +232,7 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assorted miscellaneous tests" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Bitfields can be captured (#1027)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions involving commas" time="{duration}"/>
<testcase classname="<exe-name>.global" name="CAPTURE parses string and character constants" time="{duration}"/>
@@ -750,9 +750,6 @@ Misc.tests.cpp:<line number>
<testcase classname="<exe-name>.Template_Fixture" name="Template test case method with test types specified inside std::tuple - MyTypes - 0" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture" name="Template test case method with test types specified inside std::tuple - MyTypes - 1" time="{duration}"/>
<testcase classname="<exe-name>.Template_Fixture" name="Template test case method with test types specified inside std::tuple - MyTypes - 2" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 0" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 1" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 2" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside std::tuple - MyTypes - 0" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside std::tuple - MyTypes - 1" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside std::tuple - MyTypes - 2" time="{duration}"/>

View File

@@ -43,25 +43,6 @@
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1027: Bitfields can be captured" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
y.v == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
0 == y.v
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1147" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
@@ -2199,6 +2180,25 @@ Nor would this
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Bitfields can be captured (#1027)" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Original>
y.v == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Original>
0 == y.v
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="CAPTURE can deal with complex expressions" tags="[capture][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<Info>
a := 1
@@ -9895,39 +9895,6 @@ Message from section two
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 0" tags="[list][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Original>
sizeof(TestType) > 0
</Original>
<Expanded>
1 > 0
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 1" tags="[list][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Original>
sizeof(TestType) > 0
</Original>
<Expanded>
1 > 0
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 2" tags="[list][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Original>
sizeof(TestType) > 0
</Original>
<Expanded>
4 > 0
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Template test case with test types specified inside std::tuple - MyTypes - 0" tags="[list][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Original>
@@ -14767,7 +14734,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="1401" failures="149" expectedFailures="21"/>
<OverallResults successes="1398" failures="149" expectedFailures="21"/>
</Group>
<OverallResults successes="1401" failures="148" expectedFailures="21"/>
<OverallResults successes="1398" failures="148" expectedFailures="21"/>
</Catch>

View File

@@ -194,31 +194,6 @@ namespace { namespace CompilationTests {
REQUIRE(std::is_same<TypeList<int>, TypeList<int>>::value);
}
// #925
using signal_t = void (*) (void*);
struct TestClass {
signal_t testMethod_uponComplete_arg = nullptr;
};
namespace utility {
inline static void synchronizing_callback( void * ) { }
}
TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) {
TestClass test;
REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg);
}
TEST_CASE( "#1027: Bitfields can be captured" ) {
struct Y {
uint32_t v : 1;
};
Y y{ 0 };
REQUIRE( y.v == 0 );
REQUIRE( 0 == y.v );
}
}} // namespace CompilationTests

View File

@@ -371,16 +371,6 @@ TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside std
REQUIRE(sizeof(TestType) > 0);
}
struct NonDefaultConstructibleType {
NonDefaultConstructibleType() = delete;
};
using MyNonDefaultConstructibleTypes = std::tuple<NonDefaultConstructibleType, char, float>;
TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside non-default-constructible std::tuple", "[template][list]", MyNonDefaultConstructibleTypes)
{
REQUIRE(sizeof(TestType) > 0);
}
// https://github.com/philsquared/Catch/issues/166
TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") {
SECTION("Outer")
@@ -440,6 +430,12 @@ TEST_CASE( "long long" ) {
REQUIRE( l == std::numeric_limits<long long>::max() );
}
//TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) {
// int i = 0;
// int x = 10/i; // This should cause the signal to fire
// CHECK( x == 0 );
//}
TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" ) {
SUCCEED( "oops!" );
}

View File

@@ -402,6 +402,32 @@ TEST_CASE( "non-copyable objects", "[.][failing]" ) {
CHECK( ti == typeid(int) );
}
// #925
using signal_t = void (*) (void*);
struct TestClass {
signal_t testMethod_uponComplete_arg = nullptr;
};
namespace utility {
inline static void synchronizing_callback( void * ) { }
}
TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) {
TestClass test;
REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg);
}
TEST_CASE( "Bitfields can be captured (#1027)" ) {
struct Y {
uint32_t v : 1;
};
Y y{ 0 };
REQUIRE( y.v == 0 );
REQUIRE( 0 == y.v );
}
TEST_CASE("#1514: stderr/stdout is not captured in tests aborted by an exception", "[output-capture][regression][.]") {
std::cout << "This would not be caught previously\n" << std::flush;
std::clog << "Nor would this\n" << std::flush;

View File

@@ -1,19 +0,0 @@
# Workaround for a peculiarity where CTest disregards the return code from a
# test command if a PASS_REGULAR_EXPRESSION is also set
execute_process(
COMMAND ${CMAKE_ARGV3} -w NoTests "___nonexistent_test___"
RESULT_VARIABLE ret
OUTPUT_VARIABLE out
)
message("${out}")
if(NOT ${ret} MATCHES "^[0-9]+$")
message(FATAL_ERROR "${ret}")
endif()
if(${ret} EQUAL 0)
message(FATAL_ERROR "Expected nonzero return code")
elseif(${out} MATCHES "Helper failed with")
message(FATAL_ERROR "Helper failed")
endif()

View File

@@ -10,13 +10,13 @@ import re
import difflib
import scriptCommon
from scriptCommon import catchPath
from scriptCommon import catchPathSymbolic
if os.name == 'nt':
# Enable console colours on windows
os.system('')
rootPath = os.path.join(catchPath, 'projects/SelfTest/Baselines')
rootPath = os.path.join(catchPathSymbolic, 'projects/SelfTest/Baselines')
langFilenameParser = re.compile(r'(.+\.[ch]pp)')
filelocParser = re.compile(r'''
@@ -92,9 +92,10 @@ def diffFiles(fileA, fileB):
def normalizeFilepath(line):
if catchPath in line:
if catchPathSymbolic in line or catchPathSymbolic.lower() in line:
# make paths relative to Catch root
line = line.replace(catchPath + os.sep, '')
line = line.replace(catchPathSymbolic + os.sep, '')
line = line.replace(catchPathSymbolic.lower() + os.sep, '')
m = langFilenameParser.match(line)
if m:

View File

@@ -1,94 +0,0 @@
#!/usr/bin/env python
#
# extractFeaturesFromReleaseNotes.py
#
# Read the release notes - docs/release-notes.md - and generate text
# for pasting in to individual documentation pages, to indicate which
# versions recent features were released in.
#
# Using the output of the file is easier than manually constructing
# the text to paste in to documentation pages.
#
# One way to use this:
# - run this script, saving the output to some temporary file
# - diff this output with the actual release notes page
# - the differences are Markdown text that can be pasted in to the
# appropriate documentation pages in the docs/ directory.
# - each release also has a github link to show which documentation files
# were changed in it.
# This can be helpful to see which documentation pages
# to add the 'Introduced in Catch ...' snippets to the relevant pages.
#
from __future__ import print_function
import re
def create_introduced_in_text(version, bug_number = None):
"""Generate text to paste in to documentation file"""
if bug_number:
return '> [Introduced](https://github.com/catchorg/Catch2/issues/%s) in Catch %s.' % (bug_number, version)
else:
# Use this text for changes that don't have issue numbers
return '> Introduced in Catch %s.' % version
def link_to_changes_in_release(release, releases):
"""
Markdown text for a hyperlink showing all edits in a release, or empty string
:param release: A release version, as a string
:param releases: A container of releases, in descending order - newest to oldest
:return: Markdown text for a hyperlink showing the differences between the give release and the prior one,
or empty string, if the previous release is not known
"""
if release == releases[-1]:
# This is the earliest release we know about
return ''
index = releases.index(release)
previous_release = releases[index + 1]
return '\n[Changes in %s](https://github.com/catchorg/Catch2/compare/v%s...v%s)' % (release, previous_release, release)
def write_recent_release_notes_with_introduced_text():
current_version = None
release_toc_regex = r'\[(\d.\d.\d)\]\(#\d+\)<br>'
issue_number_regex = r'#[0-9]+'
releases = []
with open('../docs/release-notes.md') as release_notes:
for line in release_notes:
line = line[:-1]
print(line)
# Extract version number from table of contents
match = re.search(release_toc_regex, line)
if match:
release_name = match.group(1)
releases.append(release_name)
if line.startswith('## '):
# It's a section with version number
current_version = line.replace('## ', '')
# We decided not to add released-date info for older versions
if current_version == 'Older versions':
break
print(create_introduced_in_text(current_version))
print(link_to_changes_in_release(current_version, releases))
# Not yet found a version number, so to avoid picking up hyperlinks to
# version numbers in the index, keep going
if not current_version:
continue
for bug_link in re.findall(issue_number_regex, line):
bug_number = bug_link.replace('#', '')
print(create_introduced_in_text(current_version, bug_number))
if __name__ == '__main__':
write_recent_release_notes_with_introduced_text()

View File

@@ -4,8 +4,6 @@ import os
import sys
import re
import string
import glob
import fnmatch
from scriptCommon import catchPath
@@ -100,47 +98,29 @@ def updateReadmeFile(version):
def updateCmakeFile(version):
with open(cmakePath, 'rb') as file:
with open(cmakePath, 'r') as file:
lines = file.readlines()
replacementRegex = re.compile(b'project\\(Catch2 LANGUAGES CXX VERSION \\d+\\.\\d+\\.\\d+\\)')
replacement = 'project(Catch2 LANGUAGES CXX VERSION {0})'.format(version.getVersionString()).encode('ascii')
with open(cmakePath, 'wb') as file:
with open(cmakePath, 'w') as file:
for line in lines:
file.write(replacementRegex.sub(replacement, line))
if 'project(Catch2 LANGUAGES CXX VERSION ' in line:
file.write('project(Catch2 LANGUAGES CXX VERSION {0})\n'.format(version.getVersionString()))
else:
file.write(line)
def updateVersionDefine(version):
# First member of the tuple is the compiled regex object, the second is replacement if it matches
replacementRegexes = [(re.compile(b'#define CATCH_VERSION_MAJOR \\d+'),'#define CATCH_VERSION_MAJOR {}'.format(version.majorVersion).encode('ascii')),
(re.compile(b'#define CATCH_VERSION_MINOR \\d+'),'#define CATCH_VERSION_MINOR {}'.format(version.minorVersion).encode('ascii')),
(re.compile(b'#define CATCH_VERSION_PATCH \\d+'),'#define CATCH_VERSION_PATCH {}'.format(version.patchNumber).encode('ascii')),
]
with open(definePath, 'rb') as file:
with open(definePath, 'r') as file:
lines = file.readlines()
with open(definePath, 'wb') as file:
with open(definePath, 'w') as file:
for line in lines:
for replacement in replacementRegexes:
line = replacement[0].sub(replacement[1], line)
file.write(line)
def updateVersionPlaceholder(filename, version):
with open(filename, 'rb') as file:
lines = file.readlines()
placeholderRegex = re.compile(b'\) in Catch X.Y.Z')
replacement = '\) in Catch {}.{}.{}'.format(version.majorVersion, version.minorVersion, version.patchNumber).encode('ascii')
with open(filename, 'wb') as file:
for line in lines:
file.write(placeholderRegex.sub(replacement, line))
def updateDocumentationVersionPlaceholders(version):
print('Updating version placeholder in documentation')
docsPath = os.path.join(catchPath, 'docs/')
for basePath, _, files in os.walk(docsPath):
for file in files:
if fnmatch.fnmatch(file, "*.md") and "contributing.md" != file:
updateVersionPlaceholder(os.path.join(basePath, file), version)
if '#define CATCH_VERSION_MAJOR' in line:
file.write('#define CATCH_VERSION_MAJOR {}\n'.format(version.majorVersion))
elif '#define CATCH_VERSION_MINOR' in line:
file.write('#define CATCH_VERSION_MINOR {}\n'.format(version.minorVersion))
elif '#define CATCH_VERSION_PATCH' in line:
file.write('#define CATCH_VERSION_PATCH {}\n'.format(version.patchNumber))
else:
file.write(line)
def performUpdates(version):
@@ -163,4 +143,3 @@ def performUpdates(version):
updateReadmeFile(version)
updateCmakeFile(version)
updateDocumentationVersionPlaceholders(version)

View File

@@ -4,6 +4,7 @@ import subprocess
catchPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0])))
catchPathSymbolic = os.path.dirname(os.path.dirname(sys.argv[0]))
def getBuildExecutable():
if os.name == 'nt':

View File

@@ -1,6 +1,6 @@
/*
* Catch v2.9.2
* Generated: 2019-08-08 13:35:12.279703
* Catch v2.9.1
* Generated: 2019-06-17 11:59:24.363643
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 9
#define CATCH_VERSION_PATCH 2
#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header
@@ -275,17 +275,6 @@ namespace Catch {
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
////////////////////////////////////////////////////////////////////////////////
// RTX is a special version of Windows that is real time.
// This means that it is detected as Windows, but does not provide
// the same set of capabilities as real Windows does.
#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
#define CATCH_INTERNAL_CONFIG_NO_ASYNC
#define CATCH_CONFIG_COLOUR_NONE
#endif
////////////////////////////////////////////////////////////////////////////////
// Check if string_view is available and usable
// The check is split apart to work around v140 (VS2015) preprocessor issue...
@@ -303,14 +292,6 @@ namespace Catch {
# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
#endif // __has_include
////////////////////////////////////////////////////////////////////////////////
// Check if byte is available and usable
#if defined(__has_include)
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
#endif // __has_include
////////////////////////////////////////////////////////////////////////////////
// Check if variant is available and usable
#if defined(__has_include)
@@ -365,10 +346,6 @@ namespace Catch {
# define CATCH_CONFIG_CPP17_VARIANT
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
# define CATCH_CONFIG_CPP17_BYTE
#endif
#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
#endif
@@ -385,7 +362,7 @@ namespace Catch {
# define CATCH_CONFIG_POLYFILL_ISNAN
#endif
#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
# define CATCH_CONFIG_USE_ASYNC
#endif
@@ -538,7 +515,6 @@ namespace Catch {
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
};
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
@@ -1177,7 +1153,7 @@ struct AutoReg : NonCopyable {
} \
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
using TestInit = decltype(convert<TestName>(std::declval<TmplList>())); \
using TestInit = decltype(convert<TestName>(TmplList {})); \
TestInit t; \
t.reg_tests(); \
return 0; \
@@ -1303,7 +1279,7 @@ struct AutoReg : NonCopyable {
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
using TestInit = decltype(convert<TestNameClass>(std::declval<TmplList>()));\
using TestInit = decltype(convert<TestNameClass>(TmplList {}));\
TestInit t;\
t.reg_tests();\
return 0;\
@@ -1703,12 +1679,6 @@ namespace Catch {
}
};
#if defined(CATCH_CONFIG_CPP17_BYTE)
template<>
struct StringMaker<std::byte> {
static std::string convert(std::byte value);
};
#endif // defined(CATCH_CONFIG_CPP17_BYTE)
template<>
struct StringMaker<int> {
static std::string convert(int value);
@@ -3210,15 +3180,6 @@ namespace Matchers {
virtual bool match( ObjectT const& arg ) const = 0;
};
#if defined(__OBJC__)
// Hack to fix Catch GH issue #1661. Could use id for generic Object support.
// use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
template<>
struct MatcherMethod<NSString*> {
virtual bool match( NSString* arg ) const = 0;
};
#endif
#ifdef __clang__
# pragma clang diagnostic pop
#endif
@@ -3868,9 +3829,6 @@ namespace Generators {
template<typename T>
class FixedValuesGenerator final : public IGenerator<T> {
static_assert(!std::is_same<T, bool>::value,
"ValuesGenerator does not support bools because of std::vector<bool>"
"specialization, use SingleValue Generator instead.");
std::vector<T> m_values;
size_t m_idx = 0;
public:
@@ -4090,9 +4048,6 @@ namespace Generators {
template <typename T>
class RepeatGenerator : public IGenerator<T> {
static_assert(!std::is_same<T, bool>::value,
"RepeatGenerator currently does not support bools"
"because of std::vector<bool> specialization");
GeneratorWrapper<T> m_generator;
mutable std::vector<T> m_returned;
size_t m_target_repeats;
@@ -4207,14 +4162,12 @@ namespace Generators {
m_chunk_size(size), m_generator(std::move(generator))
{
m_chunk.reserve(m_chunk_size);
if (m_chunk_size != 0) {
m_chunk.push_back(m_generator.get());
for (size_t i = 1; i < m_chunk_size; ++i) {
if (!m_generator.next()) {
Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
}
m_chunk.push_back(m_generator.get());
m_chunk.push_back(m_generator.get());
for (size_t i = 1; i < m_chunk_size; ++i) {
if (!m_generator.next()) {
Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
}
m_chunk.push_back(m_generator.get());
}
}
std::vector<T> const& get() const override {
@@ -4758,7 +4711,7 @@ namespace Catch {
arcSafeRelease( m_substr );
}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return false;
}
@@ -4768,7 +4721,7 @@ namespace Catch {
struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr];
}
@@ -4781,7 +4734,7 @@ namespace Catch {
struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound;
}
@@ -4794,7 +4747,7 @@ namespace Catch {
struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0;
}
@@ -4806,7 +4759,7 @@ namespace Catch {
struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
}
@@ -4914,23 +4867,17 @@ namespace Catch
namespace Catch {
struct IConfig;
class TestSpec {
class Pattern {
public:
explicit Pattern( std::string const& name );
struct Pattern {
virtual ~Pattern();
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
std::string const& name() const;
private:
std::string const m_name;
};
using PatternPtr = std::shared_ptr<Pattern>;
class NamePattern : public Pattern {
public:
explicit NamePattern( std::string const& name, std::string const& filterString );
NamePattern( std::string const& name );
virtual ~NamePattern();
bool matches( TestCaseInfo const& testCase ) const override;
private:
WildcardPattern m_wildcardPattern;
@@ -4938,7 +4885,8 @@ namespace Catch {
class TagPattern : public Pattern {
public:
explicit TagPattern( std::string const& tag, std::string const& filterString );
TagPattern( std::string const& tag );
virtual ~TagPattern();
bool matches( TestCaseInfo const& testCase ) const override;
private:
std::string m_tag;
@@ -4946,7 +4894,8 @@ namespace Catch {
class ExcludedPattern : public Pattern {
public:
explicit ExcludedPattern( PatternPtr const& underlyingPattern );
ExcludedPattern( PatternPtr const& underlyingPattern );
virtual ~ExcludedPattern();
bool matches( TestCaseInfo const& testCase ) const override;
private:
PatternPtr m_underlyingPattern;
@@ -4956,19 +4905,11 @@ namespace Catch {
std::vector<PatternPtr> m_patterns;
bool matches( TestCaseInfo const& testCase ) const;
std::string name() const;
};
public:
struct FilterMatch {
std::string name;
std::vector<TestCase const*> tests;
};
using Matches = std::vector<FilterMatch>;
bool hasFilters() const;
bool matches( TestCaseInfo const& testCase ) const;
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
private:
std::vector<Filter> m_filters;
@@ -5008,10 +4949,8 @@ namespace Catch {
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Mode m_mode = None;
bool m_exclusion = false;
std::size_t m_pos = 0;
std::size_t m_start = std::string::npos, m_pos = 0;
std::string m_arg;
std::string m_substring;
std::string m_patternName;
std::vector<std::size_t> m_escapeChars;
TestSpec::Filter m_currentFilter;
TestSpec m_testSpec;
@@ -5025,32 +4964,26 @@ namespace Catch {
private:
void visitChar( char c );
void startNewMode( Mode mode );
bool processNoneChar( char c );
void processNameChar( char c );
bool processOtherChar( char c );
void endMode();
void startNewMode( Mode mode, std::size_t start );
void escape();
bool isControlChar( char c ) const;
std::string subString() const;
template<typename T>
void addPattern() {
std::string token = m_patternName;
std::string token = subString();
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
token = token.substr( 8 );
}
if( !token.empty() ) {
TestSpec::PatternPtr pattern = std::make_shared<T>( token, m_substring );
TestSpec::PatternPtr pattern = std::make_shared<T>( token );
if( m_exclusion )
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
m_currentFilter.m_patterns.push_back( pattern );
}
m_substring.clear();
m_patternName.clear();
m_exclusion = false;
m_mode = None;
}
@@ -6193,7 +6126,6 @@ namespace Catch {
void testRunEnded(TestRunStats const& testRunStats) override;
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void benchmarkPreparing(std::string const& name) override;
void benchmarkStarting(BenchmarkInfo const&) override;
void benchmarkEnded(BenchmarkStats<> const&) override;
void benchmarkFailed(std::string const&) override;
@@ -9987,16 +9919,7 @@ namespace Catch {
}
// end catch_debug_console.h
#if defined(__ANDROID__)
#include <android/log.h>
namespace Catch {
void writeToDebugConsole( std::string const& text ) {
__android_log_print( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
}
}
#elif defined(CATCH_PLATFORM_WINDOWS)
#ifdef CATCH_PLATFORM_WINDOWS
namespace Catch {
void writeToDebugConsole( std::string const& text ) {
@@ -10450,7 +10373,7 @@ namespace Catch {
// 32kb for the alternate stack seems to be sufficient. However, this value
// is experimentally determined, so that's not guaranteed.
static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
static SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
@@ -10888,18 +10811,9 @@ namespace Catch {
}
std::string TagInfo::all() const {
size_t size = 0;
for (auto const& spelling : spellings) {
// Add 2 for the brackes
size += spelling.size() + 2;
}
std::string out; out.reserve(size);
for (auto const& spelling : spellings) {
out += '[';
out += spelling;
out += ']';
}
std::string out;
for( auto const& spelling : spellings )
out += "[" + spelling + "]";
return out;
}
@@ -11746,8 +11660,6 @@ namespace Catch {
struct IConfig;
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
@@ -12591,7 +12503,7 @@ namespace Catch {
void libIdentify();
int applyCommandLine( int argc, char const * const * argv );
#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int applyCommandLine( int argc, wchar_t const * const * argv );
#endif
@@ -12658,8 +12570,6 @@ namespace Catch {
// end catch_version.h
#include <cstdlib>
#include <iomanip>
#include <set>
#include <iterator>
namespace Catch {
@@ -12693,53 +12603,45 @@ namespace Catch {
return ret;
}
class TestGroup {
public:
explicit TestGroup(std::shared_ptr<Config> const& config)
: m_config{config}
, m_context{config, makeReporter(config)}
{
auto const& allTestCases = getAllTestCasesSorted(*m_config);
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
auto reporter = makeReporter(config);
if (m_matches.empty()) {
for (auto const& test : allTestCases)
if (!test.isHidden())
m_tests.emplace(&test);
} else {
for (auto const& match : m_matches)
m_tests.insert(match.tests.begin(), match.tests.end());
}
RunContext context(config, std::move(reporter));
Totals totals;
context.testGroupStarting(config->name(), 1, 1);
TestSpec testSpec = config->testSpec();
auto const& allTestCases = getAllTestCasesSorted(*config);
for (auto const& testCase : allTestCases) {
bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
(testSpec.hasFilters() && matchTest(testCase, testSpec, *config));
if (!context.aborting() && matching)
totals += context.runTest(testCase);
else
context.reporter().skipTest(testCase);
}
Totals execute() {
Totals totals;
m_context.testGroupStarting(m_config->name(), 1, 1);
for (auto const& testCase : m_tests) {
if (!m_context.aborting())
totals += m_context.runTest(*testCase);
else
m_context.reporter().skipTest(*testCase);
if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
ReusableStringStream testConfig;
bool first = true;
for (const auto& input : config->getTestsOrTags()) {
if (!first) { testConfig << ' '; }
first = false;
testConfig << input;
}
for (auto const& match : m_matches) {
if (match.tests.empty()) {
m_context.reporter().noMatchingTestCases(match.name);
totals.error = -1;
}
}
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
return totals;
context.reporter().noMatchingTestCases(testConfig.str());
totals.error = -1;
}
private:
using Tests = std::set<TestCase const*>;
std::shared_ptr<Config> m_config;
RunContext m_context;
Tests m_tests;
TestSpec::Matches m_matches;
};
context.testGroupEnded(config->name(), totals, 1, 1);
return totals;
}
void applyFilenamesAsTags(Catch::IConfig const& config) {
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
@@ -12839,7 +12741,7 @@ namespace Catch {
return 0;
}
#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
char **utf8Argv = new char *[ argc ];
@@ -12916,12 +12818,7 @@ namespace Catch {
if( Option<std::size_t> listed = list( m_config ) )
return static_cast<int>( *listed );
TestGroup tests { m_config };
auto const totals = tests.execute();
if( m_config->warnAboutNoTests() && totals.error == -1 )
return 2;
auto totals = runTests( m_config );
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
@@ -13632,13 +13529,8 @@ namespace Catch {
}
return sorted;
}
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
return !testCase.throws() || config.allowThrows();
}
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
return testSpec.matches( testCase ) && isThrowSafe( testCase, config );
return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
}
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
@@ -13841,7 +13733,7 @@ namespace TestCaseTracking {
m_runState = CompletedSuccessfully;
break;
case ExecutingChildren:
if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
if( m_children.empty() || m_children.back()->isComplete() )
m_runState = CompletedSuccessfully;
break;
@@ -13984,77 +13876,47 @@ namespace Catch {
namespace Catch {
TestSpec::Pattern::Pattern( std::string const& name )
: m_name( name )
{}
TestSpec::Pattern::~Pattern() = default;
TestSpec::NamePattern::~NamePattern() = default;
TestSpec::TagPattern::~TagPattern() = default;
TestSpec::ExcludedPattern::~ExcludedPattern() = default;
std::string const& TestSpec::Pattern::name() const {
return m_name;
}
TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
: Pattern( filterString )
, m_wildcardPattern( toLower( name ), CaseSensitive::No )
TestSpec::NamePattern::NamePattern( std::string const& name )
: m_wildcardPattern( toLower( name ), CaseSensitive::No )
{}
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
return m_wildcardPattern.matches( toLower( testCase.name ) );
}
TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
: Pattern( filterString )
, m_tag( toLower( tag ) )
{}
TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
return std::find(begin(testCase.lcaseTags),
end(testCase.lcaseTags),
m_tag) != end(testCase.lcaseTags);
}
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern )
: Pattern( underlyingPattern->name() )
, m_underlyingPattern( underlyingPattern )
{}
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const {
return !m_underlyingPattern->matches( testCase );
}
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } );
}
std::string TestSpec::Filter::name() const {
std::string name;
for( auto const& p : m_patterns )
name += p->name();
return name;
// All patterns in a filter must match for the filter to be a match
for( auto const& pattern : m_patterns ) {
if( !pattern->matches( testCase ) )
return false;
}
return true;
}
bool TestSpec::hasFilters() const {
return !m_filters.empty();
}
bool TestSpec::matches( TestCaseInfo const& testCase ) const {
return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
// A TestSpec matches if any filter matches
for( auto const& filter : m_filters )
if( filter.matches( testCase ) )
return true;
return false;
}
TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
{
Matches matches( m_filters.size() );
std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
std::vector<TestCase const*> currentMatches;
for( auto const& test : testCases )
if( isThrowSafe( test, config ) && filter.matches( test ) )
currentMatches.emplace_back( &test );
return FilterMatch{ filter.name(), currentMatches };
} );
return matches;
}
}
// end catch_test_spec.cpp
// start catch_test_spec_parser.cpp
@@ -14066,125 +13928,64 @@ namespace Catch {
TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
m_mode = None;
m_exclusion = false;
m_start = std::string::npos;
m_arg = m_tagAliases->expandAliases( arg );
m_escapeChars.clear();
m_substring.reserve(m_arg.size());
m_patternName.reserve(m_arg.size());
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
visitChar( m_arg[m_pos] );
endMode();
if( m_mode == Name )
addPattern<TestSpec::NamePattern>();
return *this;
}
TestSpec TestSpecParser::testSpec() {
addFilter();
return m_testSpec;
}
void TestSpecParser::visitChar( char c ) {
if( c == ',' ) {
endMode();
addFilter();
return;
if( m_mode == None ) {
switch( c ) {
case ' ': return;
case '~': m_exclusion = true; return;
case '[': return startNewMode( Tag, ++m_pos );
case '"': return startNewMode( QuotedName, ++m_pos );
case '\\': return escape();
default: startNewMode( Name, m_pos ); break;
}
}
switch( m_mode ) {
case None:
if( processNoneChar( c ) )
return;
break;
case Name:
processNameChar( c );
break;
case EscapedName:
endMode();
break;
default:
case Tag:
case QuotedName:
if( processOtherChar( c ) )
return;
break;
if( m_mode == Name ) {
if( c == ',' ) {
addPattern<TestSpec::NamePattern>();
addFilter();
}
else if( c == '[' ) {
if( subString() == "exclude:" )
m_exclusion = true;
else
addPattern<TestSpec::NamePattern>();
startNewMode( Tag, ++m_pos );
}
else if( c == '\\' )
escape();
}
m_substring += c;
if( !isControlChar( c ) )
m_patternName += c;
else if( m_mode == EscapedName )
m_mode = Name;
else if( m_mode == QuotedName && c == '"' )
addPattern<TestSpec::NamePattern>();
else if( m_mode == Tag && c == ']' )
addPattern<TestSpec::TagPattern>();
}
// Two of the processing methods return true to signal the caller to return
// without adding the given character to the current pattern strings
bool TestSpecParser::processNoneChar( char c ) {
switch( c ) {
case ' ':
return true;
case '~':
m_exclusion = true;
return false;
case '[':
startNewMode( Tag );
return false;
case '"':
startNewMode( QuotedName );
return false;
case '\\':
escape();
return true;
default:
startNewMode( Name );
return false;
}
}
void TestSpecParser::processNameChar( char c ) {
if( c == '[' ) {
if( m_substring == "exclude:" )
m_exclusion = true;
else
endMode();
startNewMode( Tag );
}
}
bool TestSpecParser::processOtherChar( char c ) {
if( !isControlChar( c ) )
return false;
m_substring += c;
endMode();
return true;
}
void TestSpecParser::startNewMode( Mode mode ) {
void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
m_mode = mode;
}
void TestSpecParser::endMode() {
switch( m_mode ) {
case Name:
case QuotedName:
return addPattern<TestSpec::NamePattern>();
case Tag:
return addPattern<TestSpec::TagPattern>();
case EscapedName:
return startNewMode( Name );
case None:
default:
return startNewMode( None );
}
m_start = start;
}
void TestSpecParser::escape() {
if( m_mode == None )
m_start = m_pos;
m_mode = EscapedName;
m_escapeChars.push_back( m_pos );
}
bool TestSpecParser::isControlChar( char c ) const {
switch( m_mode ) {
default:
return false;
case None:
return c == '~';
case Name:
return c == '[';
case EscapedName:
return true;
case QuotedName:
return c == '"';
case Tag:
return c == '[' || c == ']';
}
}
std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
void TestSpecParser::addFilter() {
if( !m_currentFilter.m_patterns.empty() ) {
@@ -14424,13 +14225,6 @@ std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
}
#endif
#if defined(CATCH_CONFIG_CPP17_BYTE)
#include <cstddef>
std::string StringMaker<std::byte>::convert(std::byte value) {
return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
}
#endif // defined(CATCH_CONFIG_CPP17_BYTE)
std::string StringMaker<int>::convert(int value) {
return ::Catch::Detail::stringify(static_cast<long long>(value));
}
@@ -14620,7 +14414,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 9, 2, "", 0 );
static Version version( 2, 9, 1, "", 0 );
return version;
}
@@ -15207,25 +15001,24 @@ private:
if (itMessage == messages.end())
return;
const auto itEnd = messages.cend();
const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
// using messages.end() directly yields (or auto) compilation error:
std::vector<MessageInfo>::const_iterator itEnd = messages.end();
const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
{
Colour colourGuard(colour);
stream << " with " << pluralise(N, "message") << ':';
}
while (itMessage != itEnd) {
for (; itMessage != itEnd; ) {
// If this assertion is a warning ignore any INFO messages
if (printInfoMessages || itMessage->type != ResultWas::Info) {
printMessage();
if (itMessage != itEnd) {
stream << " '" << itMessage->message << '\'';
if (++itMessage != itEnd) {
Colour colourGuard(dimColour());
stream << " and";
}
continue;
}
++itMessage;
}
}
@@ -16562,13 +16355,10 @@ namespace Catch {
}
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void XmlReporter::benchmarkPreparing(std::string const& name) {
m_xml.startElement("BenchmarkResults")
.writeAttribute("name", name);
}
void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
m_xml.writeAttribute("samples", info.samples)
m_xml.startElement("BenchmarkResults")
.writeAttribute("name", info.name)
.writeAttribute("samples", info.samples)
.writeAttribute("resamples", info.resamples)
.writeAttribute("iterations", info.iterations)
.writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution))