forked from catchorg/Catch2
Compare commits
86 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d633072794 | ||
|
51ed08be22 | ||
|
1701325caa | ||
|
7aee973a4a | ||
|
99575b45db | ||
|
1a03918455 | ||
|
bd667f4d69 | ||
|
28db5ed4c9 | ||
|
7d2451f119 | ||
|
5bf6e47381 | ||
|
29b3b7ae6b | ||
|
ef5fd8d42f | ||
|
693647c43f | ||
|
288387fa10 | ||
|
165de9b072 | ||
|
bf4771a7ed | ||
|
7012a31a39 | ||
|
269303d9d9 | ||
|
e8bfd882e8 | ||
|
2bd0722470 | ||
|
45ebf17ec7 | ||
|
093b72416d | ||
|
c99a346490 | ||
|
359a54b6bd | ||
|
711d750ca7 | ||
|
95f7712808 | ||
|
dbbab8727c | ||
|
5d4061af12 | ||
|
9ccea82d7f | ||
|
dd3d27de57 | ||
|
7f229b4ff1 | ||
|
c03b23c84b | ||
|
17686ba571 | ||
|
d75e9b3c0f | ||
|
67308bb606 | ||
|
16dc219704 | ||
|
63d1a96908 | ||
|
061f1f836a | ||
|
5929d9530c | ||
|
e46a70f829 | ||
|
64a9c02315 | ||
|
61f4c7ab85 | ||
|
50fefd059a | ||
|
a2baabbf71 | ||
|
6f9cdd6583 | ||
|
d9e99dc2ca | ||
|
804a2118c2 | ||
|
aa1e470058 | ||
|
8d5d54e529 | ||
|
73d533ff5c | ||
|
899c5ed3df | ||
|
084b1d5fe6 | ||
|
4109870435 | ||
|
2988e9f6cf | ||
|
bc02ada4b0 | ||
|
61e1ea9185 | ||
|
b275ead8c3 | ||
|
b0381e42b2 | ||
|
8989c9b560 | ||
|
d084162b2f | ||
|
0387fb64ce | ||
|
75200b462c | ||
|
17e09be3b9 | ||
|
1c99b0ff81 | ||
|
64a0f466ec | ||
|
47602ac556 | ||
|
d1e7344f16 | ||
|
3ed5441067 | ||
|
bdee512057 | ||
|
188b3e6511 | ||
|
bbf70ca74b | ||
|
23f023f9ed | ||
|
c1720d0c42 | ||
|
d54c2258e0 | ||
|
b3faceede2 | ||
|
e7fce90b49 | ||
|
799c7a2eed | ||
|
9bc15939a5 | ||
|
461843b1f0 | ||
|
5b4ffd3c93 | ||
|
21a1cd5683 | ||
|
4902cd7215 | ||
|
18ff34788c | ||
|
d0de666362 | ||
|
862955d657 | ||
|
557e47c3ca |
@@ -31,7 +31,7 @@ class BuilderSettings(object):
|
|||||||
not match the stable pattern. Otherwise it will upload to stable
|
not match the stable pattern. Otherwise it will upload to stable
|
||||||
channel.
|
channel.
|
||||||
"""
|
"""
|
||||||
return os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/horenmar/Catch2")
|
return os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/catchorg/Catch2")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def upload_only_when_stable(self):
|
def upload_only_when_stable(self):
|
||||||
@@ -49,7 +49,7 @@ class BuilderSettings(object):
|
|||||||
def reference(self):
|
def reference(self):
|
||||||
""" Read project version from branch create Conan referece
|
""" Read project version from branch create Conan referece
|
||||||
"""
|
"""
|
||||||
return os.getenv("CONAN_REFERENCE", "Catch2/{}@{}/{}".format(self._version, self.username, self.channel))
|
return os.getenv("CONAN_REFERENCE", "Catch2/{}".format(self._version))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def channel(self):
|
def channel(self):
|
||||||
|
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create an issue that documents a bug
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Reproduction steps**
|
||||||
|
Steps to reproduce the bug.
|
||||||
|
<!-- Usually this means a small and self-contained piece of code that uses Catch and specifying compiler flags if relevant. -->
|
||||||
|
|
||||||
|
|
||||||
|
**Platform information:**
|
||||||
|
<!-- Fill in any extra information that might be important for your issue. -->
|
||||||
|
- OS: **Windows NT**
|
||||||
|
- Compiler+version: **GCC v2.9.5**
|
||||||
|
- Catch version: **v1.2.3**
|
||||||
|
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Create an issue that requests a feature or other improvement
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Description**
|
||||||
|
Describe the feature/change you request and why do you want it.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
29
.github/issue_template.md
vendored
29
.github/issue_template.md
vendored
@@ -1,29 +0,0 @@
|
|||||||
## Description
|
|
||||||
<!--
|
|
||||||
If your issue is a bugreport, this means describing what you did,
|
|
||||||
what did you want to happen and what actually did happen.
|
|
||||||
|
|
||||||
If your issue is a feature request, describe the feature and why do you
|
|
||||||
want it.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
### Steps to reproduce
|
|
||||||
<!--
|
|
||||||
This is only relevant for bug reports, but if you do have one,
|
|
||||||
please provide a minimal set of steps to reproduce the problem.
|
|
||||||
|
|
||||||
Usually this means providing a small and self-contained code using Catch
|
|
||||||
and specifying compiler flags/tools used if relevant.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
### Extra information
|
|
||||||
<!--
|
|
||||||
Fill in any extra information that might be important for your issue.
|
|
||||||
|
|
||||||
If your issue is a bugreport, definitely fill out at least the following.
|
|
||||||
-->
|
|
||||||
* Catch version: **v42.42.42**
|
|
||||||
* Operating System: **Joe's discount operating system**
|
|
||||||
* Compiler+version: **Hidden Dragon v1.2.3**
|
|
@@ -1,5 +1,4 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
sudo: false
|
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
except:
|
except:
|
||||||
@@ -277,7 +276,7 @@ matrix:
|
|||||||
- "3.7"
|
- "3.7"
|
||||||
dist: xenial
|
dist: xenial
|
||||||
install:
|
install:
|
||||||
- pip install conan conan-package-tools
|
- pip install conan==1.10.2 conan-package-tools
|
||||||
env:
|
env:
|
||||||
- CONAN_GCC_VERSIONS=8
|
- CONAN_GCC_VERSIONS=8
|
||||||
- CONAN_DOCKER_IMAGE=conanio/gcc8
|
- CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||||
@@ -305,7 +304,7 @@ before_script:
|
|||||||
# Use Debug builds for running Valgrind and building examples
|
# Use Debug builds for running Valgrind and building examples
|
||||||
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_CPP17=${CPP17} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE} -DCATCH_BUILD_EXTRA_TESTS=${EXTRAS}
|
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_CPP17=${CPP17} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE} -DCATCH_BUILD_EXTRA_TESTS=${EXTRAS}
|
||||||
# Don't bother with release build for coverage build
|
# Don't bother with release build for coverage build
|
||||||
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14} -DUSE_CPP17=${CPP17}
|
||||||
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
|
|||||||
set(NOT_SUBPROJECT ON)
|
set(NOT_SUBPROJECT ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Catch2 LANGUAGES CXX VERSION 2.5.0)
|
project(Catch2 LANGUAGES CXX VERSION 2.7.0)
|
||||||
|
|
||||||
# Provide path for scripts
|
# Provide path for scripts
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
[](https://travis-ci.org/catchorg/Catch2)
|
[](https://travis-ci.org/catchorg/Catch2)
|
||||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||||
[](https://codecov.io/gh/catchorg/Catch2)
|
[](https://codecov.io/gh/catchorg/Catch2)
|
||||||
[](https://wandbox.org/permlink/7lDqHmzKQxA2eaM0)
|
[](https://wandbox.org/permlink/byNJIivVphHo170P)
|
||||||
[](https://discord.gg/4CWS9zD)
|
[](https://discord.gg/4CWS9zD)
|
||||||
|
|
||||||
|
|
||||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.5.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
<a href="https://github.com/catchorg/Catch2/releases/download/v2.7.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
|
||||||
## Catch2 is released!
|
## Catch2 is released!
|
||||||
|
|
||||||
|
@@ -109,7 +109,7 @@ function(ParseFile SourceFile TestTarget)
|
|||||||
# Get test type and fixture if applicable
|
# Get test type and fixture if applicable
|
||||||
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
|
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
|
||||||
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
|
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
|
||||||
string(REPLACE "${TestType}(" "" TestFixture "${TestTypeAndFixture}")
|
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
|
||||||
|
|
||||||
# Get string parts of test definition
|
# Get string parts of test definition
|
||||||
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
|
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
|
||||||
@@ -164,7 +164,7 @@ function(ParseFile SourceFile TestTarget)
|
|||||||
break()
|
break()
|
||||||
endif(result)
|
endif(result)
|
||||||
endforeach(label)
|
endforeach(label)
|
||||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound})
|
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
|
||||||
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
||||||
else()
|
else()
|
||||||
PrintDebugMessage("Adding test \"${CTestName}\"")
|
PrintDebugMessage("Adding test \"${CTestName}\"")
|
||||||
@@ -172,11 +172,21 @@ function(ParseFile SourceFile TestTarget)
|
|||||||
PrintDebugMessage("Setting labels to ${Labels}")
|
PrintDebugMessage("Setting labels to ${Labels}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Escape commas in the test spec
|
||||||
|
string(REPLACE "," "\\," Name ${Name})
|
||||||
|
|
||||||
# Add the test and set its properties
|
# Add the test and set its properties
|
||||||
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} ${TestTarget} ${Name} ${AdditionalCatchParameters})
|
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} ${TestTarget} ${Name} ${AdditionalCatchParameters})
|
||||||
|
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
|
||||||
|
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
|
||||||
|
PrintDebugMessage("Setting DISABLED test property")
|
||||||
|
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
|
||||||
|
else()
|
||||||
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||||
LABELS "${Labels}")
|
LABELS "${Labels}")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@@ -13,5 +13,7 @@ fact then please let us know - either directly, via a PR or
|
|||||||
[issue](https://github.com/philsquared/Catch/issues), or on the [forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
|
[issue](https://github.com/philsquared/Catch/issues), or on the [forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
|
||||||
|
|
||||||
- Bloomberg
|
- Bloomberg
|
||||||
|
- [Bloomlife](https://bloomlife.com)
|
||||||
- NASA
|
- NASA
|
||||||
- [Inscopix Inc.](https://www.inscopix.com/)
|
- [Inscopix Inc.](https://www.inscopix.com/)
|
||||||
|
- [Makimo](https://makimo.pl/)
|
||||||
|
@@ -204,6 +204,7 @@ By default, Catch does not stringify some types from the standard library. This
|
|||||||
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple
|
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple
|
||||||
CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
|
CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
|
||||||
CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER // Provide StringMaker specialization for std::variant, std::monostate (on C++17)
|
CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER // Provide StringMaker specialization for std::variant, std::monostate (on C++17)
|
||||||
|
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (on C++17)
|
||||||
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
||||||
|
|
||||||
|
|
||||||
|
@@ -37,20 +37,42 @@ as these are managed by the scripts!__
|
|||||||
|
|
||||||
## Testing your changes
|
## Testing your changes
|
||||||
|
|
||||||
Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and
|
Obviously all changes to Catch's code should be tested. If you added new
|
||||||
showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements),
|
functionality, you should add tests covering and showcasing it. Even if you have
|
||||||
you should still test your changes.
|
only made changes to Catch internals (i.e. you implemented some performance
|
||||||
|
improvements), you should still test your changes.
|
||||||
|
|
||||||
This means 3 things
|
This means 2 things
|
||||||
|
|
||||||
* Compiling Catch's SelfTest project -- code that does not compile is evidently incorrect. Obviously, you are not expected to
|
* Compiling Catch's SelfTest project:
|
||||||
have access to all compilers and platforms Catch supports, Catch's CI pipeline will compile your code using supported compilers
|
```
|
||||||
once you open a PR.
|
$ cd Catch2
|
||||||
* Running the SelfTest binary. There should be no unexpected failures on simple run.
|
$ cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug
|
||||||
* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against
|
$ cmake --build debug-build
|
||||||
known good output. Catch's repository provides utility scripts `approvalTests.py` to help you with this. It needs to be passed
|
```
|
||||||
the SelfTest binary compiled with your changes, like so: `$ ./scripts/approvalTests.py clang-build/SelfTest`. The output should
|
because code that does not compile is evidently incorrect. Obviously,
|
||||||
be fairly self-explanatory.
|
you are not expected to have access to all the compilers and platforms
|
||||||
|
supported by Catch2, but you should at least smoke test your changes
|
||||||
|
on your platform. Our CI pipeline will check your PR against most of
|
||||||
|
the supported platforms, but it takes an hour to finish -- compiling
|
||||||
|
locally takes just a few minutes.
|
||||||
|
|
||||||
|
|
||||||
|
* Running the tests via CTest:
|
||||||
|
```
|
||||||
|
$ cd debug-build
|
||||||
|
$ ctest -j 2 --output-on-failure
|
||||||
|
```
|
||||||
|
If you added new tests, approval tests are very likely to fail. If they
|
||||||
|
do not, it means that your changes weren't run as part of them. This
|
||||||
|
_might_ be intentional, but usually is not.
|
||||||
|
|
||||||
|
The approval tests compare current output of the SelfTest binary in various
|
||||||
|
configurations against known good outputs. The reason it fails is,
|
||||||
|
_usually_, that you've added new tests but have not yet approved the changes
|
||||||
|
they introduce. This is done with the `scripts/approve.py` script, but
|
||||||
|
before you do so, you need to check that the introduced changes are indeed
|
||||||
|
intentional.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -83,6 +83,11 @@ be changed so that hidden tests are included in a run only if they
|
|||||||
positively match a testspec.
|
positively match a testspec.
|
||||||
|
|
||||||
|
|
||||||
|
### Console Colour API
|
||||||
|
|
||||||
|
The API for Catch2's console colour will be changed to take an extra
|
||||||
|
argument, the stream to which the colour code should be applied.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@@ -1,50 +1,133 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Data Generators
|
# Data Generators
|
||||||
|
|
||||||
_Generators are currently considered an experimental feature and their
|
|
||||||
API can change between versions freely._
|
|
||||||
|
|
||||||
Data generators (also known as _data driven/parametrized test cases_)
|
Data generators (also known as _data driven/parametrized test cases_)
|
||||||
let you reuse the same set of assertions across different input values.
|
let you reuse the same set of assertions across different input values.
|
||||||
In Catch2, this means that they respect the ordering and nesting
|
In Catch2, this means that they respect the ordering and nesting
|
||||||
of the `TEST_CASE` and `SECTION` macros.
|
of the `TEST_CASE` and `SECTION` macros, and their nested sections
|
||||||
|
are run once per each value in a generator.
|
||||||
How does combining generators and test cases work might be better
|
|
||||||
explained by an example:
|
|
||||||
|
|
||||||
|
This is best explained with an example:
|
||||||
```cpp
|
```cpp
|
||||||
TEST_CASE("Generators") {
|
TEST_CASE("Generators") {
|
||||||
auto i = GENERATE( range(1, 11) );
|
auto i = GENERATE(1, 2, 3);
|
||||||
|
SECTION("one") {
|
||||||
SECTION( "Some section" ) {
|
auto j = GENERATE( -3, -2, -1 );
|
||||||
auto j = GENERATE( range( 11, 21 ) );
|
REQUIRE(j < i);
|
||||||
REQUIRE(i < j);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
the assertion will be checked 100 times, because there are 10 possible
|
The assertion in this test case will be run 9 times, because there
|
||||||
values for `i` (1, 2, ..., 10) and for each of them, there are 10 possible
|
are 3 possible values for `i` (1, 2, and 3) and there are 3 possible
|
||||||
values for `j` (11, 12, ..., 20).
|
values for `j` (-3, -2, and -1).
|
||||||
|
|
||||||
|
|
||||||
|
There are 2 parts to generators in Catch2, the `GENERATE` macro together
|
||||||
|
with the already provided generators, and the `IGenerator<T>` interface
|
||||||
|
that allows users to implement their own generators.
|
||||||
|
|
||||||
|
## Provided generators
|
||||||
|
|
||||||
|
Catch2's provided generator functionality consists of three parts,
|
||||||
|
|
||||||
|
* `GENERATE` macro, that serves to integrate generator expression with
|
||||||
|
a test case,
|
||||||
|
* 2 fundamental generators
|
||||||
|
* `ValueGenerator<T>` -- contains only single element
|
||||||
|
* `ValuesGenerator<T>` -- contains multiple elements
|
||||||
|
* 5 generic generators that modify other generators
|
||||||
|
* `FilterGenerator<T, Predicate>` -- filters out elements from a generator
|
||||||
|
for which the predicate returns "false"
|
||||||
|
* `TakeGenerator<T>` -- takes first `n` elements from a generator
|
||||||
|
* `RepeatGenerator<T>` -- repeats output from a generator `n` times
|
||||||
|
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
|
||||||
|
on elements from a different generator
|
||||||
|
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
|
||||||
|
* 3 specific purpose generators
|
||||||
|
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
||||||
|
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
||||||
|
* `RangeGenerator<T>` -- generates all values inside a specific range
|
||||||
|
|
||||||
|
The generators also have associated helper functions that infer their
|
||||||
|
type, making their usage much nicer. These are
|
||||||
|
|
||||||
|
* `value(T&&)` for `ValueGenerator<T>`
|
||||||
|
* `values(std::initializer_list<T>)` for `ValuesGenerator<T>`
|
||||||
|
* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>`
|
||||||
|
* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
|
||||||
|
* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
|
||||||
|
* `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, T, Func>` (map `T` to `T`)
|
||||||
|
* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
|
||||||
|
* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>`
|
||||||
|
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
||||||
|
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
||||||
|
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
|
||||||
|
|
||||||
|
|
||||||
|
And can be used as shown in the example below to create a generator
|
||||||
|
that returns 100 odd random number:
|
||||||
|
|
||||||
You can also combine multiple generators by concatenation:
|
|
||||||
```cpp
|
```cpp
|
||||||
static int square(int x) { return x * x; }
|
TEST_CASE("Generating random ints", "[example][generator]") {
|
||||||
TEST_CASE("Generators 2") {
|
SECTION("Deducing functions") {
|
||||||
auto i = GENERATE(0, 1, -1, range(-20, -10), range(10, 20));
|
auto i = GENERATE(take(100, filter([](int i) { return i % 2 == 1; }, random(-100, 100))));
|
||||||
CAPTURE(i);
|
REQUIRE(i > -100);
|
||||||
REQUIRE(square(i) >= 0);
|
REQUIRE(i < 100);
|
||||||
|
REQUIRE(i % 2 == 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This will call `square` with arguments `0`, `1`, `-1`, `-20`, ..., `-11`,
|
|
||||||
`10`, ..., `19`.
|
|
||||||
|
|
||||||
----------
|
Apart from registering generators with Catch2, the `GENERATE` macro has
|
||||||
|
one more purpose, and that is to provide simple way of generating trivial
|
||||||
|
generators, as seen in the first example on this page, where we used it
|
||||||
|
as `auto i = GENERATE(1, 2, 3);`. This usage converted each of the three
|
||||||
|
literals into a single `ValueGenerator<int>` and then placed them all in
|
||||||
|
a special generator that concatenates other generators. It can also be
|
||||||
|
used with other generators as arguments, such as `auto i = GENERATE(0, 2,
|
||||||
|
take(100, random(300, 3000)));`. This is useful e.g. if you know that
|
||||||
|
specific inputs are problematic and want to test them separately/first.
|
||||||
|
|
||||||
|
**For safety reasons, you cannot use variables inside the `GENERATE` macro.**
|
||||||
|
|
||||||
|
You can also override the inferred type by using `as<type>` as the first
|
||||||
|
argument to the macro. This can be useful when dealing with string literals,
|
||||||
|
if you want them to come out as `std::string`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
TEST_CASE("type conversion", "[generators]") {
|
||||||
|
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");`
|
||||||
|
REQUIRE(str.size() > 0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generator interface
|
||||||
|
|
||||||
|
You can also implement your own generators, by deriving from the
|
||||||
|
`IGenerator<T>` interface:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename T>
|
||||||
|
struct IGenerator : GeneratorUntypedBase {
|
||||||
|
// via GeneratorUntypedBase:
|
||||||
|
// Attempts to move the generator to the next element.
|
||||||
|
// Returns true if successful (and thus has another element that can be read)
|
||||||
|
virtual bool next() = 0;
|
||||||
|
|
||||||
|
// Precondition:
|
||||||
|
// The generator is either freshly constructed or the last call to next() returned true
|
||||||
|
virtual T const& get() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
However, to be able to use your custom generator inside `GENERATE`, it
|
||||||
|
will need to be wrapped inside a `GeneratorWrapper<T>`.
|
||||||
|
`GeneratorWrapper<T>` is a value wrapper around a
|
||||||
|
`std::unique_ptr<IGenerator<T>>`.
|
||||||
|
|
||||||
|
For full example of implementing your own generator, look into Catch2's
|
||||||
|
examples, specifically
|
||||||
|
[Generators: Create your own generator](../examples/300-Gen-OwnGenerator.cpp).
|
||||||
|
|
||||||
Because of the experimental nature of the current Generator implementation,
|
|
||||||
we won't list all of the first-party generators in Catch2. Instead you
|
|
||||||
should look at our current usage tests in
|
|
||||||
[projects/SelfTest/UsageTests/Generators.tests.cpp](/projects/SelfTest/UsageTests/Generators.tests.cpp).
|
|
||||||
For implementing your own generators, you can look at their implementation in
|
|
||||||
[include/internal/catch_generators.hpp](/include/internal/catch_generators.hpp).
|
|
||||||
|
@@ -14,6 +14,10 @@
|
|||||||
- Report: [TeamCity reporter](../examples/207-Rpt-TeamCityReporter.cpp)
|
- Report: [TeamCity reporter](../examples/207-Rpt-TeamCityReporter.cpp)
|
||||||
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
|
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
|
||||||
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
|
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
|
||||||
|
- Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp)
|
||||||
|
- Generators: [Use map to convert types in GENERATE expression](../examples/301-Gen-MapTypeConversion.cpp)
|
||||||
|
- Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp)
|
||||||
|
|
||||||
|
|
||||||
## Planned
|
## Planned
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Logging macros
|
# Logging macros
|
||||||
|
|
||||||
Additional messages can be logged during a test case. Note that the messages are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
|
Additional messages can be logged during a test case. Note that the messages logged with `INFO` are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
TEST_CASE("Foo") {
|
TEST_CASE("Foo") {
|
||||||
@@ -28,6 +28,60 @@ The number is 1
|
|||||||
```
|
```
|
||||||
When the last `CHECK` fails in the "Bar" test case, then only one message will be printed: `Test case start`.
|
When the last `CHECK` fails in the "Bar" test case, then only one message will be printed: `Test case start`.
|
||||||
|
|
||||||
|
## Logging without local scope
|
||||||
|
|
||||||
|
`UNSCOPED_INFO` is similar to `INFO` with two key differences:
|
||||||
|
|
||||||
|
- Lifetime of an unscoped message is not tied to its own scope.
|
||||||
|
- An unscoped message can be reported by the first following assertion only, regardless of the result of that assertion.
|
||||||
|
|
||||||
|
In other words, lifetime of `UNSCOPED_INFO` is limited by the following assertion (or by the end of test case/section, whichever comes first) whereas lifetime of `INFO` is limited by its own scope.
|
||||||
|
|
||||||
|
These differences make this macro useful for reporting information from helper functions or inner scopes. An example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void print_some_info() {
|
||||||
|
UNSCOPED_INFO("Info from helper");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Baz") {
|
||||||
|
print_some_info();
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
UNSCOPED_INFO("The number is " << i);
|
||||||
|
}
|
||||||
|
CHECK(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Qux") {
|
||||||
|
INFO("First info");
|
||||||
|
UNSCOPED_INFO("First unscoped info");
|
||||||
|
CHECK(false);
|
||||||
|
|
||||||
|
INFO("Second info");
|
||||||
|
UNSCOPED_INFO("Second unscoped info");
|
||||||
|
CHECK(false);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
"Baz" test case prints:
|
||||||
|
```
|
||||||
|
Info from helper
|
||||||
|
The number is 0
|
||||||
|
The number is 1
|
||||||
|
```
|
||||||
|
|
||||||
|
With "Qux" test case, two messages will be printed when the first `CHECK` fails:
|
||||||
|
```
|
||||||
|
First info
|
||||||
|
First unscoped info
|
||||||
|
```
|
||||||
|
|
||||||
|
"First unscoped info" message will be cleared after the first `CHECK`, while "First info" message will persist until the end of the test case. Therefore, when the second `CHECK` fails, three messages will be printed:
|
||||||
|
```
|
||||||
|
First info
|
||||||
|
Second info
|
||||||
|
Second unscoped info
|
||||||
|
```
|
||||||
|
|
||||||
## Streaming macros
|
## Streaming macros
|
||||||
|
|
||||||
@@ -43,7 +97,14 @@ These macros come in three forms:
|
|||||||
|
|
||||||
**INFO(** _message expression_ **)**
|
**INFO(** _message expression_ **)**
|
||||||
|
|
||||||
The message is logged to a buffer, but only reported with the next assertion that is logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
|
The message is logged to a buffer, but only reported with next assertions that are logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
|
||||||
|
|
||||||
|
_Note that in Catch2 2.x.x `INFO` can be used without a trailing semicolon as there is a trailing semicolon inside macro.
|
||||||
|
This semicolon will be removed with next major version. It is highly advised to use a trailing semicolon after `INFO` macro._
|
||||||
|
|
||||||
|
**UNSCOPED_INFO(** _message expression_ **)**
|
||||||
|
|
||||||
|
Similar to `INFO`, but messages are not limited to their own scope: They are removed from the buffer after each assertion, section or test case, whichever comes first.
|
||||||
|
|
||||||
**WARN(** _message expression_ **)**
|
**WARN(** _message expression_ **)**
|
||||||
|
|
||||||
|
@@ -18,25 +18,28 @@ Listing a project here does not imply endorsement and the plan is to keep these
|
|||||||
## Libraries & Frameworks
|
## Libraries & Frameworks
|
||||||
|
|
||||||
### [Azmq](https://github.com/zeromq/azmq)
|
### [Azmq](https://github.com/zeromq/azmq)
|
||||||
Boost Asio style bindings for ZeroMQ
|
Boost Asio style bindings for ZeroMQ.
|
||||||
|
|
||||||
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
||||||
The core part of the Chakra JavaScript engine that powers Microsoft Edge
|
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
|
||||||
|
|
||||||
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
|
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
|
||||||
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
|
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques.
|
||||||
|
|
||||||
### [Clara](https://github.com/philsquared/Clara)
|
### [Clara](https://github.com/philsquared/Clara)
|
||||||
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
|
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
|
||||||
|
|
||||||
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
|
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
|
||||||
The next-generation core storage and query engine for Couchbase Lite
|
The next-generation core storage and query engine for Couchbase Lite.
|
||||||
|
|
||||||
|
### [cppcodec](https://github.com/tplgy/cppcodec)
|
||||||
|
Header-only C++11 library to encode/decode base64, base64url, base32, base32hex and hex (a.k.a. base16) as specified in RFC 4648, plus Crockford's base32.
|
||||||
|
|
||||||
### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
|
### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
|
||||||
A High-performance Cluster Computing Engine
|
A High-performance Cluster Computing Engine.
|
||||||
|
|
||||||
### [forest](https://github.com/xorz57/forest)
|
### [forest](https://github.com/xorz57/forest)
|
||||||
Template Library of Tree Data Structures
|
Template Library of Tree Data Structures.
|
||||||
|
|
||||||
### [Fuxedo](https://github.com/fuxedo/fuxedo)
|
### [Fuxedo](https://github.com/fuxedo/fuxedo)
|
||||||
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
||||||
@@ -60,25 +63,25 @@ A small C++ library wrapper for the native C ODBC API.
|
|||||||
A header-only framework for benchmarking small snippets of C++ code.
|
A header-only framework for benchmarking small snippets of C++ code.
|
||||||
|
|
||||||
### [SOCI](https://github.com/SOCI/soci)
|
### [SOCI](https://github.com/SOCI/soci)
|
||||||
The C++ Database Access Library
|
The C++ Database Access Library.
|
||||||
|
|
||||||
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
|
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
|
||||||
A polymorphic value-type for C++
|
A polymorphic value-type for C++.
|
||||||
|
|
||||||
### [Ppconsul](https://github.com/oliora/ppconsul)
|
### [Ppconsul](https://github.com/oliora/ppconsul)
|
||||||
A C++ client library for Consul. Consul is a distributed tool for discovering and configuring services in your infrastructure
|
A C++ client library for Consul. Consul is a distributed tool for discovering and configuring services in your infrastructure.
|
||||||
|
|
||||||
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
|
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
|
||||||
A library of algorithms for values-distributed-in-time
|
A library of algorithms for values-distributed-in-time.
|
||||||
|
|
||||||
### [thor](https://github.com/xorz57/thor)
|
### [thor](https://github.com/xorz57/thor)
|
||||||
Wrapper Library for CUDA
|
Wrapper Library for CUDA.
|
||||||
|
|
||||||
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
|
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
|
||||||
A small, single-header-only, library for wrapping and composing columns of text
|
A small, single-header-only, library for wrapping and composing columns of text.
|
||||||
|
|
||||||
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
|
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
|
||||||
A thread safe header only mocking framework for C++14
|
A thread-safe header-only mocking framework for C++14.
|
||||||
|
|
||||||
### [args](https://github.com/Taywee/args)
|
### [args](https://github.com/Taywee/args)
|
||||||
A simple header-only C++ argument parser library.
|
A simple header-only C++ argument parser library.
|
||||||
@@ -92,7 +95,7 @@ ArangoDB is a native multi-model database with flexible data models for document
|
|||||||
Minimal, open-source and cross-platform audio tool for live music production.
|
Minimal, open-source and cross-platform audio tool for live music production.
|
||||||
|
|
||||||
### [MAME](https://github.com/mamedev/mame)
|
### [MAME](https://github.com/mamedev/mame)
|
||||||
MAME originally stood for Multiple Arcade Machine Emulator
|
MAME originally stood for Multiple Arcade Machine Emulator.
|
||||||
|
|
||||||
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
|
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
|
||||||
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
|
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
|
||||||
@@ -101,7 +104,7 @@ Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
|
|||||||
SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
|
SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
|
||||||
|
|
||||||
### [Standardese](https://github.com/foonathan/standardese)
|
### [Standardese](https://github.com/foonathan/standardese)
|
||||||
Standardese aims to be a nextgen Doxygen
|
Standardese aims to be a nextgen Doxygen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
# Release notes
|
# Release notes
|
||||||
**Contents**<br>
|
**Contents**<br>
|
||||||
|
[2.7.0](#270)<br>
|
||||||
|
[2.6.1](#261)<br>
|
||||||
|
[2.6.0](#260)<br>
|
||||||
[2.5.0](#250)<br>
|
[2.5.0](#250)<br>
|
||||||
[2.4.2](#242)<br>
|
[2.4.2](#242)<br>
|
||||||
[2.4.1](#241)<br>
|
[2.4.1](#241)<br>
|
||||||
@@ -18,6 +21,96 @@
|
|||||||
[Older versions](#older-versions)<br>
|
[Older versions](#older-versions)<br>
|
||||||
[Even Older versions](#even-older-versions)<br>
|
[Even Older versions](#even-older-versions)<br>
|
||||||
|
|
||||||
|
## 2.7.0
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* `TEMPLATE_PRODUCT_TEST_CASE` now uses the resulting type in the name, instead of the serial number (#1544)
|
||||||
|
* Catch2's single header is now strictly ASCII (#1542)
|
||||||
|
* Added generator for random integral/floating point types
|
||||||
|
* The types are inferred within the `random` helper
|
||||||
|
* Added back RangeGenerator (#1526)
|
||||||
|
* RangeGenerator returns elements within a certain range
|
||||||
|
* Added ChunkGenerator generic transform (#1538)
|
||||||
|
* A ChunkGenerator returns the elements from different generator in chunks of n elements
|
||||||
|
* Added `UNSCOPED_INFO` (#415, #983, #1522)
|
||||||
|
* This is a variant of `INFO` that lives until next assertion/end of the test case.
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* All calls to C stdlib functions are now `std::` qualified (#1541)
|
||||||
|
* Code brought in from Clara was also updated.
|
||||||
|
* Running tests will no longer open the specified output file twice (#1545)
|
||||||
|
* This would cause trouble when the file was not a file, but rather a named pipe
|
||||||
|
* Fixes the CLion/Resharper integration with Catch
|
||||||
|
* Fixed `-Wunreachable-code` occuring with (old) ccache+cmake+clang combination (#1540)
|
||||||
|
* Fixed `-Wdefaulted-function-deleted` warning with Clang 8 (#1537)
|
||||||
|
* Catch2's type traits and helpers are now properly namespaced inside `Catch::` (#1548)
|
||||||
|
* Fixed std{out,err} redirection for failing test (#1514, #1525)
|
||||||
|
* Somehow, this bug has been present for well over a year before it was reported
|
||||||
|
|
||||||
|
|
||||||
|
### Contrib
|
||||||
|
* `ParseAndAddCatchTests` now properly escapes commas in the test name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2.6.1
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* The JUnit reporter now also reports random seed (#1520, #1521)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* The TAP reporter now formats comments with test name properly (#1529)
|
||||||
|
* `CATCH_REQUIRE_THROWS`'s internals were unified with `REQUIRE_THROWS` (#1536)
|
||||||
|
* This fixes a potential `-Wunused-value` warning when used
|
||||||
|
* Fixed a potential segfault when using any of the `--list-*` options (#1533, #1534)
|
||||||
|
|
||||||
|
|
||||||
|
## 2.6.0
|
||||||
|
|
||||||
|
**With this release the data generator feature is now fully supported.**
|
||||||
|
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Added `TEMPLATE_PRODUCT_TEST_CASE` (#1454, #1468)
|
||||||
|
* This allows you to easily test various type combinations, see documentation for details
|
||||||
|
* The error message for `&&` and `||` inside assertions has been improved (#1273, #1480)
|
||||||
|
* The error message for chained comparisons inside assertions has been improved (#1481)
|
||||||
|
* Added `StringMaker` specialization for `std::optional` (#1510)
|
||||||
|
* The generator interface has been redone once again (#1516)
|
||||||
|
* It is no longer considered experimental and is fully supported
|
||||||
|
* The new interface supports "Input" generators
|
||||||
|
* The generator documentation has been fully updated
|
||||||
|
* We also added 2 generator examples
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Fixed `-Wredundant-move` on newer Clang (#1474)
|
||||||
|
* Removed unreachable mentions `std::current_exception`, `std::rethrow_exception` in no-exceptions mode (#1462)
|
||||||
|
* This should fix compilation with IAR
|
||||||
|
* Fixed missing `<type_traits>` include (#1494)
|
||||||
|
* Fixed various static analysis warnings
|
||||||
|
* Unrestored stream state in `XmlWriter` (#1489)
|
||||||
|
* Potential division by zero in `estimateClockResolution` (#1490)
|
||||||
|
* Uninitialized member in `RunContext` (#1491)
|
||||||
|
* `SourceLineInfo` move ops are now marked `noexcept`
|
||||||
|
* `CATCH_BREAK_INTO_DEBUGGER` is now always a function
|
||||||
|
* Fix double run of a test case if user asks for a specific section (#1394, #1492)
|
||||||
|
* ANSI colour code output now respects `-o` flag and writes to the file as well (#1502)
|
||||||
|
* Fixed detection of `std::variant` support for compilers other than Clang (#1511)
|
||||||
|
|
||||||
|
|
||||||
|
### Contrib
|
||||||
|
* `ParseAndAddCatchTests` has learned how to use `DISABLED` CTest property (#1452)
|
||||||
|
* `ParseAndAddCatchTests` now works when there is a whitspace before the test name (#1493)
|
||||||
|
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
* We added new issue templates for reporting issues on GitHub
|
||||||
|
* `contributing.md` has been updated to reflect the current test status (#1484)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 2.5.0
|
## 2.5.0
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
@@ -48,3 +48,25 @@ dependent on a specific version of the single-include header.
|
|||||||
|
|
||||||
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
|
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
|
||||||
signed.
|
signed.
|
||||||
|
|
||||||
|
#### Signing a tag
|
||||||
|
|
||||||
|
To create a signed tag, use `git tag -s <VERSION>`, where `<VERSION>`
|
||||||
|
is the version being released, e.g. `git tag -s v2.6.0`.
|
||||||
|
|
||||||
|
Use the version name as the short message and the release notes as
|
||||||
|
the body (long) message.
|
||||||
|
|
||||||
|
#### Signing the headers
|
||||||
|
|
||||||
|
This will create ASCII-armored signatures for the headers that are
|
||||||
|
uploaded to the GitHub release:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp
|
||||||
|
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
|
||||||
|
$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
|
||||||
|
$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
|
||||||
|
```
|
||||||
|
|
||||||
|
_GPG does not support signing multiple files in single invocation._
|
||||||
|
@@ -95,7 +95,8 @@ Other than the additional prefixes and the formatting in the console reporter th
|
|||||||
## Type parametrised test cases
|
## Type parametrised test cases
|
||||||
|
|
||||||
In addition to `TEST_CASE`s, Catch2 also supports test cases parametrised
|
In addition to `TEST_CASE`s, Catch2 also supports test cases parametrised
|
||||||
by type, in the form of `TEMPLATE_TEST_CASE`.
|
by types, in the form of `TEMPLATE_TEST_CASE` and
|
||||||
|
`TEMPLATE_PRODUCT_TEST_CASE`.
|
||||||
|
|
||||||
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
|
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
|
||||||
|
|
||||||
@@ -147,9 +148,48 @@ 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_) **)**
|
||||||
|
|
||||||
|
_template-type1_ through _template-typen_ is list of template template
|
||||||
|
types which should be combined with each of _template-arg1_ through
|
||||||
|
_template-argm_, resulting in _n * m_ test cases. Inside the test case,
|
||||||
|
the resulting type is available under the name of `TestType`.
|
||||||
|
|
||||||
|
To specify more than 1 type as a single _template-type_ or _template-arg_,
|
||||||
|
you must enclose the types in an additional set of parentheses, e.g.
|
||||||
|
`((int, float), (char, double))` specifies 2 template-args, each
|
||||||
|
consisting of 2 concrete types (`int`, `float` and `char`, `double`
|
||||||
|
respectively). You can also omit the outer set of parentheses if you
|
||||||
|
specify only one type as the full set of either the _template-types_,
|
||||||
|
or the _template-args_.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```cpp
|
||||||
|
template< typename T>
|
||||||
|
struct Foo {
|
||||||
|
size_t size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]", (std::vector, Foo), (int, float)) {
|
||||||
|
TestType x;
|
||||||
|
REQUIRE(x.size() == 0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also have different arities in the _template-arg_ packs:
|
||||||
|
```cpp
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
|
||||||
|
TestType x;
|
||||||
|
REQUIRE(std::tuple_size<TestType>::value >= 1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
_While there is an upper limit on the number of types you can specify
|
_While there is an upper limit on the number of types you can specify
|
||||||
in single `TEMPLATE_TEST_CASE`, the limit is very high and should not
|
in single `TEMPLATE_TEST_CASE` or `TEMPLATE_PRODUCT_TEST_CASE`, the limit
|
||||||
be encountered in practice._
|
is very high and should not be encountered in practice._
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -31,16 +31,22 @@ class UniqueTestsFixture {
|
|||||||
The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter.
|
The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter.
|
||||||
|
|
||||||
|
|
||||||
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD` that can be used together
|
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD` and
|
||||||
with templated fixtures to perform tests for multiple different types.
|
`TEMPLATE_PRODUCT_TEST_CASE_METHOD` that can be used together
|
||||||
However, unlike `TEST_CASE_METHOD`, `TEMPLATE_TEST_CASE_METHOD` requires
|
with templated fixtures and templated template fixtures to perform
|
||||||
the tag specification to be non-empty, as it is followed by further macros
|
tests for multiple different types. Unlike `TEST_CASE_METHOD`,
|
||||||
arguments.
|
`TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD` do
|
||||||
|
require the tag specification to be non-empty, as it is followed by
|
||||||
|
further macro arguments.
|
||||||
|
|
||||||
Also note that, because of limitations of the C++ preprocessor, if you
|
Also note that, because of limitations of the C++ preprocessor, if you
|
||||||
want to specify a type with multiple template parameters, you need to
|
want to specify a type with multiple template parameters, you need to
|
||||||
enclose it in parentheses, e.g. `std::map<int, std::string>` needs to be
|
enclose it in parentheses, e.g. `std::map<int, std::string>` needs to be
|
||||||
passed as `(std::map<int, std::string>)`.
|
passed as `(std::map<int, std::string>)`.
|
||||||
|
In the case of `TEMPLATE_PRODUCT_TEST_CASE_METHOD`, if a member of the
|
||||||
|
type list should consist of more than single type, it needs to be enclosed
|
||||||
|
in another pair of parentheses, e.g. `(std::map, std::pair)` and
|
||||||
|
`((int, float), (char, double))`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```cpp
|
```cpp
|
||||||
@@ -54,11 +60,29 @@ struct Template_Fixture {
|
|||||||
TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
|
TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
|
||||||
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
|
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Template_Template_Fixture {
|
||||||
|
Template_Template_Fixture() {}
|
||||||
|
|
||||||
|
T m_a;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Foo_class {
|
||||||
|
size_t size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Template_Fixture, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test succeeds", "[class][template]", (Foo_class, std::vector), int) {
|
||||||
|
REQUIRE( Template_Template_Fixture<TestType>::m_a.size() == 0 );
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
_While there is an upper limit on the number of types you can specify
|
_While there is an upper limit on the number of types you can specify
|
||||||
in single `TEMPLATE_TEST_CASE`, the limit is very high and should not
|
in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
|
||||||
be encountered in practice._
|
the limit is very high and should not be encountered in practice._
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -260,8 +260,9 @@ Do not write your tests in header files!
|
|||||||
## Type parametrised test cases
|
## Type parametrised test cases
|
||||||
|
|
||||||
Test cases in Catch2 can be also parametrised by type, via the
|
Test cases in Catch2 can be also parametrised by type, via the
|
||||||
`TEMPLATE_TEST_CASE` macro, which behaves in the same way the `TEST_CASE`
|
`TEMPLATE_TEST_CASE` and `TEMPLATE_PRODUCT_TEST_CASE` macros,
|
||||||
macro, but is run for every type.
|
which behave in the same way the `TEST_CASE` macro, but are run for
|
||||||
|
every type or type combination.
|
||||||
|
|
||||||
For more details, see our documentation on [test cases and
|
For more details, see our documentation on [test cases and
|
||||||
sections](test-cases-and-sections.md#type-parametrised-test-cases).
|
sections](test-cases-and-sections.md#type-parametrised-test-cases).
|
||||||
|
@@ -387,16 +387,16 @@ TEST_CASE( "2: Testcase with sections", "[tag-A][tag-B]" ) {
|
|||||||
REQUIRE( i == 42 );
|
REQUIRE( i == 42 );
|
||||||
|
|
||||||
SECTION("Section 1") {
|
SECTION("Section 1") {
|
||||||
INFO("Section 1")
|
INFO("Section 1");
|
||||||
i = 7;
|
i = 7;
|
||||||
SECTION("Section 1.1") {
|
SECTION("Section 1.1") {
|
||||||
INFO("Section 1.1")
|
INFO("Section 1.1");
|
||||||
REQUIRE( i == 42 );
|
REQUIRE( i == 42 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Section 2") {
|
SECTION("Section 2") {
|
||||||
INFO("Section 2")
|
INFO("Section 2");
|
||||||
REQUIRE( i == 42 );
|
REQUIRE( i == 42 );
|
||||||
}
|
}
|
||||||
WARN("At end of test case");
|
WARN("At end of test case");
|
||||||
|
59
examples/300-Gen-OwnGenerator.cpp
Normal file
59
examples/300-Gen-OwnGenerator.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// 300-Gen-OwnGenerator.cpp
|
||||||
|
// Shows how to define a custom generator.
|
||||||
|
|
||||||
|
// Specifically we will implement a random number generator for integers
|
||||||
|
// It will have infinite capacity and settable lower/upper bound
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
// This class shows how to implement a simple generator for Catch tests
|
||||||
|
class RandomIntGenerator : public Catch::Generators::IGenerator<int> {
|
||||||
|
std::minstd_rand m_rand;
|
||||||
|
std::uniform_int_distribution<> m_dist;
|
||||||
|
int current_number;
|
||||||
|
public:
|
||||||
|
|
||||||
|
RandomIntGenerator(int low, int high):
|
||||||
|
m_rand(std::random_device{}()),
|
||||||
|
m_dist(low, high)
|
||||||
|
{
|
||||||
|
static_cast<void>(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
int const& get() const override;
|
||||||
|
bool next() override {
|
||||||
|
current_number = m_dist(m_rand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Avoids -Wweak-vtables
|
||||||
|
int const& RandomIntGenerator::get() const {
|
||||||
|
return current_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This helper function provides a nicer UX when instantiating the generator
|
||||||
|
// Notice that it returns an instance of GeneratorWrapper<int>, which
|
||||||
|
// is a value-wrapper around std::unique_ptr<IGenerator<int>>.
|
||||||
|
Catch::Generators::GeneratorWrapper<int> random(int low, int high) {
|
||||||
|
return Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new RandomIntGenerator(low, high)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The two sections in this test case are equivalent, but the first one
|
||||||
|
// is much more readable/nicer to use
|
||||||
|
TEST_CASE("Generating random ints", "[example][generator]") {
|
||||||
|
SECTION("Nice UX") {
|
||||||
|
auto i = GENERATE(take(100, random(-100, 100)));
|
||||||
|
REQUIRE(i >= -100);
|
||||||
|
REQUIRE(i <= 100);
|
||||||
|
}
|
||||||
|
SECTION("Creating the random generator directly") {
|
||||||
|
auto i = GENERATE(take(100, GeneratorWrapper<int>(std::unique_ptr<IGenerator<int>>(new RandomIntGenerator(-100, 100)))));
|
||||||
|
REQUIRE(i >= -100);
|
||||||
|
REQUIRE(i <= 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compiling and running this file will result in 400 successful assertions
|
54
examples/301-Gen-MapTypeConversion.cpp
Normal file
54
examples/301-Gen-MapTypeConversion.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// 301-Gen-MapTypeConversion.cpp
|
||||||
|
// Shows how to use map to modify generator's return type.
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// Returns a line from a stream. You could have it e.g. read lines from
|
||||||
|
// a file, but to avoid problems with paths in examples, we will use
|
||||||
|
// a fixed stringstream.
|
||||||
|
class LineGenerator : public Catch::Generators::IGenerator<std::string> {
|
||||||
|
std::string m_line;
|
||||||
|
std::stringstream m_stream;
|
||||||
|
public:
|
||||||
|
LineGenerator() {
|
||||||
|
m_stream.str("1\n2\n3\n4\n");
|
||||||
|
if (!next()) {
|
||||||
|
throw Catch::GeneratorException("Couldn't read a single line");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string const& get() const override {
|
||||||
|
return m_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next() override {
|
||||||
|
return !!std::getline(m_stream, m_line);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This helper function provides a nicer UX when instantiating the generator
|
||||||
|
// Notice that it returns an instance of GeneratorWrapper<std::string>, which
|
||||||
|
// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
|
||||||
|
Catch::Generators::GeneratorWrapper<std::string> lines(std::string /* ignored for example */) {
|
||||||
|
return Catch::Generators::GeneratorWrapper<std::string>(
|
||||||
|
std::unique_ptr<Catch::Generators::IGenerator<std::string>>(
|
||||||
|
new LineGenerator()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("filter can convert types inside the generator expression", "[example][generator]") {
|
||||||
|
auto num = GENERATE(map<int>([](std::string const& line) { return std::stoi(line); },
|
||||||
|
lines("fake-file")));
|
||||||
|
|
||||||
|
REQUIRE(num > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compiling and running this file will result in 4 successful assertions
|
72
examples/310-Gen-VariablesInGenerators.cpp
Normal file
72
examples/310-Gen-VariablesInGenerators.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// 310-Gen-VariablesInGenerator.cpp
|
||||||
|
// Shows how to use variables when creating generators.
|
||||||
|
|
||||||
|
// Note that using variables inside generators is dangerous and should
|
||||||
|
// be done only if you know what you are doing, because the generators
|
||||||
|
// _WILL_ outlive the variables -- thus they should be either captured
|
||||||
|
// by value directly, or copied by the generators during construction.
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
// Lets start by implementing a parametrizable double generator
|
||||||
|
class RandomDoubleGenerator : public Catch::Generators::IGenerator<double> {
|
||||||
|
std::minstd_rand m_rand;
|
||||||
|
std::uniform_real_distribution<> m_dist;
|
||||||
|
double current_number;
|
||||||
|
public:
|
||||||
|
|
||||||
|
RandomDoubleGenerator(double low, double high):
|
||||||
|
m_rand(std::random_device{}()),
|
||||||
|
m_dist(low, high)
|
||||||
|
{
|
||||||
|
static_cast<void>(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
double const& get() const override;
|
||||||
|
bool next() override {
|
||||||
|
current_number = m_dist(m_rand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Avoids -Wweak-vtables
|
||||||
|
double const& RandomDoubleGenerator::get() const {
|
||||||
|
return current_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Also provide a nice shortcut for creating the generator
|
||||||
|
Catch::Generators::GeneratorWrapper<double> random(double low, double high) {
|
||||||
|
return Catch::Generators::GeneratorWrapper<double>(std::unique_ptr<Catch::Generators::IGenerator<double>>(new RandomDoubleGenerator(low, high)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Generate random doubles across different ranges",
|
||||||
|
"[generator][example][advanced]") {
|
||||||
|
// Workaround for old libstdc++
|
||||||
|
using record = std::tuple<double, double>;
|
||||||
|
// Set up 3 ranges to generate numbers from
|
||||||
|
auto r = GENERATE(table<double, double>({
|
||||||
|
record{3, 4},
|
||||||
|
record{-4, -3},
|
||||||
|
record{10, 1000}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// This will not compile (intentionally), because it accesses a variable
|
||||||
|
// auto number = GENERATE(take(50, random(r.first, r.second)));
|
||||||
|
|
||||||
|
// We have to manually register the generators instead
|
||||||
|
// Notice that we are using value capture in the lambda, to avoid lifetime issues
|
||||||
|
auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
|
||||||
|
[=]{
|
||||||
|
using namespace Catch::Generators;
|
||||||
|
return makeGenerators(take(50, random(std::get<0>(r), std::get<1>(r))));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
REQUIRE(std::abs(number) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compiling and running this file will result in 150 successful assertions
|
||||||
|
|
@@ -44,6 +44,9 @@ set( SOURCES_IDIOMATIC_TESTS
|
|||||||
110-Fix-ClassFixture.cpp
|
110-Fix-ClassFixture.cpp
|
||||||
120-Bdd-ScenarioGivenWhenThen.cpp
|
120-Bdd-ScenarioGivenWhenThen.cpp
|
||||||
210-Evt-EventListeners.cpp
|
210-Evt-EventListeners.cpp
|
||||||
|
300-Gen-OwnGenerator.cpp
|
||||||
|
301-Gen-MapTypeConversion.cpp
|
||||||
|
310-Gen-VariablesInGenerators.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# main-s for reporter-specific test sources:
|
# main-s for reporter-specific test sources:
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||||
|
|
||||||
#define CATCH_VERSION_MAJOR 2
|
#define CATCH_VERSION_MAJOR 2
|
||||||
#define CATCH_VERSION_MINOR 5
|
#define CATCH_VERSION_MINOR 7
|
||||||
#define CATCH_VERSION_PATCH 0
|
#define CATCH_VERSION_PATCH 0
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@@ -63,6 +63,8 @@
|
|||||||
#include "internal/catch_capture_matchers.h"
|
#include "internal/catch_capture_matchers.h"
|
||||||
#endif
|
#endif
|
||||||
#include "internal/catch_generators.hpp"
|
#include "internal/catch_generators.hpp"
|
||||||
|
#include "internal/catch_generators_generic.hpp"
|
||||||
|
#include "internal/catch_generators_specific.hpp"
|
||||||
|
|
||||||
// These files are included here so the single_include script doesn't put them
|
// These files are included here so the single_include script doesn't put them
|
||||||
// in the conditionally compiled sections
|
// in the conditionally compiled sections
|
||||||
@@ -101,7 +103,7 @@
|
|||||||
#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
||||||
#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
|
#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
|
||||||
|
|
||||||
#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
|
#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
||||||
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
|
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
|
||||||
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
|
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
|
||||||
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
||||||
@@ -115,7 +117,7 @@
|
|||||||
#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||||
#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
|
#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
|
||||||
|
|
||||||
#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
|
#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||||
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
|
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
|
||||||
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
|
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
|
||||||
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
||||||
@@ -148,9 +150,13 @@
|
|||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
||||||
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
#else
|
#else
|
||||||
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
|
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
|
||||||
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
|
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -209,6 +215,7 @@
|
|||||||
#endif // CATCH_CONFIG_DISABLE_MATCHERS
|
#endif // CATCH_CONFIG_DISABLE_MATCHERS
|
||||||
|
|
||||||
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
|
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
|
||||||
|
#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
|
||||||
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
|
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
|
||||||
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
|
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
|
||||||
|
|
||||||
@@ -226,9 +233,13 @@
|
|||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
||||||
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
#else
|
#else
|
||||||
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
|
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
|
||||||
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
|
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -313,9 +324,13 @@ using Catch::Detail::Approx;
|
|||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
|
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
|
||||||
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
|
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
#else
|
#else
|
||||||
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
|
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
|
||||||
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
|
#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
||||||
|
#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// "BDD-style" convenience wrappers
|
// "BDD-style" convenience wrappers
|
||||||
@@ -384,9 +399,13 @@ using Catch::Detail::Approx;
|
|||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
|
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
|
||||||
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
|
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
#else
|
#else
|
||||||
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
|
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
|
||||||
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
|
#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
|
||||||
|
#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define STATIC_REQUIRE( ... ) (void)(0)
|
#define STATIC_REQUIRE( ... ) (void)(0)
|
||||||
|
4
include/external/clara.hpp
vendored
4
include/external/clara.hpp
vendored
@@ -370,7 +370,7 @@ inline auto Column::operator + (Column const& other) -> Columns {
|
|||||||
// ----------- end of #include from clara_textflow.hpp -----------
|
// ----------- end of #include from clara_textflow.hpp -----------
|
||||||
// ........... back in clara.hpp
|
// ........... back in clara.hpp
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -664,7 +664,7 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
|
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
|
||||||
std::string srcLC = source;
|
std::string srcLC = source;
|
||||||
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
|
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );
|
||||||
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
|
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
|
||||||
target = true;
|
target = true;
|
||||||
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
|
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
|
||||||
|
@@ -48,7 +48,7 @@
|
|||||||
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
||||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
|
} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
|
||||||
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
|
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -130,6 +130,10 @@
|
|||||||
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
||||||
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
|
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
|
||||||
|
Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Although this is matcher-based, it can be used with just a string
|
// Although this is matcher-based, it can be used with just a string
|
||||||
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
|
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
|
||||||
|
@@ -53,9 +53,9 @@ namespace Catch {
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
SourceLineInfo( SourceLineInfo const& other ) = default;
|
SourceLineInfo( SourceLineInfo const& other ) = default;
|
||||||
SourceLineInfo( SourceLineInfo && ) = default;
|
|
||||||
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
|
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
|
||||||
SourceLineInfo& operator = ( SourceLineInfo && ) = default;
|
SourceLineInfo( SourceLineInfo&& ) noexcept = default;
|
||||||
|
SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
|
||||||
|
|
||||||
bool empty() const noexcept;
|
bool empty() const noexcept;
|
||||||
bool operator == ( SourceLineInfo const& other ) const noexcept;
|
bool operator == ( SourceLineInfo const& other ) const noexcept;
|
||||||
|
@@ -183,6 +183,14 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Check if optional is available and usable
|
||||||
|
#if defined(__has_include)
|
||||||
|
# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
|
# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
||||||
|
# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
|
#endif // __has_include
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Check if variant is available and usable
|
// Check if variant is available and usable
|
||||||
#if defined(__has_include)
|
#if defined(__has_include)
|
||||||
@@ -196,6 +204,8 @@
|
|||||||
# else
|
# else
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||||
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||||
|
# else
|
||||||
|
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||||
# endif // defined(__clang__) && (__clang_major__ < 8)
|
# endif // defined(__clang__) && (__clang_major__ < 8)
|
||||||
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
#endif // __has_include
|
#endif // __has_include
|
||||||
@@ -220,6 +230,10 @@
|
|||||||
# define CATCH_CONFIG_CPP11_TO_STRING
|
# define CATCH_CONFIG_CPP11_TO_STRING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||||
|
# define CATCH_CONFIG_CPP17_OPTIONAL
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||||
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
|
@@ -160,7 +160,8 @@ namespace {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void setColour( const char* _escapeCode ) {
|
void setColour( const char* _escapeCode ) {
|
||||||
Catch::cout() << '\033' << _escapeCode;
|
getCurrentContext().getConfig()->stream()
|
||||||
|
<< '\033' << _escapeCode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -38,12 +38,9 @@ namespace Catch {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CATCH_TRAP
|
#ifdef CATCH_TRAP
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
#define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
|
||||||
#else
|
#else
|
||||||
namespace Catch {
|
#define CATCH_BREAK_INTO_DEBUGGER() []{}()
|
||||||
inline void doNothing() {}
|
|
||||||
}
|
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
|
#include "catch_meta.hpp"
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
|
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
|
||||||
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
|
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
|
||||||
#pragma warning(disable:4180) // qualifier applied to function type has no meaning
|
#pragma warning(disable:4180) // qualifier applied to function type has no meaning
|
||||||
|
#pragma warning(disable:4800) // Forcing result to true or false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@@ -62,6 +64,62 @@ namespace Catch {
|
|||||||
m_op( op ),
|
m_op( op ),
|
||||||
m_rhs( rhs )
|
m_rhs( rhs )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<T>::value,
|
||||||
|
"chained comparisons are not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename LhsT>
|
template<typename LhsT>
|
||||||
@@ -74,7 +132,7 @@ namespace Catch {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit UnaryExpr( LhsT lhs )
|
explicit UnaryExpr( LhsT lhs )
|
||||||
: ITransientExpression{ false, lhs ? true : false },
|
: ITransientExpression{ false, static_cast<bool>(lhs) },
|
||||||
m_lhs( lhs )
|
m_lhs( lhs )
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@@ -143,6 +201,20 @@ namespace Catch {
|
|||||||
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
|
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename RhsT>
|
||||||
|
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<RhsT>::value,
|
||||||
|
"operator&& is not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RhsT>
|
||||||
|
auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
|
static_assert(always_false<RhsT>::value,
|
||||||
|
"operator|| is not supported inside assertions, "
|
||||||
|
"wrap the expression inside parentheses, or decompose it");
|
||||||
|
}
|
||||||
|
|
||||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||||
return UnaryExpr<LhsT>{ m_lhs };
|
return UnaryExpr<LhsT>{ m_lhs };
|
||||||
}
|
}
|
||||||
|
@@ -67,17 +67,23 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
||||||
|
if (m_translators.empty()) {
|
||||||
|
std::rethrow_exception(std::current_exception());
|
||||||
|
} else {
|
||||||
|
return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else // ^^ Exceptions are enabled // Exceptions are disabled vv
|
#else // ^^ Exceptions are enabled // Exceptions are disabled vv
|
||||||
std::string ExceptionTranslatorRegistry::translateActiveException() const {
|
std::string ExceptionTranslatorRegistry::translateActiveException() const {
|
||||||
CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
|
CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
||||||
|
CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
|
||||||
if( m_translators.empty() )
|
|
||||||
std::rethrow_exception(std::current_exception());
|
|
||||||
else
|
|
||||||
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -16,35 +16,17 @@ namespace Catch {
|
|||||||
|
|
||||||
IGeneratorTracker::~IGeneratorTracker() {}
|
IGeneratorTracker::~IGeneratorTracker() {}
|
||||||
|
|
||||||
|
const char* GeneratorException::what() const noexcept {
|
||||||
|
return m_msg;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Generators {
|
namespace Generators {
|
||||||
|
|
||||||
GeneratorBase::~GeneratorBase() {}
|
GeneratorUntypedBase::~GeneratorUntypedBase() {}
|
||||||
|
|
||||||
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ) {
|
|
||||||
|
|
||||||
assert( selectionSize <= sourceSize );
|
|
||||||
std::vector<size_t> indices;
|
|
||||||
indices.reserve( selectionSize );
|
|
||||||
std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
|
|
||||||
|
|
||||||
std::set<size_t> seen;
|
|
||||||
// !TBD: improve this algorithm
|
|
||||||
while( indices.size() < selectionSize ) {
|
|
||||||
auto index = uid( rng() );
|
|
||||||
if( seen.insert( index ).second )
|
|
||||||
indices.push_back( index );
|
|
||||||
}
|
|
||||||
return indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
|
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
|
||||||
return getResultCapture().acquireGeneratorTracker( lineInfo );
|
return getResultCapture().acquireGeneratorTracker( lineInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
|
||||||
auto all<int>() -> Generator<int> {
|
|
||||||
return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Generators
|
} // namespace Generators
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
@@ -16,8 +16,21 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
class GeneratorException : public std::exception {
|
||||||
|
const char* const m_msg = "";
|
||||||
|
|
||||||
|
public:
|
||||||
|
GeneratorException(const char* msg):
|
||||||
|
m_msg(msg)
|
||||||
|
{}
|
||||||
|
|
||||||
|
const char* what() const noexcept override final;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Generators {
|
namespace Generators {
|
||||||
|
|
||||||
// !TBD move this into its own location?
|
// !TBD move this into its own location?
|
||||||
@@ -29,218 +42,159 @@ namespace Generators {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IGenerator {
|
struct IGenerator : GeneratorUntypedBase {
|
||||||
virtual ~IGenerator() {}
|
virtual ~IGenerator() = default;
|
||||||
virtual auto get( size_t index ) const -> T = 0;
|
|
||||||
|
// Returns the current element of the generator
|
||||||
|
//
|
||||||
|
// \Precondition The generator is either freshly constructed,
|
||||||
|
// or the last call to `next()` returned true
|
||||||
|
virtual T const& get() const = 0;
|
||||||
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class SingleValueGenerator : public IGenerator<T> {
|
class SingleValueGenerator final : public IGenerator<T> {
|
||||||
T m_value;
|
T m_value;
|
||||||
public:
|
public:
|
||||||
SingleValueGenerator( T const& value ) : m_value( value ) {}
|
SingleValueGenerator(T const& value) : m_value( value ) {}
|
||||||
|
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
|
||||||
|
|
||||||
auto get( size_t ) const -> T override {
|
T const& get() const override {
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
bool next() override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class FixedValuesGenerator : public IGenerator<T> {
|
class FixedValuesGenerator final : public IGenerator<T> {
|
||||||
std::vector<T> m_values;
|
std::vector<T> m_values;
|
||||||
|
size_t m_idx = 0;
|
||||||
public:
|
public:
|
||||||
FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
|
FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
|
||||||
|
|
||||||
auto get( size_t index ) const -> T override {
|
T const& get() const override {
|
||||||
return m_values[index];
|
return m_values[m_idx];
|
||||||
|
}
|
||||||
|
bool next() override {
|
||||||
|
++m_idx;
|
||||||
|
return m_idx < m_values.size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
class RangeGenerator : public IGenerator<T> {
|
class GeneratorWrapper final {
|
||||||
T const m_first;
|
|
||||||
T const m_last;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) {
|
|
||||||
assert( m_last > m_first );
|
|
||||||
}
|
|
||||||
|
|
||||||
auto get( size_t index ) const -> T override {
|
|
||||||
// ToDo:: introduce a safe cast to catch potential overflows
|
|
||||||
return static_cast<T>(m_first+index);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct NullGenerator : IGenerator<T> {
|
|
||||||
auto get( size_t ) const -> T override {
|
|
||||||
CATCH_INTERNAL_ERROR("A Null Generator is always empty");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Generator {
|
|
||||||
std::unique_ptr<IGenerator<T>> m_generator;
|
std::unique_ptr<IGenerator<T>> m_generator;
|
||||||
size_t m_size;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Generator( size_t size, std::unique_ptr<IGenerator<T>> generator )
|
GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
|
||||||
: m_generator( std::move( generator ) ),
|
m_generator(std::move(generator))
|
||||||
m_size( size )
|
|
||||||
{}
|
{}
|
||||||
|
T const& get() const {
|
||||||
auto size() const -> size_t { return m_size; }
|
return m_generator->get();
|
||||||
auto operator[]( size_t index ) const -> T {
|
}
|
||||||
assert( index < m_size );
|
bool next() {
|
||||||
return m_generator->get( index );
|
return m_generator->next();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize );
|
template <typename T>
|
||||||
|
GeneratorWrapper<T> value(T&& value) {
|
||||||
template<typename T>
|
return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
|
||||||
class GeneratorRandomiser : public IGenerator<T> {
|
|
||||||
Generator<T> m_baseGenerator;
|
|
||||||
|
|
||||||
std::vector<size_t> m_indices;
|
|
||||||
public:
|
|
||||||
GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems )
|
|
||||||
: m_baseGenerator( std::move( baseGenerator ) ),
|
|
||||||
m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto get( size_t index ) const -> T override {
|
|
||||||
return m_baseGenerator[m_indices[index]];
|
|
||||||
}
|
}
|
||||||
};
|
template <typename T>
|
||||||
|
GeneratorWrapper<T> values(std::initializer_list<T> values) {
|
||||||
template<typename T>
|
return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
|
||||||
struct RequiresASpecialisationFor;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); }
|
|
||||||
|
|
||||||
template<>
|
|
||||||
auto all<int>() -> Generator<int>;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto range( T const& first, T const& last ) -> Generator<T> {
|
|
||||||
return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto random( T const& first, T const& last ) -> Generator<T> {
|
class Generators : public IGenerator<T> {
|
||||||
auto gen = range( first, last );
|
std::vector<GeneratorWrapper<T>> m_generators;
|
||||||
auto size = gen.size();
|
size_t m_current = 0;
|
||||||
|
|
||||||
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
|
void populate(GeneratorWrapper<T>&& generator) {
|
||||||
|
m_generators.emplace_back(std::move(generator));
|
||||||
}
|
}
|
||||||
template<typename T>
|
void populate(T&& val) {
|
||||||
auto random( size_t size ) -> Generator<T> {
|
m_generators.emplace_back(value(std::move(val)));
|
||||||
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto values( std::initializer_list<T> values ) -> Generator<T> {
|
|
||||||
return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) );
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
auto value( T const& val ) -> Generator<T> {
|
|
||||||
return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto as() -> Generator<T> {
|
|
||||||
return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Ts>
|
|
||||||
auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> {
|
|
||||||
return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct Generators : GeneratorBase {
|
|
||||||
std::vector<Generator<T>> m_generators;
|
|
||||||
|
|
||||||
using type = T;
|
|
||||||
|
|
||||||
Generators() : GeneratorBase( 0 ) {}
|
|
||||||
|
|
||||||
void populate( T&& val ) {
|
|
||||||
m_size += 1;
|
|
||||||
m_generators.emplace_back( value( std::move( val ) ) );
|
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
void populate( U&& val ) {
|
void populate(U&& val) {
|
||||||
populate( T( std::move( val ) ) );
|
populate(T(std::move(val)));
|
||||||
}
|
}
|
||||||
void populate( Generator<T>&& generator ) {
|
|
||||||
m_size += generator.size();
|
|
||||||
m_generators.emplace_back( std::move( generator ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U, typename... Gs>
|
template<typename U, typename... Gs>
|
||||||
void populate( U&& valueOrGenerator, Gs... moreGenerators ) {
|
void populate(U&& valueOrGenerator, Gs... moreGenerators) {
|
||||||
populate( std::forward<U>( valueOrGenerator ) );
|
populate(std::forward<U>(valueOrGenerator));
|
||||||
populate( std::forward<Gs>( moreGenerators )... );
|
populate(std::forward<Gs>(moreGenerators)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator[]( size_t index ) const -> T {
|
public:
|
||||||
size_t sizes = 0;
|
template <typename... Gs>
|
||||||
for( auto const& gen : m_generators ) {
|
Generators(Gs... moreGenerators) {
|
||||||
auto localIndex = index-sizes;
|
m_generators.reserve(sizeof...(Gs));
|
||||||
sizes += gen.size();
|
populate(std::forward<Gs>(moreGenerators)...);
|
||||||
if( index < sizes )
|
|
||||||
return gen[localIndex];
|
|
||||||
}
|
}
|
||||||
CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')');
|
|
||||||
|
T const& get() const override {
|
||||||
|
return m_generators[m_current].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next() override {
|
||||||
|
if (m_current >= m_generators.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const bool current_status = m_generators[m_current].next();
|
||||||
|
if (!current_status) {
|
||||||
|
++m_current;
|
||||||
|
}
|
||||||
|
return m_current < m_generators.size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
|
||||||
|
return values<std::tuple<Ts...>>( tuples );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag type to signal that a generator sequence should convert arguments to a specific type
|
||||||
|
template <typename T>
|
||||||
|
struct as {};
|
||||||
|
|
||||||
template<typename T, typename... Gs>
|
template<typename T, typename... Gs>
|
||||||
auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
|
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
|
||||||
Generators<T> generators;
|
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
|
||||||
generators.m_generators.reserve( 1+sizeof...(Gs) );
|
|
||||||
generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
|
|
||||||
return generators;
|
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto makeGenerators( Generator<T>&& generator ) -> Generators<T> {
|
auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
|
||||||
Generators<T> generators;
|
return Generators<T>(std::move(generator));
|
||||||
generators.populate( std::move( generator ) );
|
|
||||||
return generators;
|
|
||||||
}
|
}
|
||||||
template<typename T, typename... Gs>
|
template<typename T, typename... Gs>
|
||||||
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
|
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
|
||||||
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
|
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
|
||||||
}
|
}
|
||||||
template<typename T, typename U, typename... Gs>
|
template<typename T, typename U, typename... Gs>
|
||||||
auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators<T> {
|
auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
|
||||||
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
|
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
|
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
|
||||||
|
|
||||||
template<typename L>
|
template<typename L>
|
||||||
// Note: The type after -> is weird, because VS2015 cannot parse
|
// Note: The type after -> is weird, because VS2015 cannot parse
|
||||||
// the expression used in the typedef inside, when it is in
|
// the expression used in the typedef inside, when it is in
|
||||||
// return type. Yeah, ¯\_(ツ)_/¯
|
// return type. Yeah.
|
||||||
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) {
|
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
|
||||||
using UnderlyingType = typename decltype(generatorExpression())::type;
|
using UnderlyingType = typename decltype(generatorExpression())::type;
|
||||||
|
|
||||||
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
|
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
|
||||||
if( !tracker.hasGenerator() )
|
if (!tracker.hasGenerator()) {
|
||||||
tracker.setGenerator( pf::make_unique<Generators<UnderlyingType>>( generatorExpression() ) );
|
tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
|
||||||
|
}
|
||||||
|
|
||||||
auto const& generator = static_cast<Generators<UnderlyingType> const&>( *tracker.getGenerator() );
|
auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
|
||||||
return generator[tracker.getIndex()];
|
return generator.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Generators
|
} // namespace Generators
|
||||||
|
230
include/internal/catch_generators_generic.hpp
Normal file
230
include/internal/catch_generators_generic.hpp
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 23/2/2019.
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_generators.hpp"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
namespace Generators {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class TakeGenerator : public IGenerator<T> {
|
||||||
|
GeneratorWrapper<T> m_generator;
|
||||||
|
size_t m_returned = 0;
|
||||||
|
size_t m_target;
|
||||||
|
public:
|
||||||
|
TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
|
||||||
|
m_generator(std::move(generator)),
|
||||||
|
m_target(target)
|
||||||
|
{
|
||||||
|
assert(target != 0 && "Empty generators are not allowed");
|
||||||
|
}
|
||||||
|
T const& get() const override {
|
||||||
|
return m_generator.get();
|
||||||
|
}
|
||||||
|
bool next() override {
|
||||||
|
++m_returned;
|
||||||
|
if (m_returned >= m_target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto success = m_generator.next();
|
||||||
|
// If the underlying generator does not contain enough values
|
||||||
|
// then we cut short as well
|
||||||
|
if (!success) {
|
||||||
|
m_returned = m_target;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
|
||||||
|
return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, typename Predicate>
|
||||||
|
class FilterGenerator : public IGenerator<T> {
|
||||||
|
GeneratorWrapper<T> m_generator;
|
||||||
|
Predicate m_predicate;
|
||||||
|
public:
|
||||||
|
template <typename P = Predicate>
|
||||||
|
FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
|
||||||
|
m_generator(std::move(generator)),
|
||||||
|
m_predicate(std::forward<P>(pred))
|
||||||
|
{
|
||||||
|
if (!m_predicate(m_generator.get())) {
|
||||||
|
// It might happen that there are no values that pass the
|
||||||
|
// filter. In that case we throw an exception.
|
||||||
|
auto has_initial_value = next();
|
||||||
|
if (!has_initial_value) {
|
||||||
|
Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T const& get() const override {
|
||||||
|
return m_generator.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next() override {
|
||||||
|
bool success = m_generator.next();
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, typename Predicate>
|
||||||
|
GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
|
||||||
|
return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class RepeatGenerator : public IGenerator<T> {
|
||||||
|
GeneratorWrapper<T> m_generator;
|
||||||
|
mutable std::vector<T> m_returned;
|
||||||
|
size_t m_target_repeats;
|
||||||
|
size_t m_current_repeat = 0;
|
||||||
|
size_t m_repeat_index = 0;
|
||||||
|
public:
|
||||||
|
RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
|
||||||
|
m_generator(std::move(generator)),
|
||||||
|
m_target_repeats(repeats)
|
||||||
|
{
|
||||||
|
assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
|
||||||
|
}
|
||||||
|
|
||||||
|
T const& get() const override {
|
||||||
|
if (m_current_repeat == 0) {
|
||||||
|
m_returned.push_back(m_generator.get());
|
||||||
|
return m_returned.back();
|
||||||
|
}
|
||||||
|
return m_returned[m_repeat_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next() override {
|
||||||
|
// There are 2 basic cases:
|
||||||
|
// 1) We are still reading the generator
|
||||||
|
// 2) We are reading our own cache
|
||||||
|
|
||||||
|
// In the first case, we need to poke the underlying generator.
|
||||||
|
// If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
|
||||||
|
if (m_current_repeat == 0) {
|
||||||
|
const auto success = m_generator.next();
|
||||||
|
if (!success) {
|
||||||
|
++m_current_repeat;
|
||||||
|
}
|
||||||
|
return m_current_repeat < m_target_repeats;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the second case, we need to move indices forward and check that we haven't run up against the end
|
||||||
|
++m_repeat_index;
|
||||||
|
if (m_repeat_index == m_returned.size()) {
|
||||||
|
m_repeat_index = 0;
|
||||||
|
++m_current_repeat;
|
||||||
|
}
|
||||||
|
return m_current_repeat < m_target_repeats;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
|
||||||
|
return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U, typename Func>
|
||||||
|
class MapGenerator : public IGenerator<T> {
|
||||||
|
// TBD: provide static assert for mapping function, for friendly error message
|
||||||
|
GeneratorWrapper<U> m_generator;
|
||||||
|
Func m_function;
|
||||||
|
// To avoid returning dangling reference, we have to save the values
|
||||||
|
T m_cache;
|
||||||
|
public:
|
||||||
|
template <typename F2 = Func>
|
||||||
|
MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
|
||||||
|
m_generator(std::move(generator)),
|
||||||
|
m_function(std::forward<F2>(function)),
|
||||||
|
m_cache(m_function(m_generator.get()))
|
||||||
|
{}
|
||||||
|
|
||||||
|
T const& get() const override {
|
||||||
|
return m_cache;
|
||||||
|
}
|
||||||
|
bool next() override {
|
||||||
|
const auto success = m_generator.next();
|
||||||
|
if (success) {
|
||||||
|
m_cache = m_function(m_generator.get());
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U, typename Func>
|
||||||
|
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
|
||||||
|
return GeneratorWrapper<T>(
|
||||||
|
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
template <typename T, typename Func>
|
||||||
|
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
|
||||||
|
return GeneratorWrapper<T>(
|
||||||
|
pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ChunkGenerator final : public IGenerator<std::vector<T>> {
|
||||||
|
std::vector<T> m_chunk;
|
||||||
|
size_t m_chunk_size;
|
||||||
|
GeneratorWrapper<T> m_generator;
|
||||||
|
bool m_used_up = false;
|
||||||
|
public:
|
||||||
|
ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
|
||||||
|
m_chunk_size(size), m_generator(std::move(generator))
|
||||||
|
{
|
||||||
|
m_chunk.reserve(m_chunk_size);
|
||||||
|
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 {
|
||||||
|
return m_chunk;
|
||||||
|
}
|
||||||
|
bool next() override {
|
||||||
|
m_chunk.clear();
|
||||||
|
for (size_t idx = 0; idx < m_chunk_size; ++idx) {
|
||||||
|
if (!m_generator.next()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_chunk.push_back(m_generator.get());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
|
||||||
|
return GeneratorWrapper<std::vector<T>>(
|
||||||
|
pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Generators
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
|
135
include/internal/catch_generators_specific.hpp
Normal file
135
include/internal/catch_generators_specific.hpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 15/6/2018.
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef TWOBLUECUBES_CATCH_GENERATORS_SPECIFIC_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_GENERATORS_SPECIFIC_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_context.h"
|
||||||
|
#include "catch_generators.hpp"
|
||||||
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
namespace Generators {
|
||||||
|
|
||||||
|
template <typename Float>
|
||||||
|
class RandomFloatingGenerator final : public IGenerator<Float> {
|
||||||
|
// FIXME: What is the right seed?
|
||||||
|
std::minstd_rand m_rand;
|
||||||
|
std::uniform_real_distribution<Float> m_dist;
|
||||||
|
Float m_current_number;
|
||||||
|
public:
|
||||||
|
|
||||||
|
RandomFloatingGenerator(Float a, Float b):
|
||||||
|
m_rand(getCurrentContext().getConfig()->rngSeed()),
|
||||||
|
m_dist(a, b) {
|
||||||
|
static_cast<void>(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
Float const& get() const override {
|
||||||
|
return m_current_number;
|
||||||
|
}
|
||||||
|
bool next() override {
|
||||||
|
m_current_number = m_dist(m_rand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Integer>
|
||||||
|
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
||||||
|
std::minstd_rand m_rand;
|
||||||
|
std::uniform_int_distribution<Integer> m_dist;
|
||||||
|
Integer m_current_number;
|
||||||
|
public:
|
||||||
|
|
||||||
|
RandomIntegerGenerator(Integer a, Integer b):
|
||||||
|
m_rand(getCurrentContext().getConfig()->rngSeed()),
|
||||||
|
m_dist(a, b) {
|
||||||
|
static_cast<void>(next());
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer const& get() const override {
|
||||||
|
return m_current_number;
|
||||||
|
}
|
||||||
|
bool next() override {
|
||||||
|
m_current_number = m_dist(m_rand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Ideally this would be also constrained against the various char types,
|
||||||
|
// but I don't expect users to run into that in practice.
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
|
||||||
|
GeneratorWrapper<T>>::type
|
||||||
|
random(T a, T b) {
|
||||||
|
return GeneratorWrapper<T>(
|
||||||
|
pf::make_unique<RandomIntegerGenerator<T>>(a, b)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value,
|
||||||
|
GeneratorWrapper<T>>::type
|
||||||
|
random(T a, T b) {
|
||||||
|
return GeneratorWrapper<T>(
|
||||||
|
pf::make_unique<RandomFloatingGenerator<T>>(a, b)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class RangeGenerator final : public IGenerator<T> {
|
||||||
|
T m_current;
|
||||||
|
T m_end;
|
||||||
|
T m_step;
|
||||||
|
bool m_positive;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RangeGenerator(T const& start, T const& end, T const& step):
|
||||||
|
m_current(start),
|
||||||
|
m_end(end),
|
||||||
|
m_step(step),
|
||||||
|
m_positive(m_step > T(0))
|
||||||
|
{
|
||||||
|
assert(m_current != m_end && "Range start and end cannot be equal");
|
||||||
|
assert(m_step != T(0) && "Step size cannot be zero");
|
||||||
|
assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeGenerator(T const& start, T const& end):
|
||||||
|
RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
|
||||||
|
{}
|
||||||
|
|
||||||
|
T const& get() const override {
|
||||||
|
return m_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next() override {
|
||||||
|
m_current += m_step;
|
||||||
|
return (m_positive) ? (m_current < m_end) : (m_current > m_end);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
|
||||||
|
static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
|
||||||
|
return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GeneratorWrapper<T> range(T const& start, T const& end) {
|
||||||
|
static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
|
||||||
|
return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Generators
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_GENERATORS_SPECIFIC_HPP_INCLUDED
|
@@ -20,6 +20,7 @@ namespace Catch {
|
|||||||
struct SectionInfo;
|
struct SectionInfo;
|
||||||
struct SectionEndInfo;
|
struct SectionEndInfo;
|
||||||
struct MessageInfo;
|
struct MessageInfo;
|
||||||
|
struct MessageBuilder;
|
||||||
struct Counts;
|
struct Counts;
|
||||||
struct BenchmarkInfo;
|
struct BenchmarkInfo;
|
||||||
struct BenchmarkStats;
|
struct BenchmarkStats;
|
||||||
@@ -46,6 +47,8 @@ namespace Catch {
|
|||||||
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
||||||
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
||||||
|
|
||||||
|
virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
|
||||||
|
|
||||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||||
|
|
||||||
virtual void handleExpr
|
virtual void handleExpr
|
||||||
|
@@ -13,16 +13,17 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
namespace Generators {
|
namespace Generators {
|
||||||
class GeneratorBase {
|
class GeneratorUntypedBase {
|
||||||
protected:
|
|
||||||
size_t m_size = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GeneratorBase( size_t size ) : m_size( size ) {}
|
GeneratorUntypedBase() = default;
|
||||||
virtual ~GeneratorBase();
|
virtual ~GeneratorUntypedBase();
|
||||||
auto size() const -> size_t { return m_size; }
|
// Attempts to move the generator to the next element
|
||||||
|
//
|
||||||
|
// Returns true iff the move succeeded (and a valid element
|
||||||
|
// can be retrieved).
|
||||||
|
virtual bool next() = 0;
|
||||||
};
|
};
|
||||||
using GeneratorBasePtr = std::unique_ptr<GeneratorBase>;
|
using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
|
||||||
|
|
||||||
} // namespace Generators
|
} // namespace Generators
|
||||||
|
|
||||||
@@ -31,7 +32,6 @@ namespace Catch {
|
|||||||
virtual auto hasGenerator() const -> bool = 0;
|
virtual auto hasGenerator() const -> bool = 0;
|
||||||
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
|
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
|
||||||
virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
|
virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
|
||||||
virtual auto getIndex() const -> std::size_t = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
@@ -80,8 +80,8 @@ namespace Catch {
|
|||||||
|
|
||||||
AssertionStats( AssertionStats const& ) = default;
|
AssertionStats( AssertionStats const& ) = default;
|
||||||
AssertionStats( AssertionStats && ) = default;
|
AssertionStats( AssertionStats && ) = default;
|
||||||
AssertionStats& operator = ( AssertionStats const& ) = default;
|
AssertionStats& operator = ( AssertionStats const& ) = delete;
|
||||||
AssertionStats& operator = ( AssertionStats && ) = default;
|
AssertionStats& operator = ( AssertionStats && ) = delete;
|
||||||
virtual ~AssertionStats();
|
virtual ~AssertionStats();
|
||||||
|
|
||||||
AssertionResult assertionResult;
|
AssertionResult assertionResult;
|
||||||
|
@@ -9,7 +9,6 @@
|
|||||||
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -20,8 +19,6 @@ namespace Catch {
|
|||||||
virtual ~ITestInvoker();
|
virtual ~ITestInvoker();
|
||||||
};
|
};
|
||||||
|
|
||||||
using ITestCasePtr = std::shared_ptr<ITestInvoker>;
|
|
||||||
|
|
||||||
class TestCase;
|
class TestCase;
|
||||||
struct IConfig;
|
struct IConfig;
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include "catch_interfaces_reporter.h"
|
#include "catch_interfaces_reporter.h"
|
||||||
#include "catch_interfaces_testcase.h"
|
#include "catch_interfaces_testcase.h"
|
||||||
|
|
||||||
|
#include "catch_context.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_text.h"
|
#include "catch_text.h"
|
||||||
|
|
||||||
@@ -146,15 +147,16 @@ namespace Catch {
|
|||||||
return factories.size();
|
return factories.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Option<std::size_t> list( Config const& config ) {
|
Option<std::size_t> list( std::shared_ptr<Config> const& config ) {
|
||||||
Option<std::size_t> listedCount;
|
Option<std::size_t> listedCount;
|
||||||
if( config.listTests() )
|
getCurrentMutableContext().setConfig( config );
|
||||||
listedCount = listedCount.valueOr(0) + listTests( config );
|
if( config->listTests() )
|
||||||
if( config.listTestNamesOnly() )
|
listedCount = listedCount.valueOr(0) + listTests( *config );
|
||||||
listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
|
if( config->listTestNamesOnly() )
|
||||||
if( config.listTags() )
|
listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
|
||||||
listedCount = listedCount.valueOr(0) + listTags( config );
|
if( config->listTags() )
|
||||||
if( config.listReporters() )
|
listedCount = listedCount.valueOr(0) + listTags( *config );
|
||||||
|
if( config->listReporters() )
|
||||||
listedCount = listedCount.valueOr(0) + listReporters();
|
listedCount = listedCount.valueOr(0) + listReporters();
|
||||||
return listedCount;
|
return listedCount;
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,7 @@ namespace Catch {
|
|||||||
|
|
||||||
std::size_t listReporters();
|
std::size_t listReporters();
|
||||||
|
|
||||||
Option<std::size_t> list( Config const& config );
|
Option<std::size_t> list( std::shared_ptr<Config> const& config );
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
|
@@ -47,14 +47,20 @@ namespace Catch {
|
|||||||
|
|
||||||
|
|
||||||
ScopedMessage::ScopedMessage( MessageBuilder const& builder )
|
ScopedMessage::ScopedMessage( MessageBuilder const& builder )
|
||||||
: m_info( builder.m_info )
|
: m_info( builder.m_info ), m_moved()
|
||||||
{
|
{
|
||||||
m_info.message = builder.m_stream.str();
|
m_info.message = builder.m_stream.str();
|
||||||
getResultCapture().pushScopedMessage( m_info );
|
getResultCapture().pushScopedMessage( m_info );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopedMessage::ScopedMessage( ScopedMessage&& old )
|
||||||
|
: m_info( old.m_info ), m_moved()
|
||||||
|
{
|
||||||
|
old.m_moved = true;
|
||||||
|
}
|
||||||
|
|
||||||
ScopedMessage::~ScopedMessage() {
|
ScopedMessage::~ScopedMessage() {
|
||||||
if ( !uncaught_exceptions() ){
|
if ( !uncaught_exceptions() && !m_moved ){
|
||||||
getResultCapture().popScopedMessage(m_info);
|
getResultCapture().popScopedMessage(m_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -64,9 +64,12 @@ namespace Catch {
|
|||||||
class ScopedMessage {
|
class ScopedMessage {
|
||||||
public:
|
public:
|
||||||
explicit ScopedMessage( MessageBuilder const& builder );
|
explicit ScopedMessage( MessageBuilder const& builder );
|
||||||
|
ScopedMessage( ScopedMessage& duplicate ) = delete;
|
||||||
|
ScopedMessage( ScopedMessage&& old );
|
||||||
~ScopedMessage();
|
~ScopedMessage();
|
||||||
|
|
||||||
MessageInfo m_info;
|
MessageInfo m_info;
|
||||||
|
bool m_moved;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Capturer {
|
class Capturer {
|
||||||
|
77
include/internal/catch_meta.hpp
Normal file
77
include/internal/catch_meta.hpp
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Created by Jozef on 02/12/2018.
|
||||||
|
* Copyright 2018 Two Blue Cubes Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TWOBLUECUBES_CATCH_META_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_META_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
template< typename... >
|
||||||
|
struct TypeList {};
|
||||||
|
|
||||||
|
template< typename... >
|
||||||
|
struct append;
|
||||||
|
|
||||||
|
template< template<typename...> class L1
|
||||||
|
, typename...E1
|
||||||
|
, template<typename...> class L2
|
||||||
|
, typename...E2
|
||||||
|
>
|
||||||
|
struct append< L1<E1...>, L2<E2...> > {
|
||||||
|
using type = L1<E1..., E2...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< template<typename...> class L1
|
||||||
|
, typename...E1
|
||||||
|
, template<typename...> class L2
|
||||||
|
, typename...E2
|
||||||
|
, typename...Rest
|
||||||
|
>
|
||||||
|
struct append< L1<E1...>, L2<E2...>, Rest...> {
|
||||||
|
using type = typename append< L1<E1..., E2...>, Rest... >::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< template<typename...> class
|
||||||
|
, typename...
|
||||||
|
>
|
||||||
|
struct rewrap;
|
||||||
|
|
||||||
|
template< template<typename...> class Container
|
||||||
|
, template<typename...> class List
|
||||||
|
, typename...elems
|
||||||
|
>
|
||||||
|
struct rewrap<Container, List<elems...>> {
|
||||||
|
using type = TypeList< Container< elems... > >;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< template<typename...> class Container
|
||||||
|
, template<typename...> class List
|
||||||
|
, class...Elems
|
||||||
|
, typename...Elements>
|
||||||
|
struct rewrap<Container, List<Elems...>, Elements...> {
|
||||||
|
using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< template<typename...> class...Containers >
|
||||||
|
struct combine {
|
||||||
|
template< typename...Types >
|
||||||
|
struct with_types {
|
||||||
|
template< template <typename...> class Final >
|
||||||
|
struct into {
|
||||||
|
using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct always_false : std::false_type {};
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_META_HPP_INCLUDED
|
@@ -49,6 +49,15 @@ namespace Catch {
|
|||||||
{}
|
{}
|
||||||
auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
|
auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
|
||||||
|
|
||||||
|
RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
|
||||||
|
: m_redirectedCout(redirectedCout),
|
||||||
|
m_redirectedCerr(redirectedCerr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
RedirectedStreams::~RedirectedStreams() {
|
||||||
|
m_redirectedCout += m_redirectedStdOut.str();
|
||||||
|
m_redirectedCerr += m_redirectedStdErr.str();
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_NEW_CAPTURE)
|
#if defined(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
|
||||||
|
@@ -46,6 +46,21 @@ namespace Catch {
|
|||||||
auto str() const -> std::string;
|
auto str() const -> std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RedirectedStreams {
|
||||||
|
public:
|
||||||
|
RedirectedStreams(RedirectedStreams const&) = delete;
|
||||||
|
RedirectedStreams& operator=(RedirectedStreams const&) = delete;
|
||||||
|
RedirectedStreams(RedirectedStreams&&) = delete;
|
||||||
|
RedirectedStreams& operator=(RedirectedStreams&&) = delete;
|
||||||
|
|
||||||
|
RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
|
||||||
|
~RedirectedStreams();
|
||||||
|
private:
|
||||||
|
std::string& m_redirectedCout;
|
||||||
|
std::string& m_redirectedCerr;
|
||||||
|
RedirectedStdOut m_redirectedStdOut;
|
||||||
|
RedirectedStdErr m_redirectedStdErr;
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_NEW_CAPTURE)
|
#if defined(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
|
||||||
|
@@ -57,6 +57,16 @@
|
|||||||
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
|
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
|
||||||
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
|
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
|
||||||
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
|
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
|
||||||
|
#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
|
||||||
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
|
#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
|
||||||
|
#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
|
||||||
|
#else
|
||||||
|
// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
|
||||||
|
#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
|
||||||
|
#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
|
||||||
|
#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
|
#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
|
||||||
|
|
||||||
@@ -71,4 +81,9 @@
|
|||||||
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
|
#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)>
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
|
||||||
|
CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED
|
||||||
|
@@ -14,7 +14,6 @@ namespace Catch {
|
|||||||
|
|
||||||
namespace Generators {
|
namespace Generators {
|
||||||
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
|
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
|
||||||
size_t m_index = static_cast<size_t>( -1 );
|
|
||||||
GeneratorBasePtr m_generator;
|
GeneratorBasePtr m_generator;
|
||||||
|
|
||||||
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||||
@@ -28,7 +27,7 @@ namespace Catch {
|
|||||||
ITracker& currentTracker = ctx.currentTracker();
|
ITracker& currentTracker = ctx.currentTracker();
|
||||||
if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
|
if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
|
||||||
assert( childTracker );
|
assert( childTracker );
|
||||||
assert( childTracker->isIndexTracker() );
|
assert( childTracker->isGeneratorTracker() );
|
||||||
tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
|
tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -37,29 +36,25 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( !ctx.completedCycle() && !tracker->isComplete() ) {
|
if( !ctx.completedCycle() && !tracker->isComplete() ) {
|
||||||
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
|
|
||||||
tracker->moveNext();
|
|
||||||
tracker->open();
|
tracker->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
return *tracker;
|
return *tracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveNext() {
|
|
||||||
m_index++;
|
|
||||||
m_children.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrackerBase interface
|
// TrackerBase interface
|
||||||
bool isIndexTracker() const override { return true; }
|
bool isGeneratorTracker() const override { return true; }
|
||||||
auto hasGenerator() const -> bool override {
|
auto hasGenerator() const -> bool override {
|
||||||
return !!m_generator;
|
return !!m_generator;
|
||||||
}
|
}
|
||||||
void close() override {
|
void close() override {
|
||||||
TrackerBase::close();
|
TrackerBase::close();
|
||||||
if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 )
|
// Generator interface only finds out if it has another item on atual move
|
||||||
|
if (m_runState == CompletedSuccessfully && m_generator->next()) {
|
||||||
|
m_children.clear();
|
||||||
m_runState = Executing;
|
m_runState = Executing;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IGeneratorTracker interface
|
// IGeneratorTracker interface
|
||||||
auto getGenerator() const -> GeneratorBasePtr const& override {
|
auto getGenerator() const -> GeneratorBasePtr const& override {
|
||||||
@@ -68,14 +63,10 @@ namespace Catch {
|
|||||||
void setGenerator( GeneratorBasePtr&& generator ) override {
|
void setGenerator( GeneratorBasePtr&& generator ) override {
|
||||||
m_generator = std::move( generator );
|
m_generator = std::move( generator );
|
||||||
}
|
}
|
||||||
auto getIndex() const -> size_t override {
|
|
||||||
return m_index;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
GeneratorTracker::~GeneratorTracker() {}
|
GeneratorTracker::~GeneratorTracker() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
||||||
: m_runInfo(_config->name()),
|
: m_runInfo(_config->name()),
|
||||||
m_context(getCurrentMutableContext()),
|
m_context(getCurrentMutableContext()),
|
||||||
@@ -170,6 +161,9 @@ namespace Catch {
|
|||||||
// and should be let to clear themselves out.
|
// and should be let to clear themselves out.
|
||||||
static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
|
static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
|
||||||
|
|
||||||
|
if (result.getResultType() != ResultWas::Warning)
|
||||||
|
m_messageScopes.clear();
|
||||||
|
|
||||||
// Reset working state
|
// Reset working state
|
||||||
resetAssertionInfo();
|
resetAssertionInfo();
|
||||||
m_lastResult = result;
|
m_lastResult = result;
|
||||||
@@ -224,6 +218,7 @@ namespace Catch {
|
|||||||
|
|
||||||
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
|
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
|
||||||
m_messages.clear();
|
m_messages.clear();
|
||||||
|
m_messageScopes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
|
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
|
||||||
@@ -250,6 +245,10 @@ namespace Catch {
|
|||||||
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
|
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
|
||||||
|
m_messageScopes.emplace_back( builder );
|
||||||
|
}
|
||||||
|
|
||||||
std::string RunContext::getCurrentTestName() const {
|
std::string RunContext::getCurrentTestName() const {
|
||||||
return m_activeTestCase
|
return m_activeTestCase
|
||||||
? m_activeTestCase->getTestCaseInfo().name
|
? m_activeTestCase->getTestCaseInfo().name
|
||||||
@@ -310,6 +309,7 @@ namespace Catch {
|
|||||||
m_lastAssertionPassed = true;
|
m_lastAssertionPassed = true;
|
||||||
++m_totals.assertions.passed;
|
++m_totals.assertions.passed;
|
||||||
resetAssertionInfo();
|
resetAssertionInfo();
|
||||||
|
m_messageScopes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunContext::aborting() const {
|
bool RunContext::aborting() const {
|
||||||
@@ -331,13 +331,10 @@ namespace Catch {
|
|||||||
CATCH_TRY {
|
CATCH_TRY {
|
||||||
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
||||||
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
||||||
RedirectedStdOut redirectedStdOut;
|
RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
|
||||||
RedirectedStdErr redirectedStdErr;
|
|
||||||
|
|
||||||
timer.start();
|
timer.start();
|
||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
redirectedCout += redirectedStdOut.str();
|
|
||||||
redirectedCerr += redirectedStdErr.str();
|
|
||||||
#else
|
#else
|
||||||
OutputRedirect r(redirectedCout, redirectedCerr);
|
OutputRedirect r(redirectedCout, redirectedCerr);
|
||||||
timer.start();
|
timer.start();
|
||||||
@@ -364,6 +361,7 @@ namespace Catch {
|
|||||||
m_testCaseTracker->close();
|
m_testCaseTracker->close();
|
||||||
handleUnfinishedSections();
|
handleUnfinishedSections();
|
||||||
m_messages.clear();
|
m_messages.clear();
|
||||||
|
m_messageScopes.clear();
|
||||||
|
|
||||||
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
||||||
m_reporter->sectionEnded(testCaseSectionStats);
|
m_reporter->sectionEnded(testCaseSectionStats);
|
||||||
|
@@ -88,6 +88,8 @@ namespace Catch {
|
|||||||
void pushScopedMessage( MessageInfo const& message ) override;
|
void pushScopedMessage( MessageInfo const& message ) override;
|
||||||
void popScopedMessage( MessageInfo const& message ) override;
|
void popScopedMessage( MessageInfo const& message ) override;
|
||||||
|
|
||||||
|
void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
|
||||||
|
|
||||||
std::string getCurrentTestName() const override;
|
std::string getCurrentTestName() const override;
|
||||||
|
|
||||||
const AssertionResult* getLastResult() const override;
|
const AssertionResult* getLastResult() const override;
|
||||||
@@ -128,13 +130,14 @@ namespace Catch {
|
|||||||
TestRunInfo m_runInfo;
|
TestRunInfo m_runInfo;
|
||||||
IMutableContext& m_context;
|
IMutableContext& m_context;
|
||||||
TestCase const* m_activeTestCase = nullptr;
|
TestCase const* m_activeTestCase = nullptr;
|
||||||
ITracker* m_testCaseTracker;
|
ITracker* m_testCaseTracker = nullptr;
|
||||||
Option<AssertionResult> m_lastResult;
|
Option<AssertionResult> m_lastResult;
|
||||||
|
|
||||||
IConfigPtr m_config;
|
IConfigPtr m_config;
|
||||||
Totals m_totals;
|
Totals m_totals;
|
||||||
IStreamingReporterPtr m_reporter;
|
IStreamingReporterPtr m_reporter;
|
||||||
std::vector<MessageInfo> m_messages;
|
std::vector<MessageInfo> m_messages;
|
||||||
|
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
|
||||||
AssertionInfo m_lastAssertionInfo;
|
AssertionInfo m_lastAssertionInfo;
|
||||||
std::vector<SectionEndInfo> m_unfinishedSections;
|
std::vector<SectionEndInfo> m_unfinishedSections;
|
||||||
std::vector<ITracker*> m_activeSections;
|
std::vector<ITracker*> m_activeSections;
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include "catch_console_colour.h"
|
#include "catch_console_colour.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_list.h"
|
#include "catch_list.h"
|
||||||
|
#include "catch_context.h"
|
||||||
#include "catch_run_context.h"
|
#include "catch_run_context.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_test_spec.h"
|
#include "catch_test_spec.h"
|
||||||
@@ -42,14 +43,19 @@ namespace Catch {
|
|||||||
return createReporter(config->getReporterName(), config);
|
return createReporter(config->getReporterName(), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
|
// On older platforms, returning std::unique_ptr<ListeningReporter>
|
||||||
|
// when the return type is std::unique_ptr<IStreamingReporter>
|
||||||
|
// doesn't compile without a std::move call. However, this causes
|
||||||
|
// a warning on newer platforms. Thus, we have to work around
|
||||||
|
// it a bit and downcast the pointer manually.
|
||||||
|
auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
|
||||||
|
auto& multi = static_cast<ListeningReporter&>(*ret);
|
||||||
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
|
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
|
||||||
for (auto const& listener : listeners) {
|
for (auto const& listener : listeners) {
|
||||||
multi->addListener(listener->create(Catch::ReporterConfig(config)));
|
multi.addListener(listener->create(Catch::ReporterConfig(config)));
|
||||||
}
|
}
|
||||||
multi->addReporter(createReporter(config->getReporterName(), config));
|
multi.addReporter(createReporter(config->getReporterName(), config));
|
||||||
return std::move(multi);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -166,6 +172,8 @@ namespace Catch {
|
|||||||
|
|
||||||
auto result = m_cli.parse( clara::Args( argc, argv ) );
|
auto result = m_cli.parse( clara::Args( argc, argv ) );
|
||||||
if( !result ) {
|
if( !result ) {
|
||||||
|
config();
|
||||||
|
getCurrentMutableContext().setConfig(m_config);
|
||||||
Catch::cerr()
|
Catch::cerr()
|
||||||
<< Colour( Colour::Red )
|
<< Colour( Colour::Red )
|
||||||
<< "\nError(s) in input:\n"
|
<< "\nError(s) in input:\n"
|
||||||
@@ -257,7 +265,7 @@ namespace Catch {
|
|||||||
applyFilenamesAsTags( *m_config );
|
applyFilenamesAsTags( *m_config );
|
||||||
|
|
||||||
// Handle list request
|
// Handle list request
|
||||||
if( Option<std::size_t> listed = list( config() ) )
|
if( Option<std::size_t> listed = list( m_config ) )
|
||||||
return static_cast<int>( *listed );
|
return static_cast<int>( *listed );
|
||||||
|
|
||||||
auto totals = runTests( m_config );
|
auto totals = runTests( m_config );
|
||||||
|
@@ -13,8 +13,6 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
class StringData;
|
|
||||||
|
|
||||||
/// A non-owning string class (similar to the forthcoming std::string_view)
|
/// A non-owning string class (similar to the forthcoming std::string_view)
|
||||||
/// Note that, because a StringRef may be a substring of another string,
|
/// Note that, because a StringRef may be a substring of another string,
|
||||||
/// it may not be null terminated. c_str() must return a null terminated
|
/// it may not be null terminated. c_str() must return a null terminated
|
||||||
|
@@ -16,10 +16,11 @@
|
|||||||
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
# endif
|
# endif
|
||||||
#elif defined __GNUC__
|
#elif defined __GNUC__
|
||||||
// GCC likes to warn on REQUIREs, and we cannot suppress them
|
// Because REQUIREs trigger GCC's -Wparentheses, and because still
|
||||||
// locally because g++'s support for _Pragma is lacking in older,
|
// supported version of g++ have only buggy support for _Pragmas,
|
||||||
// still supported, versions
|
// Wparentheses have to be suppressed globally.
|
||||||
# pragma GCC diagnostic ignored "-Wparentheses"
|
# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
|
||||||
|
|
||||||
# pragma GCC diagnostic push
|
# pragma GCC diagnostic push
|
||||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
# pragma GCC diagnostic ignored "-Wpadded"
|
# pragma GCC diagnostic ignored "-Wpadded"
|
||||||
|
@@ -121,7 +121,7 @@ namespace TestCaseTracking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TrackerBase::isSectionTracker() const { return false; }
|
bool TrackerBase::isSectionTracker() const { return false; }
|
||||||
bool TrackerBase::isIndexTracker() const { return false; }
|
bool TrackerBase::isGeneratorTracker() const { return false; }
|
||||||
|
|
||||||
void TrackerBase::open() {
|
void TrackerBase::open() {
|
||||||
m_runState = Executing;
|
m_runState = Executing;
|
||||||
@@ -190,6 +190,17 @@ namespace TestCaseTracking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SectionTracker::isComplete() const {
|
||||||
|
bool complete = true;
|
||||||
|
|
||||||
|
if ((m_filters.empty() || m_filters[0] == "") ||
|
||||||
|
std::find(m_filters.begin(), m_filters.end(),
|
||||||
|
m_nameAndLocation.name) != m_filters.end())
|
||||||
|
complete = TrackerBase::isComplete();
|
||||||
|
return complete;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool SectionTracker::isSectionTracker() const { return true; }
|
bool SectionTracker::isSectionTracker() const { return true; }
|
||||||
|
|
||||||
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
|
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
|
||||||
@@ -227,55 +238,11 @@ namespace TestCaseTracking {
|
|||||||
m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
|
m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
|
|
||||||
: TrackerBase( nameAndLocation, ctx, parent ),
|
|
||||||
m_size( size )
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool IndexTracker::isIndexTracker() const { return true; }
|
|
||||||
|
|
||||||
IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
|
|
||||||
std::shared_ptr<IndexTracker> tracker;
|
|
||||||
|
|
||||||
ITracker& currentTracker = ctx.currentTracker();
|
|
||||||
if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
|
|
||||||
assert( childTracker );
|
|
||||||
assert( childTracker->isIndexTracker() );
|
|
||||||
tracker = std::static_pointer_cast<IndexTracker>( childTracker );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, ¤tTracker, size );
|
|
||||||
currentTracker.addChild( tracker );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !ctx.completedCycle() && !tracker->isComplete() ) {
|
|
||||||
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
|
|
||||||
tracker->moveNext();
|
|
||||||
tracker->open();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *tracker;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IndexTracker::index() const { return m_index; }
|
|
||||||
|
|
||||||
void IndexTracker::moveNext() {
|
|
||||||
m_index++;
|
|
||||||
m_children.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndexTracker::close() {
|
|
||||||
TrackerBase::close();
|
|
||||||
if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
|
|
||||||
m_runState = Executing;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace TestCaseTracking
|
} // namespace TestCaseTracking
|
||||||
|
|
||||||
using TestCaseTracking::ITracker;
|
using TestCaseTracking::ITracker;
|
||||||
using TestCaseTracking::TrackerContext;
|
using TestCaseTracking::TrackerContext;
|
||||||
using TestCaseTracking::SectionTracker;
|
using TestCaseTracking::SectionTracker;
|
||||||
using TestCaseTracking::IndexTracker;
|
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@@ -54,7 +54,7 @@ namespace TestCaseTracking {
|
|||||||
|
|
||||||
// Debug/ checking
|
// Debug/ checking
|
||||||
virtual bool isSectionTracker() const = 0;
|
virtual bool isSectionTracker() const = 0;
|
||||||
virtual bool isIndexTracker() const = 0;
|
virtual bool isGeneratorTracker() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TrackerContext {
|
class TrackerContext {
|
||||||
@@ -120,7 +120,7 @@ namespace TestCaseTracking {
|
|||||||
void openChild() override;
|
void openChild() override;
|
||||||
|
|
||||||
bool isSectionTracker() const override;
|
bool isSectionTracker() const override;
|
||||||
bool isIndexTracker() const override;
|
bool isGeneratorTracker() const override;
|
||||||
|
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
@@ -140,6 +140,8 @@ namespace TestCaseTracking {
|
|||||||
|
|
||||||
bool isSectionTracker() const override;
|
bool isSectionTracker() const override;
|
||||||
|
|
||||||
|
bool isComplete() const override;
|
||||||
|
|
||||||
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
|
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
|
||||||
|
|
||||||
void tryOpen();
|
void tryOpen();
|
||||||
@@ -148,28 +150,11 @@ namespace TestCaseTracking {
|
|||||||
void addNextFilters( std::vector<std::string> const& filters );
|
void addNextFilters( std::vector<std::string> const& filters );
|
||||||
};
|
};
|
||||||
|
|
||||||
class IndexTracker : public TrackerBase {
|
|
||||||
int m_size;
|
|
||||||
int m_index = -1;
|
|
||||||
public:
|
|
||||||
IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size );
|
|
||||||
|
|
||||||
bool isIndexTracker() const override;
|
|
||||||
void close() override;
|
|
||||||
|
|
||||||
static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size );
|
|
||||||
|
|
||||||
int index() const;
|
|
||||||
|
|
||||||
void moveNext();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TestCaseTracking
|
} // namespace TestCaseTracking
|
||||||
|
|
||||||
using TestCaseTracking::ITracker;
|
using TestCaseTracking::ITracker;
|
||||||
using TestCaseTracking::TrackerContext;
|
using TestCaseTracking::TrackerContext;
|
||||||
using TestCaseTracking::SectionTracker;
|
using TestCaseTracking::SectionTracker;
|
||||||
using TestCaseTracking::IndexTracker;
|
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
#include "catch_type_traits.hpp"
|
#include "catch_type_traits.hpp"
|
||||||
#include "catch_preprocessor.hpp"
|
#include "catch_preprocessor.hpp"
|
||||||
|
#include "catch_meta.hpp"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -150,6 +151,41 @@ struct AutoReg : NonCopyable {
|
|||||||
return 0;\
|
return 0;\
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
template<typename TestType> static void TestFuncName(); \
|
||||||
|
namespace { \
|
||||||
|
template<typename... Types> \
|
||||||
|
struct TestName { \
|
||||||
|
TestName() { \
|
||||||
|
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \
|
||||||
|
int index = 0; \
|
||||||
|
using expander = int[]; \
|
||||||
|
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
|
||||||
|
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
|
||||||
|
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
|
||||||
|
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||||
|
using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \
|
||||||
|
::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \
|
||||||
|
TestInit(); \
|
||||||
|
return 0; \
|
||||||
|
}(); \
|
||||||
|
} \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
template<typename TestType> \
|
||||||
|
static void TestFuncName()
|
||||||
|
|
||||||
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
|
||||||
|
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
|
||||||
|
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
|
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ \
|
namespace{ \
|
||||||
@@ -180,4 +216,42 @@ struct AutoReg : NonCopyable {
|
|||||||
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
|
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\
|
||||||
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
template<typename TestType> \
|
||||||
|
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||||
|
void test();\
|
||||||
|
};\
|
||||||
|
namespace {\
|
||||||
|
template<typename...Types>\
|
||||||
|
struct TestNameClass{\
|
||||||
|
TestNameClass(){\
|
||||||
|
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
|
||||||
|
int index = 0;\
|
||||||
|
using expander = int[];\
|
||||||
|
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
|
||||||
|
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
|
||||||
|
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
|
||||||
|
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
|
||||||
|
}\
|
||||||
|
};\
|
||||||
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||||
|
using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\
|
||||||
|
::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\
|
||||||
|
TestInit();\
|
||||||
|
return 0;\
|
||||||
|
}(); \
|
||||||
|
}\
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
template<typename TestType> \
|
||||||
|
void TestName<TestType>::test()
|
||||||
|
|
||||||
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
|
||||||
|
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ )
|
||||||
|
#else
|
||||||
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
|
||||||
|
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
|
||||||
|
@@ -40,7 +40,7 @@ namespace Catch {
|
|||||||
// is terrible and we should move on.
|
// is terrible and we should move on.
|
||||||
// TBD: How to signal that the measured resolution is probably wrong?
|
// TBD: How to signal that the measured resolution is probably wrong?
|
||||||
if (ticks > startTime + 3 * nanosecondsInSecond) {
|
if (ticks > startTime + 3 * nanosecondsInSecond) {
|
||||||
return sum / i;
|
return sum / ( i + 1u );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -348,6 +348,7 @@ namespace Catch {
|
|||||||
# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||||
# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
|
# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
|
||||||
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Separate std::pair specialization
|
// Separate std::pair specialization
|
||||||
@@ -369,6 +370,24 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||||
|
#include <optional>
|
||||||
|
namespace Catch {
|
||||||
|
template<typename T>
|
||||||
|
struct StringMaker<std::optional<T> > {
|
||||||
|
static std::string convert(const std::optional<T>& optional) {
|
||||||
|
ReusableStringStream rss;
|
||||||
|
if (optional.has_value()) {
|
||||||
|
rss << ::Catch::Detail::stringify(*optional);
|
||||||
|
} else {
|
||||||
|
rss << "{ }";
|
||||||
|
}
|
||||||
|
return rss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
|
||||||
|
|
||||||
// Separate std::tuple specialization
|
// Separate std::tuple specialization
|
||||||
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
|
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Catch{
|
namespace Catch{
|
||||||
|
|
||||||
#ifdef CATCH_CPP17_OR_GREATER
|
#ifdef CATCH_CPP17_OR_GREATER
|
||||||
|
@@ -37,7 +37,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Version const& libraryVersion() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 2, 5, 0, "", 0 );
|
static Version version( 2, 7, 0, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,9 +44,11 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void hexEscapeChar(std::ostream& os, unsigned char c) {
|
void hexEscapeChar(std::ostream& os, unsigned char c) {
|
||||||
|
std::ios_base::fmtflags f(os.flags());
|
||||||
os << "\\x"
|
os << "\\x"
|
||||||
<< std::uppercase << std::hex << std::setfill('0') << std::setw(2)
|
<< std::uppercase << std::hex << std::setfill('0') << std::setw(2)
|
||||||
<< static_cast<int>(c);
|
<< static_cast<int>(c);
|
||||||
|
os.flags(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@@ -36,7 +36,7 @@ namespace Catch {
|
|||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
sprintf_s(buffer, "%.3f", duration);
|
sprintf_s(buffer, "%.3f", duration);
|
||||||
#else
|
#else
|
||||||
sprintf(buffer, "%.3f", duration);
|
std::sprintf(buffer, "%.3f", duration);
|
||||||
#endif
|
#endif
|
||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
}
|
}
|
||||||
|
@@ -245,7 +245,7 @@ public:
|
|||||||
case Unit::Nanoseconds:
|
case Unit::Nanoseconds:
|
||||||
return "ns";
|
return "ns";
|
||||||
case Unit::Microseconds:
|
case Unit::Microseconds:
|
||||||
return "µs";
|
return "us";
|
||||||
case Unit::Milliseconds:
|
case Unit::Milliseconds:
|
||||||
return "ms";
|
return "ms";
|
||||||
case Unit::Seconds:
|
case Unit::Seconds:
|
||||||
|
@@ -76,6 +76,13 @@ namespace Catch {
|
|||||||
void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
|
void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
|
||||||
CumulativeReporterBase::testRunStarting( runInfo );
|
CumulativeReporterBase::testRunStarting( runInfo );
|
||||||
xml.startElement( "testsuites" );
|
xml.startElement( "testsuites" );
|
||||||
|
if( m_config->rngSeed() != 0 ) {
|
||||||
|
xml.startElement( "properties" );
|
||||||
|
xml.scopedElement( "property" )
|
||||||
|
.writeAttribute( "name", "random-seed" )
|
||||||
|
.writeAttribute( "value", m_config->rngSeed() );
|
||||||
|
xml.endElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
|
void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
|
||||||
|
@@ -42,9 +42,9 @@ namespace Catch {
|
|||||||
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
||||||
++counter;
|
++counter;
|
||||||
|
|
||||||
|
stream << "# " << currentTestCaseInfo->name << std::endl;
|
||||||
AssertionPrinter printer( stream, _assertionStats, counter );
|
AssertionPrinter printer( stream, _assertionStats, counter );
|
||||||
printer.print();
|
printer.print();
|
||||||
stream << " # " << currentTestCaseInfo->name ;
|
|
||||||
|
|
||||||
stream << std::endl;
|
stream << std::endl;
|
||||||
return true;
|
return true;
|
||||||
|
@@ -9,6 +9,38 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
std::string escape_arg(const std::string& arg) {
|
||||||
|
if (arg.empty() == false &&
|
||||||
|
arg.find_first_of(" \t\n\v\"") == arg.npos) {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string escaped;
|
||||||
|
escaped.push_back('"');
|
||||||
|
for (auto it = arg.begin(); ; ++it) {
|
||||||
|
int num_backslashes = 0;
|
||||||
|
|
||||||
|
while (it != arg.end() && *it == '\\') {
|
||||||
|
++it;
|
||||||
|
++num_backslashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == arg.end()) {
|
||||||
|
escaped.append(num_backslashes * 2, '\\');
|
||||||
|
break;
|
||||||
|
} else if (*it == '"') {
|
||||||
|
escaped.append(num_backslashes * 2 + 1, '\\');
|
||||||
|
escaped.push_back(*it);
|
||||||
|
} else {
|
||||||
|
escaped.append(num_backslashes, '\\');
|
||||||
|
escaped.push_back(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
escaped.push_back('"');
|
||||||
|
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void create_empty_file(std::string const& path) {
|
void create_empty_file(std::string const& path) {
|
||||||
std::ofstream ofs(path);
|
std::ofstream ofs(path);
|
||||||
@@ -60,8 +92,9 @@ std::string windowsify_path(std::string path) {
|
|||||||
void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
// cmd has already been escaped outside this function.
|
||||||
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
|
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
|
||||||
+ ".bin --quiet " + "--sources " + path + " --cover_children -- " + cmd;
|
+ ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
|
||||||
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
|
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
|
||||||
std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
|
std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
|
||||||
#else // Just for testing, in the real world we will always work under WIN32
|
#else // Just for testing, in the real world we will always work under WIN32
|
||||||
@@ -93,7 +126,7 @@ int main(int argc, char** argv) {
|
|||||||
auto num = parse_log_file_arg(args[1]);
|
auto num = parse_log_file_arg(args[1]);
|
||||||
|
|
||||||
auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
|
auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
|
||||||
return lhs + ' ' + rhs;
|
return lhs + ' ' + escape_arg(rhs);
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -36,6 +36,7 @@ set(TEST_SOURCES
|
|||||||
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
|
||||||
|
${SELF_TEST_DIR}/UsageTests/ToStringOptional.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringVariant.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringVariant.tests.cpp
|
||||||
@@ -101,6 +102,8 @@ set(INTERNAL_HEADERS
|
|||||||
${HEADER_DIR}/internal/catch_external_interfaces.h
|
${HEADER_DIR}/internal/catch_external_interfaces.h
|
||||||
${HEADER_DIR}/internal/catch_fatal_condition.h
|
${HEADER_DIR}/internal/catch_fatal_condition.h
|
||||||
${HEADER_DIR}/internal/catch_generators.hpp
|
${HEADER_DIR}/internal/catch_generators.hpp
|
||||||
|
${HEADER_DIR}/internal/catch_generators_generic.hpp
|
||||||
|
${HEADER_DIR}/internal/catch_generators_specific.hpp
|
||||||
${HEADER_DIR}/internal/catch_impl.hpp
|
${HEADER_DIR}/internal/catch_impl.hpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_capture.h
|
${HEADER_DIR}/internal/catch_interfaces_capture.h
|
||||||
${HEADER_DIR}/internal/catch_interfaces_config.h
|
${HEADER_DIR}/internal/catch_interfaces_config.h
|
||||||
@@ -118,6 +121,7 @@ set(INTERNAL_HEADERS
|
|||||||
${HEADER_DIR}/internal/catch_matchers_string.h
|
${HEADER_DIR}/internal/catch_matchers_string.h
|
||||||
${HEADER_DIR}/internal/catch_matchers_vector.h
|
${HEADER_DIR}/internal/catch_matchers_vector.h
|
||||||
${HEADER_DIR}/internal/catch_message.h
|
${HEADER_DIR}/internal/catch_message.h
|
||||||
|
${HEADER_DIR}/internal/catch_meta.hpp
|
||||||
${HEADER_DIR}/internal/catch_objc.hpp
|
${HEADER_DIR}/internal/catch_objc.hpp
|
||||||
${HEADER_DIR}/internal/catch_objc_arc.hpp
|
${HEADER_DIR}/internal/catch_objc_arc.hpp
|
||||||
${HEADER_DIR}/internal/catch_option.hpp
|
${HEADER_DIR}/internal/catch_option.hpp
|
||||||
@@ -344,10 +348,16 @@ set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No asserti
|
|||||||
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
|
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
|
||||||
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
|
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
|
||||||
|
|
||||||
|
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
|
||||||
|
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
||||||
|
add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
|
||||||
|
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
||||||
|
|
||||||
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
||||||
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||||
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
||||||
|
|
||||||
|
|
||||||
if (CATCH_USE_VALGRIND)
|
if (CATCH_USE_VALGRIND)
|
||||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||||
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||||
|
@@ -14,6 +14,10 @@ Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uar
|
|||||||
Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
|
Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
|
||||||
Compilation.tests.cpp:<line number>: passed:
|
Compilation.tests.cpp:<line number>: passed:
|
||||||
Compilation.tests.cpp:<line number>: passed: h1 == h2 for: [1403 helper] == [1403 helper]
|
Compilation.tests.cpp:<line number>: passed: h1 == h2 for: [1403 helper] == [1403 helper]
|
||||||
|
This would not be caught previously
|
||||||
|
Nor would this
|
||||||
|
Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
|
||||||
|
Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
|
||||||
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
|
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
|
||||||
@@ -57,108 +61,97 @@ Tricky.tests.cpp:<line number>: passed: !is_true<false>::value for: true
|
|||||||
Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true
|
Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true
|
||||||
Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true
|
Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true
|
||||||
Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false
|
Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 101
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 102
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 103
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 104
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 105
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 106
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 107
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 108
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 109
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 110
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 101
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 102
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 103
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 104
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 105
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 106
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 107
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 108
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 109
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 110
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 101
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 102
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 103
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 104
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 105
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 106
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 107
|
Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 108
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 109
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 110
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 101
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 102
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 103
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 104
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 105
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 106
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 107
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 108
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 109
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 110
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 101
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 102
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 103
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 104
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 105
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 106
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 107
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 108
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 109
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 110
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 101
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 102
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 103
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 104
|
Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 105
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 106
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 107
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 108
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 109
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 110
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 101
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 102
|
Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 103
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 104
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 105
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 106
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 107
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 108
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 109
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 110
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 101
|
Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 102
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 103
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 104
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 105
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 106
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 107
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 108
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 109
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 110
|
Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 101
|
Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 102
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 103
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 104
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 105
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 106
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 107
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 108
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 109
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 110
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 101
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 102
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 103
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 104
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 105
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 106
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 107
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 108
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 109
|
|
||||||
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 110
|
|
||||||
Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world"
|
Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world"
|
||||||
Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello"
|
Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello"
|
||||||
|
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
|
||||||
|
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
|
||||||
|
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
|
||||||
|
Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
|
||||||
|
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
|
||||||
|
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
|
||||||
|
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
|
||||||
|
Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
|
||||||
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0 == 2
|
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0 == 2
|
||||||
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0f == 2
|
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0f == 2
|
||||||
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1 == 2
|
Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1 == 2
|
||||||
@@ -167,6 +160,10 @@ Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for:
|
|||||||
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>: failed: m_a == 2 for: 1 == 2
|
Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
|
||||||
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
|
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
|
||||||
|
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
|
||||||
|
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
|
||||||
|
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
|
||||||
|
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
|
||||||
Approx.tests.cpp:<line number>: passed: d == 1.23_a for: 1.23 == Approx( 1.23 )
|
Approx.tests.cpp:<line number>: passed: d == 1.23_a for: 1.23 == Approx( 1.23 )
|
||||||
Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 )
|
Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 )
|
||||||
Approx.tests.cpp:<line number>: passed: -d == -1.23_a for: -1.23 == Approx( -1.23 )
|
Approx.tests.cpp:<line number>: passed: -d == -1.23_a for: -1.23 == Approx( -1.23 )
|
||||||
@@ -406,48 +403,180 @@ Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, 0.f)
|
|||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
|
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0)
|
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0)
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error
|
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 8'
|
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 9'
|
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 10'
|
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 2'
|
Generators.tests.cpp:<line number>: passed: filter([] (int) {return false; }, value(1)), Catch::GeneratorException
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 3.141'
|
Generators.tests.cpp:<line number>: passed: i < 4 for: 1 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 1.379'
|
Generators.tests.cpp:<line number>: passed: i < 4 for: 2 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 8'
|
Generators.tests.cpp:<line number>: passed: i < 4 for: 3 < 4
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 9'
|
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 10'
|
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 2'
|
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 3.141'
|
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 1.379'
|
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 8'
|
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 9'
|
Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 10'
|
Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 2'
|
Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 3.141'
|
Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
|
||||||
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 1.379'
|
Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2
|
Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 2 for: 2 == 2
|
Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 1 == 1
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 4 for: 4 == 4
|
Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3
|
Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[2] == 4 for: 4 == 4
|
Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 3 == 3
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[3] == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 4 for: 4 == 4
|
Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 1 == 1
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: chunk2.front() < 3 for: 1 < 3
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 2 for: 2 == 2
|
Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[2] == 9 for: 9 == 9
|
Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 2 == 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[3] == 7 for: 7 == 7
|
Generators.tests.cpp:<line number>: passed: chunk2.front() < 3 for: 2 < 3
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2
|
Generators.tests.cpp:<line number>: passed: chunk(2, value(1)), Catch::GeneratorException
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3
|
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 1
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2
|
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 1
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: base->size() == 4 for: 4 == 4
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 3
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: typed for: 0x<hex digits>
|
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: typed->size() == 4 for: 4 == 4
|
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: (*typed)[0] == 7 for: 7 == 7
|
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 2
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: (*typed)[3] == 11 for: 11 == 11
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 2
|
||||||
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 3
|
||||||
|
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 3
|
||||||
|
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 3
|
||||||
|
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
|
||||||
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
|
||||||
|
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4 for: 4 == 4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get().size() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "aa" for: "aa" == "aa"
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "bb" for: "bb" == "bb"
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "cc" for: "cc" == "cc"
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2.0 for: 2.0 == 2.0
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4.0 for: 4.0 == 4.0
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 6.0 for: 6.0 == 6.0
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -2 for: -2 == -2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.22 ) for: 1.23 >= Approx( 1.22 )
|
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.22 ) for: 1.23 >= Approx( 1.22 )
|
||||||
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.23 ) for: 1.23 >= Approx( 1.23 )
|
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.23 ) for: 1.23 >= Approx( 1.23 )
|
||||||
Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))
|
Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))
|
||||||
@@ -750,6 +879,9 @@ CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--use-colour", "no"
|
|||||||
CmdLine.tests.cpp:<line number>: passed: config.useColour == UseColour::No for: 2 == 2
|
CmdLine.tests.cpp:<line number>: passed: config.useColour == UseColour::No for: 2 == 2
|
||||||
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
||||||
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of"
|
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of"
|
||||||
|
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 3 >= 1
|
||||||
|
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 2 >= 1
|
||||||
|
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 1 >= 1
|
||||||
Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy!
|
Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy!
|
||||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively
|
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively
|
||||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
|
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
|
||||||
@@ -1019,69 +1151,6 @@ PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false
|
|||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() for: true
|
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() for: true
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true
|
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isSuccessfullyCompleted() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.index() == 1 for: 1 == 1
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.index() == 1 for: 1 == 1
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2b.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2.isSuccessfullyCompleted() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.index() == 0 for: 0 == 0
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2b.isOpen() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() == false for: false == false
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase3.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1c.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1c.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1c.index() == 1 for: 1 == 1
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2c.isOpen() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s2c.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: g1c.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: s1c.isComplete() for: true
|
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase3.isComplete() for: true
|
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
|
||||||
Approx.tests.cpp:<line number>: passed: d == approx( 1.23 ) for: 1.23 == Approx( 1.23 )
|
Approx.tests.cpp:<line number>: passed: d == approx( 1.23 ) for: 1.23 == Approx( 1.23 )
|
||||||
Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 )
|
Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 )
|
||||||
@@ -1216,6 +1285,7 @@ Misc.tests.cpp:<line number>: passed:
|
|||||||
Misc.tests.cpp:<line number>: passed:
|
Misc.tests.cpp:<line number>: passed:
|
||||||
loose text artifact
|
loose text artifact
|
||||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Previous info should not be seen'
|
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Previous info should not be seen'
|
||||||
|
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'previous unscoped info SHOULD not be seen'
|
||||||
Misc.tests.cpp:<line number>: passed: l == std::numeric_limits<long long>::max() for: 9223372036854775807 (0x<hex digits>)
|
Misc.tests.cpp:<line number>: passed: l == std::numeric_limits<long long>::max() for: 9223372036854775807 (0x<hex digits>)
|
||||||
==
|
==
|
||||||
9223372036854775807 (0x<hex digits>)
|
9223372036854775807 (0x<hex digits>)
|
||||||
@@ -1237,6 +1307,8 @@ Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 mes
|
|||||||
Misc.tests.cpp:<line number>: passed: ( fib[i] % 2 ) == 0 for: 0 == 0 with 1 message: 'Testing if fib[5] (8) is even'
|
Misc.tests.cpp:<line number>: passed: ( fib[i] % 2 ) == 0 for: 0 == 0 with 1 message: 'Testing if fib[5] (8) is even'
|
||||||
Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[6] (13) is even'
|
Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[6] (13) is even'
|
||||||
Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[7] (21) is even'
|
Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[7] (21) is even'
|
||||||
|
Message.tests.cpp:<line number>: warning: 'info' with 2 messages: 'unscoped info' and 'and warn may mix'
|
||||||
|
Message.tests.cpp:<line number>: warning: 'info' with 2 messages: 'unscoped info' and 'they are not cleared after warnings'
|
||||||
Misc.tests.cpp:<line number>: failed: a == b for: 1 == 2
|
Misc.tests.cpp:<line number>: failed: a == b for: 1 == 2
|
||||||
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
||||||
Misc.tests.cpp:<line number>: passed: a < b for: 1 < 2
|
Misc.tests.cpp:<line number>: passed: a < b for: 1 < 2
|
||||||
@@ -1246,6 +1318,9 @@ Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
|||||||
Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7"
|
Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7"
|
||||||
Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?}
|
Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?}
|
||||||
Misc.tests.cpp:<line number>: passed:
|
Misc.tests.cpp:<line number>: passed:
|
||||||
|
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen only for the FIRST assertion IF info is printed for passing assertions'
|
||||||
|
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen only for the SECOND assertion IF info is printed for passing assertions'
|
||||||
|
Message.tests.cpp:<line number>: failed: false with 1 message: 'this SHOULD be seen'
|
||||||
Misc.tests.cpp:<line number>: passed: makeString( false ) != static_cast<char*>(0) for: "valid string" != {null string}
|
Misc.tests.cpp:<line number>: passed: makeString( false ) != static_cast<char*>(0) for: "valid string" != {null string}
|
||||||
Misc.tests.cpp:<line number>: passed: makeString( true ) == static_cast<char*>(0) for: {null string} == {null string}
|
Misc.tests.cpp:<line number>: passed: makeString( true ) == static_cast<char*>(0) for: {null string} == {null string}
|
||||||
Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
|
Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
|
||||||
@@ -1253,6 +1328,12 @@ ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair )
|
|||||||
==
|
==
|
||||||
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||||
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
||||||
|
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions'
|
||||||
|
Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
|
||||||
|
Message.tests.cpp:<line number>: failed: false with 1 message: 'this SHOULD be seen only ONCE'
|
||||||
|
Message.tests.cpp:<line number>: passed: true
|
||||||
|
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY also be seen only ONCE IF info is printed for passing assertions'
|
||||||
|
Message.tests.cpp:<line number>: passed: true
|
||||||
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
||||||
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
|
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
|
||||||
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
||||||
@@ -1272,6 +1353,8 @@ String.tests.cpp:<line number>: passed: Catch::replaceInPlace( s, "'", "|'" ) fo
|
|||||||
String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||||
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
|
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
|
||||||
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
|
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
|
||||||
|
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 1 to 3...' and '1' and '2' and '3'
|
||||||
|
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 4 to 6...' and '4' and '5' and '6'
|
||||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }"
|
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }"
|
||||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" for: "{ { "one", 1 } }" == "{ { "one", 1 } }"
|
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" for: "{ { "one", 1 } }" == "{ { "one", 1 } }"
|
||||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" for: "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
|
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" for: "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
|
||||||
@@ -1322,6 +1405,10 @@ Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 =
|
|||||||
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
|
||||||
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 5 == 5
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 5 == 5
|
||||||
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 4 == 4
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 4 == 4
|
||||||
|
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 5 == 5
|
||||||
|
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
|
||||||
|
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 5 == 5
|
||||||
|
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
|
||||||
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
|
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
|
||||||
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
|
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
|
||||||
@@ -1389,5 +1476,5 @@ Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
|
|||||||
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
|
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
|
||||||
Misc.tests.cpp:<line number>: passed:
|
Misc.tests.cpp:<line number>: passed:
|
||||||
Misc.tests.cpp:<line number>: passed:
|
Misc.tests.cpp:<line number>: passed:
|
||||||
Failed 65 test cases, failed 125 assertions.
|
Failed 77 test cases, failed 138 assertions.
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
This would not be caught previously
|
||||||
|
Nor would this
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
<exe-name> is a <version> host application.
|
<exe-name> is a <version> host application.
|
||||||
@@ -5,6 +7,16 @@ Run with -? for options
|
|||||||
|
|
||||||
Randomness seeded to: 1
|
Randomness seeded to: 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
#1514: stderr/stdout is not captured in tests aborted by an exception
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Tricky.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Tricky.tests.cpp:<line number>: FAILED:
|
||||||
|
explicitly with message:
|
||||||
|
1514
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
#748 - captures with unexpected exceptions
|
#748 - captures with unexpected exceptions
|
||||||
outside assertions
|
outside assertions
|
||||||
@@ -92,6 +104,54 @@ Class.tests.cpp:<line number>: FAILED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
"hello" == "world"
|
"hello" == "world"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo
|
||||||
|
<float>
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Class.tests.cpp:<line number>: FAILED:
|
||||||
|
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
|
||||||
|
with expansion:
|
||||||
|
0 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo
|
||||||
|
<int>
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Class.tests.cpp:<line number>: FAILED:
|
||||||
|
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
|
||||||
|
with expansion:
|
||||||
|
0 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector
|
||||||
|
<float>
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Class.tests.cpp:<line number>: FAILED:
|
||||||
|
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
|
||||||
|
with expansion:
|
||||||
|
0 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector
|
||||||
|
<int>
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Class.tests.cpp:<line number>: FAILED:
|
||||||
|
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
|
||||||
|
with expansion:
|
||||||
|
0 == 1
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
A TEMPLATE_TEST_CASE_METHOD based test run that fails - double
|
A TEMPLATE_TEST_CASE_METHOD based test run that fails - double
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@@ -996,6 +1056,16 @@ Message.tests.cpp:<line number>: FAILED:
|
|||||||
explicitly with message:
|
explicitly with message:
|
||||||
Previous info should not be seen
|
Previous info should not be seen
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
just failure after unscoped info
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: FAILED:
|
||||||
|
explicitly with message:
|
||||||
|
previous unscoped info SHOULD not be seen
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
looped SECTION tests
|
looped SECTION tests
|
||||||
b is currently: 0
|
b is currently: 0
|
||||||
@@ -1068,6 +1138,18 @@ with expansion:
|
|||||||
with message:
|
with message:
|
||||||
Testing if fib[7] (21) is even
|
Testing if fib[7] (21) is even
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
mix info, unscoped info and warning
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: warning:
|
||||||
|
and warn may mix
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: warning:
|
||||||
|
they are not cleared after warnings
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
more nested SECTION tests
|
more nested SECTION tests
|
||||||
doesn't equal
|
doesn't equal
|
||||||
@@ -1081,6 +1163,40 @@ Misc.tests.cpp:<line number>: FAILED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
1 == 2
|
1 == 2
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
not prints unscoped info from previous failures
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: FAILED:
|
||||||
|
REQUIRE( false )
|
||||||
|
with message:
|
||||||
|
this SHOULD be seen
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
prints unscoped info on failure
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: FAILED:
|
||||||
|
REQUIRE( false )
|
||||||
|
with messages:
|
||||||
|
this SHOULD be seen
|
||||||
|
this SHOULD also be seen
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
prints unscoped info only for the first assertion
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK( false )
|
||||||
|
with message:
|
||||||
|
this SHOULD be seen only ONCE
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
send a single char to INFO
|
send a single char to INFO
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@@ -1104,6 +1220,28 @@ with messages:
|
|||||||
hi
|
hi
|
||||||
i := 7
|
i := 7
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
stacks unscoped info in loops
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK( false )
|
||||||
|
with messages:
|
||||||
|
Count 1 to 3...
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
|
||||||
|
Message.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK( false )
|
||||||
|
with messages:
|
||||||
|
Count 4 to 6...
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
string literals of different sizes can be compared
|
string literals of different sizes can be compared
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@@ -1126,6 +1264,6 @@ due to unexpected exception with message:
|
|||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 228 | 172 passed | 52 failed | 4 failed as expected
|
test cases: 255 | 189 passed | 62 failed | 4 failed as expected
|
||||||
assertions: 1310 | 1178 passed | 111 failed | 21 failed as expected
|
assertions: 1393 | 1250 passed | 122 failed | 21 failed as expected
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -133,6 +133,29 @@ Compilation.tests.cpp:<line number>: PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
[1403 helper] == [1403 helper]
|
[1403 helper] == [1403 helper]
|
||||||
|
|
||||||
|
This would not be caught previously
|
||||||
|
Nor would this
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
#1514: stderr/stdout is not captured in tests aborted by an exception
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Tricky.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Tricky.tests.cpp:<line number>: FAILED:
|
||||||
|
explicitly with message:
|
||||||
|
1514
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
#1548
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Compilation.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Compilation.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( std::is_same<TypeList<int>, TypeList<int>>::value )
|
||||||
|
with expansion:
|
||||||
|
true
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
#748 - captures with unexpected exceptions
|
#748 - captures with unexpected exceptions
|
||||||
outside assertions
|
outside assertions
|
||||||
@@ -317,12 +340,7 @@ Condition.tests.cpp:<line number>: FAILED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
false
|
false
|
||||||
|
|
||||||
Condition.tests.cpp:<line number>: FAILED:
|
|
||||||
CHECK_FALSE( true )
|
|
||||||
with expansion:
|
|
||||||
!true
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 15 | 12 passed | 1 failed | 2 failed as expected
|
test cases: 17 | 13 passed | 2 failed | 2 failed as expected
|
||||||
assertions: 39 | 32 passed | 4 failed | 3 failed as expected
|
assertions: 40 | 33 passed | 4 failed | 3 failed as expected
|
||||||
|
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesloose text artifact
|
<testsuites>
|
||||||
>
|
<properties>
|
||||||
<testsuite name="<exe-name>" errors="17" failures="109" tests="1325" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<property name="random-seed" value="1"/>
|
||||||
|
</properties>
|
||||||
|
loose text artifact
|
||||||
|
<testsuite name="<exe-name>" errors="17" failures="122" tests="1410" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
||||||
@@ -10,6 +13,19 @@
|
|||||||
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.(Fixture_1245<int, int>)" name="#1245" time="{duration}"/>
|
<testcase classname="<exe-name>.(Fixture_1245<int, int>)" name="#1245" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1403" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1403" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="#1514: stderr/stdout is not captured in tests aborted by an exception" time="{duration}">
|
||||||
|
<failure type="FAIL">
|
||||||
|
1514
|
||||||
|
Tricky.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
<system-out>
|
||||||
|
This would not be caught previously
|
||||||
|
</system-out>
|
||||||
|
<system-err>
|
||||||
|
Nor would this
|
||||||
|
</system-err>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="#1548" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
||||||
<error type="TEST_CASE">
|
<error type="TEST_CASE">
|
||||||
expected exception
|
expected exception
|
||||||
@@ -70,13 +86,37 @@ Condition.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="10x10 ints" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="3x3x3 ints" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
|
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
|
||||||
<failure message=""hello" == "world"" type="REQUIRE">
|
<failure message=""hello" == "world"" type="REQUIRE">
|
||||||
Class.tests.cpp:<line number>
|
Class.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
|
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo<float>" time="{duration}">
|
||||||
|
<failure message="0 == 1" type="REQUIRE">
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo<int>" time="{duration}">
|
||||||
|
<failure message="0 == 1" type="REQUIRE">
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector<float>" time="{duration}">
|
||||||
|
<failure message="0 == 1" type="REQUIRE">
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector<int>" time="{duration}">
|
||||||
|
<failure message="0 == 1" type="REQUIRE">
|
||||||
|
Class.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo<float>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo<int>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector<float>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector<int>" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - double" time="{duration}">
|
<testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - double" time="{duration}">
|
||||||
<failure message="1.0 == 2" type="REQUIRE">
|
<failure message="1.0 == 2" type="REQUIRE">
|
||||||
Class.tests.cpp:<line number>
|
Class.tests.cpp:<line number>
|
||||||
@@ -101,6 +141,10 @@ Class.tests.cpp:<line number>
|
|||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
|
<testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="A Template product test case - Foo<float>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="A Template product test case - Foo<int>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="A Template product test case - std::vector<float>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="A Template product test case - std::vector<int>" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="A comparison that uses literals instead of the normal constructor" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="A comparison that uses literals instead of the normal constructor" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="A couple of nested sections followed by a failure" time="{duration}">
|
<testcase classname="<exe-name>.global" name="A couple of nested sections followed by a failure" time="{duration}">
|
||||||
<failure type="FAIL">
|
<failure type="FAIL">
|
||||||
@@ -311,14 +355,35 @@ Message.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators/one" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Basic usage" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators/two" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Throws if there are no matching values" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators impl/range" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators impl/fixed values" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Same type" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators impl/combined" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Different type" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators impl/values" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Repeating a generator" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators impl/values2" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is divisible by chunk size" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Generators impl/type erasure" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is not divisible by chunk size" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Throws on too small generators" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators -- simple/one" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators -- simple/two" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Preset values" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Generator combinator" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Explicitly typed generator sequence" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Filter generator" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take less" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take more" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Map" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Singular repeat" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Actual repeat" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Positive auto step/Integer" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Negative auto step/Integer" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Positive manual step/Integer/Exact" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Positive manual step/Integer/Slightly over end" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Positive manual step/Integer/Slightly under end" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Negative manual step/Integer/Exact" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Negative manual step/Integer/Slightly over end" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators internals/Range/Negative manual step/Integer/Slightly under end" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
|
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
|
||||||
@@ -526,6 +591,9 @@ Message.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/yes" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/yes" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/no" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/no" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/error" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/error" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple<int, double, float>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple<int, double>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple<int>" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Reconstruction should be based on stringification: #914" time="{duration}">
|
<testcase classname="<exe-name>.global" name="Reconstruction should be based on stringification: #914" time="{duration}">
|
||||||
<failure message="Hey, its truthy!" type="CHECK">
|
<failure message="Hey, its truthy!" type="CHECK">
|
||||||
Decomposition.tests.cpp:<line number>
|
Decomposition.tests.cpp:<line number>
|
||||||
@@ -660,13 +728,6 @@ Exception.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/open a nested section" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Tracker/open a nested section" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator/close outer section" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator/close outer section/Re-enter for second generation" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Start a new inner section" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Start a new inner section/Re-enter for second generation" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Fail an inner section" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Tracker/start a generator/Fail an inner section/Re-enter for second generation" time="{duration}"/>
|
|
||||||
<testcase classname="<exe-name>.global" name="Unexpected exceptions can be translated" time="{duration}">
|
<testcase classname="<exe-name>.global" name="Unexpected exceptions can be translated" time="{duration}">
|
||||||
<error type="TEST_CASE">
|
<error type="TEST_CASE">
|
||||||
3.14
|
3.14
|
||||||
@@ -804,6 +865,12 @@ Misc.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="just failure" time="{duration}">
|
<testcase classname="<exe-name>.global" name="just failure" time="{duration}">
|
||||||
<failure type="FAIL">
|
<failure type="FAIL">
|
||||||
Previous info should not be seen
|
Previous info should not be seen
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="just failure after unscoped info" time="{duration}">
|
||||||
|
<failure type="FAIL">
|
||||||
|
previous unscoped info SHOULD not be seen
|
||||||
Message.tests.cpp:<line number>
|
Message.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
@@ -852,6 +919,7 @@ Testing if fib[7] (21) is even
|
|||||||
Misc.tests.cpp:<line number>
|
Misc.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="mix info, unscoped info and warning" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="more nested SECTION tests/equal/doesn't equal" time="{duration}">
|
<testcase classname="<exe-name>.global" name="more nested SECTION tests/equal/doesn't equal" time="{duration}">
|
||||||
<failure message="1 == 2" type="REQUIRE">
|
<failure message="1 == 2" type="REQUIRE">
|
||||||
Misc.tests.cpp:<line number>
|
Misc.tests.cpp:<line number>
|
||||||
@@ -864,10 +932,30 @@ Misc.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="non streamable - with conv. op" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="non streamable - with conv. op" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="non-copyable objects" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="non-copyable objects" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="not allowed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="not allowed" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="not prints unscoped info from previous failures" time="{duration}">
|
||||||
|
<failure message="false" type="REQUIRE">
|
||||||
|
this SHOULD be seen
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
<testcase classname="<exe-name>.global" name="null strings" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="null strings" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="null_ptr" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="null_ptr" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="pair<pair<int,const char *,pair<std::string,int> > -> toString" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="pair<pair<int,const char *,pair<std::string,int> > -> toString" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="pointer to class" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="pointer to class" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="print unscoped info if passing unscoped info is printed" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="prints unscoped info on failure" time="{duration}">
|
||||||
|
<failure message="false" type="REQUIRE">
|
||||||
|
this SHOULD be seen
|
||||||
|
this SHOULD also be seen
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="prints unscoped info only for the first assertion" time="{duration}">
|
||||||
|
<failure message="false" type="CHECK">
|
||||||
|
this SHOULD be seen only ONCE
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
<testcase classname="<exe-name>.global" name="random SECTION tests/doesn't equal" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="random SECTION tests/doesn't equal" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="random SECTION tests/not equal" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="random SECTION tests/not equal" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="replaceInPlace/replace single char" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="replaceInPlace/replace single char" time="{duration}"/>
|
||||||
@@ -887,6 +975,22 @@ Misc.tests.cpp:<line number>
|
|||||||
<failure message="false" type="REQUIRE">
|
<failure message="false" type="REQUIRE">
|
||||||
hi
|
hi
|
||||||
i := 7
|
i := 7
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="stacks unscoped info in loops" time="{duration}">
|
||||||
|
<failure message="false" type="CHECK">
|
||||||
|
Count 1 to 3...
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
Message.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
<failure message="false" type="CHECK">
|
||||||
|
Count 4 to 6...
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
Message.tests.cpp:<line number>
|
Message.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
@@ -914,6 +1018,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker_and_operator> )" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker_and_operator> )" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_operator> )" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="stringify( vectors<has_operator> )" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="strlen3" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="strlen3" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="tables" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
|
<testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
|
||||||
<error type="TEST_CASE">
|
<error type="TEST_CASE">
|
||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
@@ -948,11 +1053,13 @@ Exception.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="xmlentitycheck/embedded xml: <test>it should be possible to embed xml characters, such as <, " or &, or even whole <xml>documents</xml> within an attribute</test>" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="xmlentitycheck/embedded xml: <test>it should be possible to embed xml characters, such as <, " or &, or even whole <xml>documents</xml> within an attribute</test>" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="xmlentitycheck/encoded chars: these should all be encoded: &&&"""<<<&"<<&"" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="xmlentitycheck/encoded chars: these should all be encoded: &&&"""<<<&"<<&"" time="{duration}"/>
|
||||||
<system-out>
|
<system-out>
|
||||||
|
This would not be caught previously
|
||||||
A string sent directly to stdout
|
A string sent directly to stdout
|
||||||
Message from section one
|
Message from section one
|
||||||
Message from section two
|
Message from section two
|
||||||
</system-out>
|
</system-out>
|
||||||
<system-err>
|
<system-err>
|
||||||
|
Nor would this
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
A string sent to stderr via clog
|
A string sent to stderr via clog
|
||||||
</system-err>
|
</system-err>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,93 +1,209 @@
|
|||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
// Tests of generartor implementation details
|
// Tests of generator implementation details
|
||||||
|
TEST_CASE("Generators internals", "[generators][internals]") {
|
||||||
TEST_CASE("Generators impl", "[impl]") {
|
|
||||||
using namespace Catch::Generators;
|
using namespace Catch::Generators;
|
||||||
|
|
||||||
SECTION( "range" ) {
|
SECTION("Single value") {
|
||||||
auto gen = range(1,3);
|
auto gen = value(123);
|
||||||
|
REQUIRE(gen.get() == 123);
|
||||||
CHECK( gen.size() == 2 );
|
REQUIRE_FALSE(gen.next());
|
||||||
|
|
||||||
CHECK( gen[0] == 1 );
|
|
||||||
CHECK( gen[1] == 2 );
|
|
||||||
}
|
}
|
||||||
SECTION( "fixed values" ) {
|
SECTION("Preset values") {
|
||||||
auto gen = values( { 3, 1, 4, 1 } );
|
auto gen = values({ 1, 3, 5 });
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
CHECK( gen.size() == 4 );
|
REQUIRE(gen.next());
|
||||||
CHECK( gen[0] == 3 );
|
REQUIRE(gen.get() == 3);
|
||||||
CHECK( gen[1] == 1 );
|
REQUIRE(gen.next());
|
||||||
CHECK( gen[2] == 4 );
|
REQUIRE(gen.get() == 5);
|
||||||
CHECK( gen[3] == 1 );
|
REQUIRE_FALSE(gen.next());
|
||||||
}
|
}
|
||||||
SECTION( "combined" ) {
|
SECTION("Generator combinator") {
|
||||||
auto gen = makeGenerators( range( 1, 3 ), values( { 9, 7 } ) );
|
auto gen = makeGenerators(1, 5, values({ 2, 4 }), 0);
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 5);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 4);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 0);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Explicitly typed generator sequence") {
|
||||||
|
auto gen = makeGenerators(as<std::string>{}, "aa", "bb", "cc");
|
||||||
|
// This just checks that the type is std::string:
|
||||||
|
REQUIRE(gen.get().size() == 2);
|
||||||
|
// Iterate over the generator
|
||||||
|
REQUIRE(gen.get() == "aa");
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == "bb");
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == "cc");
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Filter generator") {
|
||||||
|
// Normal usage
|
||||||
|
auto gen = filter([] (int i) { return i != 2; }, values({ 2, 1, 2, 3, 2, 2 }));
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 3);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
|
||||||
CHECK( gen.size() == 4 );
|
// Completely filtered-out generator should throw on construction
|
||||||
CHECK( gen[0] == 1 );
|
REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), Catch::GeneratorException);
|
||||||
CHECK( gen[1] == 2 );
|
}
|
||||||
CHECK( gen[2] == 9 );
|
SECTION("Take generator") {
|
||||||
CHECK( gen[3] == 7 );
|
SECTION("Take less") {
|
||||||
|
auto gen = take(2, values({ 1, 2, 3 }));
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Take more") {
|
||||||
|
auto gen = take(2, value(1));
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Map") {
|
||||||
|
auto gen = map<double>([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
|
||||||
|
REQUIRE(gen.get() == 2.0);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 4.0);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 6.0);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Repeat") {
|
||||||
|
SECTION("Singular repeat") {
|
||||||
|
auto gen = repeat(1, value(3));
|
||||||
|
REQUIRE(gen.get() == 3);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Actual repeat") {
|
||||||
|
auto gen = repeat(2, values({ 1, 2, 3 }));
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 3);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 3);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Range") {
|
||||||
|
SECTION("Positive auto step") {
|
||||||
|
SECTION("Integer") {
|
||||||
|
auto gen = range(-2, 2);
|
||||||
|
REQUIRE(gen.get() == -2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 0);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Negative auto step") {
|
||||||
|
SECTION("Integer") {
|
||||||
|
auto gen = range(2, -2);
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 0);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Positive manual step") {
|
||||||
|
SECTION("Integer") {
|
||||||
|
SECTION("Exact") {
|
||||||
|
auto gen = range(-7, 5, 3);
|
||||||
|
REQUIRE(gen.get() == -7);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -4);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Slightly over end") {
|
||||||
|
auto gen = range(-7, 4, 3);
|
||||||
|
REQUIRE(gen.get() == -7);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -4);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Slightly under end") {
|
||||||
|
auto gen = range(-7, 6, 3);
|
||||||
|
REQUIRE(gen.get() == -7);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -4);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 5);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Negative manual step") {
|
||||||
|
SECTION("Integer") {
|
||||||
|
SECTION("Exact") {
|
||||||
|
auto gen = range(5, -7, -3);
|
||||||
|
REQUIRE(gen.get() == 5);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -4);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Slightly over end") {
|
||||||
|
auto gen = range(5, -6, -3);
|
||||||
|
REQUIRE(gen.get() == 5);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -4);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Slightly under end") {
|
||||||
|
auto gen = range(5, -8, -3);
|
||||||
|
REQUIRE(gen.get() == 5);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == 2);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -1);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -4);
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
REQUIRE(gen.get() == -7);
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION( "values" ) {
|
|
||||||
auto gen = makeGenerators( 3, 1 );
|
|
||||||
|
|
||||||
CHECK( gen.size() == 2 );
|
|
||||||
CHECK( gen[0] == 3 );
|
|
||||||
CHECK( gen[1] == 1 );
|
|
||||||
}
|
|
||||||
SECTION( "values2" ) {
|
|
||||||
auto gen = makeGenerators( 3, 1 );
|
|
||||||
|
|
||||||
CHECK( gen.size() == 2 );
|
|
||||||
CHECK( gen[0] == 3 );
|
|
||||||
CHECK( gen[1] == 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SECTION( "type erasure" ) {
|
|
||||||
auto gen = makeGenerators( range( 7, 10 ), 11 );
|
|
||||||
|
|
||||||
// Make type erased version
|
|
||||||
auto dynCopy = pf::make_unique<Generators<int>>( std::move( gen ) );
|
|
||||||
std::unique_ptr<GeneratorBase const> base = std::move( dynCopy );
|
|
||||||
|
|
||||||
// Only thing we can do is ask for the size
|
|
||||||
CHECK( base->size() == 4 );
|
|
||||||
|
|
||||||
// Restore typed version
|
|
||||||
auto typed = dynamic_cast<Generators<int> const*>( base.get() );
|
|
||||||
REQUIRE( typed );
|
|
||||||
CHECK( typed->size() == 4 );
|
|
||||||
CHECK( (*typed)[0] == 7 );
|
|
||||||
CHECK( (*typed)[3] == 11 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Generators impl - random", "[approvals]") {
|
|
||||||
using namespace Catch::Generators;
|
|
||||||
|
|
||||||
SECTION( "random range" ) {
|
|
||||||
auto gen = random( 3, 9 );
|
|
||||||
|
|
||||||
CHECK( gen.size() == 6 );
|
|
||||||
for( size_t i = 0; i < 6; ++i ) {
|
|
||||||
CHECK( gen[i] >= 3 );
|
|
||||||
CHECK( gen[i] <= 8 );
|
|
||||||
if( i > 0 )
|
|
||||||
CHECK( gen[i] != gen[i-1] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SECTION( "random selection" ) {
|
|
||||||
auto gen = random<int>( 10 );
|
|
||||||
|
|
||||||
CHECK( gen.size() == 10 );
|
|
||||||
for( size_t i = 0; i < 10; ++i ) {
|
|
||||||
if( i > 0 )
|
|
||||||
CHECK( gen[i] != gen[i-1] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -173,154 +173,34 @@ TEST_CASE( "Tracker" ) {
|
|||||||
testCase.close();
|
testCase.close();
|
||||||
REQUIRE( testCase.isComplete() );
|
REQUIRE( testCase.isComplete() );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION( "start a generator" ) {
|
static bool previouslyRun = false;
|
||||||
IndexTracker& g1 = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
|
static bool previouslyRunNested = false;
|
||||||
REQUIRE( g1.isOpen() );
|
|
||||||
REQUIRE( g1.index() == 0 );
|
|
||||||
|
|
||||||
REQUIRE( g1.isComplete() == false );
|
TEST_CASE( "#1394", "[.][approvals][tracker]" ) {
|
||||||
REQUIRE( s1.isComplete() == false );
|
// -- Don't re-run after specified section is done
|
||||||
|
REQUIRE(previouslyRun == false);
|
||||||
|
|
||||||
SECTION( "close outer section" )
|
SECTION( "RunSection" ) {
|
||||||
{
|
previouslyRun = true;
|
||||||
s1.close();
|
|
||||||
REQUIRE( s1.isComplete() == false );
|
|
||||||
testCase.close();
|
|
||||||
REQUIRE( testCase.isSuccessfullyCompleted() == false );
|
|
||||||
|
|
||||||
SECTION( "Re-enter for second generation" ) {
|
|
||||||
ctx.startCycle();
|
|
||||||
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
||||||
REQUIRE( testCase2.isOpen() );
|
|
||||||
|
|
||||||
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
||||||
REQUIRE( s1b.isOpen() );
|
|
||||||
|
|
||||||
|
|
||||||
IndexTracker& g1b = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
|
|
||||||
REQUIRE( g1b.isOpen() );
|
|
||||||
REQUIRE( g1b.index() == 1 );
|
|
||||||
|
|
||||||
REQUIRE( s1.isComplete() == false );
|
|
||||||
|
|
||||||
s1b.close();
|
|
||||||
REQUIRE( s1b.isComplete() );
|
|
||||||
REQUIRE( g1b.isComplete() );
|
|
||||||
testCase2.close();
|
|
||||||
REQUIRE( testCase2.isComplete() );
|
|
||||||
}
|
}
|
||||||
}
|
SECTION( "SkipSection" ) {
|
||||||
SECTION( "Start a new inner section" ) {
|
// cause an error if this section is called because it shouldn't be
|
||||||
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
REQUIRE(1 == 0);
|
||||||
REQUIRE( s2.isOpen() );
|
}
|
||||||
|
}
|
||||||
s2.close();
|
|
||||||
REQUIRE( s2.isComplete() );
|
TEST_CASE( "#1394 nested", "[.][approvals][tracker]" ) {
|
||||||
|
REQUIRE(previouslyRunNested == false);
|
||||||
s1.close();
|
|
||||||
REQUIRE( s1.isComplete() == false );
|
SECTION( "NestedRunSection" ) {
|
||||||
|
SECTION( "s1" ) {
|
||||||
testCase.close();
|
previouslyRunNested = true;
|
||||||
REQUIRE( testCase.isComplete() == false );
|
}
|
||||||
|
}
|
||||||
SECTION( "Re-enter for second generation" ) {
|
SECTION( "NestedSkipSection" ) {
|
||||||
ctx.startCycle();
|
// cause an error if this section is called because it shouldn't be
|
||||||
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
REQUIRE(1 == 0);
|
||||||
REQUIRE( testCase2.isOpen() );
|
|
||||||
|
|
||||||
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
||||||
REQUIRE( s1b.isOpen() );
|
|
||||||
|
|
||||||
// generator - next value
|
|
||||||
IndexTracker& g1b = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
|
|
||||||
REQUIRE( g1b.isOpen() );
|
|
||||||
REQUIRE( g1b.index() == 1 );
|
|
||||||
|
|
||||||
// inner section again
|
|
||||||
ITracker& s2b = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
||||||
REQUIRE( s2b.isOpen() );
|
|
||||||
|
|
||||||
s2b.close();
|
|
||||||
REQUIRE( s2b.isComplete() );
|
|
||||||
|
|
||||||
s1b.close();
|
|
||||||
REQUIRE( g1b.isComplete() );
|
|
||||||
REQUIRE( s1b.isComplete() );
|
|
||||||
|
|
||||||
testCase2.close();
|
|
||||||
REQUIRE( testCase2.isComplete() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION( "Fail an inner section" ) {
|
|
||||||
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
||||||
REQUIRE( s2.isOpen() );
|
|
||||||
|
|
||||||
s2.fail();
|
|
||||||
REQUIRE( s2.isComplete() );
|
|
||||||
REQUIRE( s2.isSuccessfullyCompleted() == false );
|
|
||||||
|
|
||||||
s1.close();
|
|
||||||
REQUIRE( s1.isComplete() == false );
|
|
||||||
|
|
||||||
testCase.close();
|
|
||||||
REQUIRE( testCase.isComplete() == false );
|
|
||||||
|
|
||||||
SECTION( "Re-enter for second generation" ) {
|
|
||||||
ctx.startCycle();
|
|
||||||
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
||||||
REQUIRE( testCase2.isOpen() );
|
|
||||||
|
|
||||||
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
||||||
REQUIRE( s1b.isOpen() );
|
|
||||||
|
|
||||||
// generator - still same value
|
|
||||||
IndexTracker& g1b = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
|
|
||||||
REQUIRE( g1b.isOpen() );
|
|
||||||
REQUIRE( g1b.index() == 0 );
|
|
||||||
|
|
||||||
// inner section again - this time won't open
|
|
||||||
ITracker& s2b = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
||||||
REQUIRE( s2b.isOpen() == false );
|
|
||||||
|
|
||||||
s1b.close();
|
|
||||||
REQUIRE( g1b.isComplete() == false );
|
|
||||||
REQUIRE( s1b.isComplete() == false );
|
|
||||||
|
|
||||||
testCase2.close();
|
|
||||||
REQUIRE( testCase2.isComplete() == false );
|
|
||||||
|
|
||||||
// Another cycle - now should complete
|
|
||||||
ctx.startCycle();
|
|
||||||
ITracker& testCase3 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
||||||
REQUIRE( testCase3.isOpen() );
|
|
||||||
|
|
||||||
ITracker& s1c = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
||||||
REQUIRE( s1c.isOpen() );
|
|
||||||
|
|
||||||
// generator - now next value
|
|
||||||
IndexTracker& g1c = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
|
|
||||||
REQUIRE( g1c.isOpen() );
|
|
||||||
REQUIRE( g1c.index() == 1 );
|
|
||||||
|
|
||||||
// inner section - now should open again
|
|
||||||
ITracker& s2c = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
||||||
REQUIRE( s2c.isOpen() );
|
|
||||||
|
|
||||||
s2c.close();
|
|
||||||
REQUIRE( s2c.isComplete() );
|
|
||||||
|
|
||||||
s1c.close();
|
|
||||||
REQUIRE( g1c.isComplete() );
|
|
||||||
REQUIRE( s1c.isComplete() );
|
|
||||||
|
|
||||||
testCase3.close();
|
|
||||||
REQUIRE( testCase3.isComplete() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// !TBD"
|
|
||||||
// nested generator
|
|
||||||
// two sections within a generator
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,18 @@ struct Template_Fixture {
|
|||||||
T m_a;
|
T m_a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Template_Fixture_2 {
|
||||||
|
Template_Fixture_2() {}
|
||||||
|
|
||||||
|
T m_a;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename T>
|
||||||
|
struct Template_Foo {
|
||||||
|
size_t size() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -62,6 +74,11 @@ TEMPLATE_TEST_CASE_METHOD(Template_Fixture, "A TEMPLATE_TEST_CASE_METHOD based t
|
|||||||
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
|
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds","[class][template][product]",(std::vector,Template_Foo),(int,float))
|
||||||
|
{
|
||||||
|
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
// We should be able to write our tests within a different namespace
|
// We should be able to write our tests within a different namespace
|
||||||
namespace Inner
|
namespace Inner
|
||||||
{
|
{
|
||||||
@@ -74,6 +91,11 @@ namespace Inner
|
|||||||
{
|
{
|
||||||
REQUIRE( Template_Fixture<TestType>::m_a == 2 );
|
REQUIRE( Template_Fixture<TestType>::m_a == 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails","[.][class][template][product][failing]",(std::vector,Template_Foo),(int,float))
|
||||||
|
{
|
||||||
|
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -17,6 +17,11 @@ namespace foo {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace bar {
|
||||||
|
template <typename... Ts>
|
||||||
|
struct TypeList {};
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic ignored "-Wmissing-declarations"
|
#pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||||
#endif
|
#endif
|
||||||
@@ -184,6 +189,11 @@ namespace { namespace CompilationTests {
|
|||||||
STATIC_REQUIRE_FALSE( std::is_void<int>::value );
|
STATIC_REQUIRE_FALSE( std::is_void<int>::value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("#1548", "[compilation]") {
|
||||||
|
using namespace bar;
|
||||||
|
REQUIRE(std::is_same<TypeList<int>, TypeList<int>>::value);
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace CompilationTests
|
}} // namespace CompilationTests
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,75 +1,63 @@
|
|||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
// Examples of usage of Generators
|
#include <cstring>
|
||||||
|
|
||||||
// This test doesn't do much - it just shows how you can have several generators, of different
|
|
||||||
// types (ie `i` and `j` are different types), can be sequenced using `,` and
|
|
||||||
// can be expressed as named generators (like range) or as individual values.
|
|
||||||
// Generators can be mixed with SECTIONs.
|
|
||||||
// At time of writing the generated values are not automatically reported as part of the test
|
|
||||||
// name or associated values - so we explicitly CAPTURE then (run this with `-s` to see them).
|
|
||||||
// We could also incorporate them into the section names using DYNAMIC_SECTION. See the BDD
|
|
||||||
// example later for more information.
|
|
||||||
TEST_CASE("Generators") {
|
|
||||||
|
|
||||||
auto i = GENERATE( as<std::string>(), "a", "b", "c" );
|
// Generators and sections can be nested freely
|
||||||
|
TEST_CASE("Generators -- simple", "[generators]") {
|
||||||
SECTION( "one" ) {
|
auto i = GENERATE(1, 2, 3);
|
||||||
auto j = GENERATE( range( 8, 11 ), 2 );
|
SECTION("one") {
|
||||||
|
auto j = GENERATE(values({ -3, -2, -1 }));
|
||||||
CAPTURE( i, j );
|
REQUIRE(j < i);
|
||||||
SUCCEED();
|
|
||||||
}
|
}
|
||||||
SECTION( "two" ) {
|
|
||||||
auto j = GENERATE( 3.141, 1.379 );
|
SECTION("two") {
|
||||||
CAPTURE( i, j );
|
// You can also explicitly set type for generators via Catch::Generators::as
|
||||||
SUCCEED();
|
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
|
||||||
|
REQUIRE(4u * i > str.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This one generates the cross-product of two ranges.
|
// You can create a cartesian-product of generators by creating multiple ones
|
||||||
// It's mostly here to demonstrate the performance which, at time of writing,
|
TEST_CASE("3x3x3 ints", "[generators]") {
|
||||||
// leaves a lot to be desired.
|
auto x = GENERATE(1, 2, 3);
|
||||||
TEST_CASE( "100x100 ints", "[.][approvals]" ) {
|
auto y = GENERATE(4, 5, 6);
|
||||||
auto x = GENERATE( range( 0,100 ) );
|
auto z = GENERATE(7, 8, 9);
|
||||||
auto y = GENERATE( range( 200,300 ) );
|
// These assertions will be run 27 times (3x3x3)
|
||||||
|
CHECK(x < y);
|
||||||
CHECK( x < y );
|
CHECK(y < z);
|
||||||
|
REQUIRE(x < z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// smaller version
|
// You can also create data tuples
|
||||||
TEST_CASE( "10x10 ints" ) {
|
TEST_CASE("tables", "[generators]") {
|
||||||
auto x = GENERATE( range( 1,11 ) );
|
// Note that this will not compile with libstdc++ older than libstdc++6
|
||||||
auto y = GENERATE( range( 101, 111 ) );
|
// See https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
|
||||||
|
// for possible workarounds
|
||||||
|
// auto data = GENERATE(table<char const*, int>({
|
||||||
|
// {"first", 5},
|
||||||
|
// {"second", 6},
|
||||||
|
// {"third", 5},
|
||||||
|
// {"etc...", 6}
|
||||||
|
// }));
|
||||||
|
|
||||||
CHECK( x < y );
|
// Workaround for the libstdc++ bug mentioned above
|
||||||
|
using tuple_type = std::tuple<char const*, int>;
|
||||||
|
auto data = GENERATE(table<char const*, int>({
|
||||||
|
tuple_type{"first", 5},
|
||||||
|
tuple_type{"second", 6},
|
||||||
|
tuple_type{"third", 5},
|
||||||
|
tuple_type{"etc...", 6}
|
||||||
|
}));
|
||||||
|
|
||||||
|
REQUIRE(strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some of the following tests use structured bindings for convenience and so are
|
|
||||||
// conditionally compiled using the de-facto (and soon to be formally) standard
|
|
||||||
// feature macros
|
|
||||||
|
|
||||||
#ifdef __cpp_structured_bindings
|
#ifdef __cpp_structured_bindings
|
||||||
|
|
||||||
// One way to do pairs of values (actual/ expected?)
|
// Structured bindings make the table utility much nicer to use
|
||||||
// For a simple case like this I'd recommend writing out a series of REQUIREs
|
TEST_CASE( "strlen2", "[approvals][generators]" ) {
|
||||||
// but it demonstrates a possible usage.
|
|
||||||
// Spelling out the pair like this is a bit verbose, so read on for better examples
|
|
||||||
// - the use of structured bindings here is an optional convenience
|
|
||||||
TEST_CASE( "strlen", "[approvals]" ) {
|
|
||||||
auto [test_input, expected] = GENERATE( values<std::pair<std::string_view, size_t>>({
|
|
||||||
{"one", 3},
|
|
||||||
{"two", 3},
|
|
||||||
{"three", 5},
|
|
||||||
{"four", 4}
|
|
||||||
}));
|
|
||||||
|
|
||||||
REQUIRE( test_input.size() == expected );
|
|
||||||
}
|
|
||||||
|
|
||||||
// A nicer way to do pairs (or more) of values - using the table generator.
|
|
||||||
// Note, you must specify the types up-front.
|
|
||||||
TEST_CASE( "strlen2", "[approvals]" ) {
|
|
||||||
auto [test_input, expected] = GENERATE( table<std::string, size_t>({
|
auto [test_input, expected] = GENERATE( table<std::string, size_t>({
|
||||||
{"one", 3},
|
{"one", 3},
|
||||||
{"two", 3},
|
{"two", 3},
|
||||||
@@ -81,11 +69,11 @@ TEST_CASE( "strlen2", "[approvals]" ) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// An alternate way of doing data tables without structure bindings
|
|
||||||
// - I'd prefer to have the Data class within the test case but gcc 4.x doesn't seem to like it
|
// An alternate way of doing data tables without structured bindings
|
||||||
struct Data { std::string str; size_t len; };
|
struct Data { std::string str; size_t len; };
|
||||||
|
|
||||||
TEST_CASE( "strlen3" ) {
|
TEST_CASE( "strlen3", "[generators]" ) {
|
||||||
auto data = GENERATE( values<Data>({
|
auto data = GENERATE( values<Data>({
|
||||||
{"one", 3},
|
{"one", 3},
|
||||||
{"two", 3},
|
{"two", 3},
|
||||||
@@ -96,15 +84,7 @@ TEST_CASE( "strlen3" ) {
|
|||||||
REQUIRE( data.str.size() == data.len );
|
REQUIRE( data.str.size() == data.len );
|
||||||
}
|
}
|
||||||
|
|
||||||
// A nod towards property-based testing - generate a random selection of numbers
|
|
||||||
// in a range and assert on global properties those numbers.
|
|
||||||
static auto square( int i ) -> int { return i*i; }
|
|
||||||
|
|
||||||
TEST_CASE( "Random numbers in a range", "[.][approvals]" ) {
|
|
||||||
auto x = GENERATE( random( -10000, 10000 ) );
|
|
||||||
CAPTURE( x );
|
|
||||||
REQUIRE( square(x) >= 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cpp_structured_bindings
|
#ifdef __cpp_structured_bindings
|
||||||
|
|
||||||
@@ -118,7 +98,7 @@ TEST_CASE( "Random numbers in a range", "[.][approvals]" ) {
|
|||||||
|
|
||||||
static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
|
static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
|
||||||
|
|
||||||
SCENARIO("Eating cucumbers", "[approvals]") {
|
SCENARIO("Eating cucumbers", "[generators][approvals]") {
|
||||||
|
|
||||||
auto [start, eat, left] = GENERATE( table<int,int,int> ({
|
auto [start, eat, left] = GENERATE( table<int,int,int> ({
|
||||||
{ 12, 5, 7 },
|
{ 12, 5, 7 },
|
||||||
@@ -132,3 +112,74 @@ SCENARIO("Eating cucumbers", "[approvals]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// There are also some generic generator manipulators
|
||||||
|
TEST_CASE("Generators -- adapters", "[generators][generic]") {
|
||||||
|
// TODO: This won't work yet, introduce GENERATE_VAR?
|
||||||
|
//auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 });
|
||||||
|
SECTION("Filtering by predicate") {
|
||||||
|
SECTION("Basic usage") {
|
||||||
|
// This filters out all odd (false) numbers, giving [2, 4, 6]
|
||||||
|
auto i = GENERATE(filter([] (int val) { return val % 2 == 0; }, values({ 1, 2, 3, 4, 5, 6 })));
|
||||||
|
REQUIRE(i % 2 == 0);
|
||||||
|
}
|
||||||
|
SECTION("Throws if there are no matching values") {
|
||||||
|
using namespace Catch::Generators;
|
||||||
|
REQUIRE_THROWS_AS(filter([] (int) {return false; }, value(1)), Catch::GeneratorException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Shortening a range") {
|
||||||
|
// This takes the first 3 elements from the values, giving back [1, 2, 3]
|
||||||
|
auto i = GENERATE(take(3, values({ 1, 2, 3, 4, 5, 6 })));
|
||||||
|
REQUIRE(i < 4);
|
||||||
|
}
|
||||||
|
SECTION("Transforming elements") {
|
||||||
|
SECTION("Same type") {
|
||||||
|
// This doubles values [1, 2, 3] into [2, 4, 6]
|
||||||
|
auto i = GENERATE(map([] (int val) { return val * 2; }, values({ 1, 2, 3 })));
|
||||||
|
REQUIRE(i % 2 == 0);
|
||||||
|
}
|
||||||
|
SECTION("Different type") {
|
||||||
|
// This takes a generator that returns ints and maps them into strings
|
||||||
|
auto i = GENERATE(map<std::string>([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
|
||||||
|
REQUIRE(i.size() == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION("Repeating a generator") {
|
||||||
|
// This will return values [1, 2, 3, 1, 2, 3]
|
||||||
|
auto j = GENERATE(repeat(2, values({ 1, 2, 3 })));
|
||||||
|
REQUIRE(j > 0);
|
||||||
|
}
|
||||||
|
SECTION("Chunking a generator into sized pieces") {
|
||||||
|
SECTION("Number of elements in source is divisible by chunk size") {
|
||||||
|
auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3, 3 })));
|
||||||
|
REQUIRE(chunk2.size() == 2);
|
||||||
|
REQUIRE(chunk2.front() == chunk2.back());
|
||||||
|
}
|
||||||
|
SECTION("Number of elements in source is not divisible by chunk size") {
|
||||||
|
auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3 })));
|
||||||
|
REQUIRE(chunk2.size() == 2);
|
||||||
|
REQUIRE(chunk2.front() == chunk2.back());
|
||||||
|
REQUIRE(chunk2.front() < 3);
|
||||||
|
}
|
||||||
|
SECTION("Throws on too small generators") {
|
||||||
|
using namespace Catch::Generators;
|
||||||
|
REQUIRE_THROWS_AS(chunk(2, value(1)), Catch::GeneratorException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that because of the non-reproducibility of distributions,
|
||||||
|
// anything involving the random generators cannot be part of approvals
|
||||||
|
TEST_CASE("Random generator", "[generators][.][approvals]") {
|
||||||
|
SECTION("Infer int from integral arguments") {
|
||||||
|
auto val = GENERATE(take(4, random(0, 1)));
|
||||||
|
STATIC_REQUIRE(std::is_same<decltype(val), int>::value);
|
||||||
|
static_cast<void>(val); // Silence VS 2015 unused variable warning
|
||||||
|
}
|
||||||
|
SECTION("Infer double from double arguments") {
|
||||||
|
auto val = GENERATE(take(4, random(0., 1.)));
|
||||||
|
STATIC_REQUIRE(std::is_same<decltype(val), double>::value);
|
||||||
|
static_cast<void>(val); // Silence VS 2015 unused variable warning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -132,6 +132,71 @@ TEST_CASE( "Pointers can be converted to strings", "[messages][.][approvals]" )
|
|||||||
WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) );
|
WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void unscoped_info( T msg ) {
|
||||||
|
UNSCOPED_INFO( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "just unscoped info", "[unscoped][info]" ) {
|
||||||
|
unscoped_info( "this should NOT be seen" );
|
||||||
|
unscoped_info( "this also should NOT be seen" );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "just failure after unscoped info", "[failing][.][unscoped][info]" ) {
|
||||||
|
FAIL( "previous unscoped info SHOULD not be seen" );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "print unscoped info if passing unscoped info is printed", "[unscoped][info]" ) {
|
||||||
|
unscoped_info( "this MAY be seen IF info is printed for passing assertions" );
|
||||||
|
REQUIRE( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "prints unscoped info on failure", "[failing][.][unscoped][info]" ) {
|
||||||
|
unscoped_info( "this SHOULD be seen" );
|
||||||
|
unscoped_info( "this SHOULD also be seen" );
|
||||||
|
REQUIRE( false );
|
||||||
|
unscoped_info( "but this should NOT be seen" );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "not prints unscoped info from previous failures", "[failing][.][unscoped][info]" ) {
|
||||||
|
unscoped_info( "this MAY be seen only for the FIRST assertion IF info is printed for passing assertions" );
|
||||||
|
REQUIRE( true );
|
||||||
|
unscoped_info( "this MAY be seen only for the SECOND assertion IF info is printed for passing assertions" );
|
||||||
|
REQUIRE( true );
|
||||||
|
unscoped_info( "this SHOULD be seen" );
|
||||||
|
REQUIRE( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "prints unscoped info only for the first assertion", "[failing][.][unscoped][info]" ) {
|
||||||
|
unscoped_info( "this SHOULD be seen only ONCE" );
|
||||||
|
CHECK( false );
|
||||||
|
CHECK( true );
|
||||||
|
unscoped_info( "this MAY also be seen only ONCE IF info is printed for passing assertions" );
|
||||||
|
CHECK( true );
|
||||||
|
CHECK( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "stacks unscoped info in loops", "[failing][.][unscoped][info]" ) {
|
||||||
|
UNSCOPED_INFO("Count 1 to 3...");
|
||||||
|
for (int i = 1; i <= 3; i++) {
|
||||||
|
unscoped_info(i);
|
||||||
|
}
|
||||||
|
CHECK( false );
|
||||||
|
|
||||||
|
UNSCOPED_INFO("Count 4 to 6...");
|
||||||
|
for (int i = 4; i <= 6; i++) {
|
||||||
|
unscoped_info(i);
|
||||||
|
}
|
||||||
|
CHECK( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "mix info, unscoped info and warning", "[unscoped][info]" ) {
|
||||||
|
INFO("info");
|
||||||
|
unscoped_info("unscoped info");
|
||||||
|
WARN("and warn may mix");
|
||||||
|
WARN("they are not cleared after warnings");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE( "CAPTURE can deal with complex expressions", "[messages][capture]" ) {
|
TEST_CASE( "CAPTURE can deal with complex expressions", "[messages][capture]" ) {
|
||||||
int a = 1;
|
int a = 1;
|
||||||
int b = 2;
|
int b = 2;
|
||||||
|
@@ -61,6 +61,11 @@ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
|||||||
static AutoTestReg autoTestReg;
|
static AutoTestReg autoTestReg;
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Foo {
|
||||||
|
size_t size() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
|
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
|
||||||
@@ -301,6 +306,15 @@ TEMPLATE_TEST_CASE( "TemplateTest: vectors can be sized and resized", "[vector][
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]", (std::vector, Foo), (int, float)) {
|
||||||
|
TestType x;
|
||||||
|
REQUIRE(x.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
|
||||||
|
REQUIRE(std::tuple_size<TestType>::value >= 1);
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/philsquared/Catch/issues/166
|
// https://github.com/philsquared/Catch/issues/166
|
||||||
TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") {
|
TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") {
|
||||||
SECTION("Outer")
|
SECTION("Outer")
|
||||||
|
23
projects/SelfTest/UsageTests/ToStringOptional.tests.cpp
Normal file
23
projects/SelfTest/UsageTests/ToStringOptional.tests.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||||
|
|
||||||
|
TEST_CASE( "std::optional<int> -> toString", "[toString][optional][approvals]" ) {
|
||||||
|
using type = std::optional<int>;
|
||||||
|
REQUIRE( "{ }" == ::Catch::Detail::stringify( type{} ) );
|
||||||
|
REQUIRE( "0" == ::Catch::Detail::stringify( type{ 0 } ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "std::optional<std::string> -> toString", "[toString][optional][approvals]" ) {
|
||||||
|
using type = std::optional<std::string>;
|
||||||
|
REQUIRE( "{ }" == ::Catch::Detail::stringify( type{} ) );
|
||||||
|
REQUIRE( "\"abc\"" == ::Catch::Detail::stringify( type{ "abc" } ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "std::vector<std::optional<int> > -> toString", "[toString][optional][approvals]" ) {
|
||||||
|
using type = std::vector<std::optional<int> >;
|
||||||
|
REQUIRE( "{ 0, { }, 2 }" == ::Catch::Detail::stringify( type{ 0, {}, 2 } ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
@@ -6,6 +6,18 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
// We need 2 types with non-trivial copies/moves
|
||||||
|
struct MyType1 {
|
||||||
|
MyType1() = default;
|
||||||
|
MyType1(MyType1 const&) { throw 1; }
|
||||||
|
MyType1& operator=(MyType1 const&) { throw 3; }
|
||||||
|
};
|
||||||
|
struct MyType2 {
|
||||||
|
MyType2() = default;
|
||||||
|
MyType2(MyType2 const&) { throw 2; }
|
||||||
|
MyType2& operator=(MyType2 const&) { throw 4; }
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE( "variant<std::monostate>", "[toString][variant][approvals]")
|
TEST_CASE( "variant<std::monostate>", "[toString][variant][approvals]")
|
||||||
{
|
{
|
||||||
using type = std::variant<std::monostate>;
|
using type = std::variant<std::monostate>;
|
||||||
@@ -26,19 +38,18 @@ TEST_CASE( "variant<float, int>", "[toString][variant][approvals]")
|
|||||||
using type = std::variant<float, int>;
|
using type = std::variant<float, int>;
|
||||||
CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
|
CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
|
||||||
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
||||||
|
|
||||||
SECTION("valueless by exception") {
|
|
||||||
struct sample {
|
|
||||||
operator int() const { throw 42; }
|
|
||||||
};
|
|
||||||
|
|
||||||
type value{1.5f};
|
|
||||||
REQUIRE_THROWS_AS( value.emplace<int>(sample{}), int );
|
|
||||||
REQUIRE( value.valueless_by_exception() );
|
|
||||||
CHECK( "{valueless variant}" == ::Catch::Detail::stringify(value) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "variant -- valueless-by-exception", "[toString][variant][approvals]" ) {
|
||||||
|
using type = std::variant<MyType1, MyType2>;
|
||||||
|
|
||||||
|
type value;
|
||||||
|
REQUIRE_THROWS_AS(value.emplace<MyType2>(MyType2{}), int);
|
||||||
|
REQUIRE(value.valueless_by_exception());
|
||||||
|
CHECK("{valueless variant}" == ::Catch::Detail::stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE( "variant<string, int>", "[toString][variant][approvals]")
|
TEST_CASE( "variant<string, int>", "[toString][variant][approvals]")
|
||||||
{
|
{
|
||||||
using type = std::variant<std::string, int>;
|
using type = std::variant<std::string, int>;
|
||||||
@@ -48,22 +59,18 @@ TEST_CASE( "variant<string, int>", "[toString][variant][approvals]")
|
|||||||
|
|
||||||
TEST_CASE( "variant<variant<float, int>, string>", "[toString][variant][approvals]")
|
TEST_CASE( "variant<variant<float, int>, string>", "[toString][variant][approvals]")
|
||||||
{
|
{
|
||||||
using inner = std::variant<float, int>;
|
using inner = std::variant<MyType1, float, int>;
|
||||||
using type = std::variant<inner, std::string>;
|
using type = std::variant<inner, std::string>;
|
||||||
CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
|
CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
|
||||||
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
||||||
CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
|
CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
|
||||||
|
|
||||||
struct sample {
|
|
||||||
operator int() const { throw 42; }
|
|
||||||
};
|
|
||||||
|
|
||||||
SECTION("valueless nested variant") {
|
SECTION("valueless nested variant") {
|
||||||
type value = inner{0.5f};
|
type value = inner{0.5f};
|
||||||
REQUIRE( std::holds_alternative<inner>(value) );
|
REQUIRE( std::holds_alternative<inner>(value) );
|
||||||
REQUIRE( std::holds_alternative<float>(std::get<inner>(value)) );
|
REQUIRE( std::holds_alternative<float>(std::get<inner>(value)) );
|
||||||
|
|
||||||
REQUIRE_THROWS_AS( std::get<0>(value).emplace<int>(sample{}), int );
|
REQUIRE_THROWS_AS( std::get<0>(value).emplace<MyType1>(MyType1{}), int );
|
||||||
|
|
||||||
// outer variant is still valid and contains inner
|
// outer variant is still valid and contains inner
|
||||||
REQUIRE( std::holds_alternative<inner>(value) );
|
REQUIRE( std::holds_alternative<inner>(value) );
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
TEST_CASE
|
TEST_CASE
|
||||||
@@ -426,3 +427,10 @@ TEST_CASE( "Bitfields can be captured (#1027)" ) {
|
|||||||
REQUIRE( y.v == 0 );
|
REQUIRE( y.v == 0 );
|
||||||
REQUIRE( 0 == y.v );
|
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;
|
||||||
|
// FAIL aborts the test by throwing a Catch exception
|
||||||
|
FAIL("1514");
|
||||||
|
}
|
||||||
|
@@ -6,9 +6,14 @@ import subprocess
|
|||||||
catchPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0])))
|
catchPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0])))
|
||||||
|
|
||||||
def getBuildExecutable():
|
def getBuildExecutable():
|
||||||
|
if os.name == 'nt':
|
||||||
|
dir = os.environ.get('CATCH_DEV_OUT_DIR', "cmake-build-debug/projects/SelfTest.exe")
|
||||||
|
return dir
|
||||||
|
else:
|
||||||
dir = os.environ.get('CATCH_DEV_OUT_DIR', "cmake-build-debug/projects/SelfTest")
|
dir = os.environ.get('CATCH_DEV_OUT_DIR', "cmake-build-debug/projects/SelfTest")
|
||||||
return dir
|
return dir
|
||||||
|
|
||||||
|
|
||||||
def runAndCapture( args ):
|
def runAndCapture( args ):
|
||||||
child = subprocess.Popen(" ".join( args ), shell=True, stdout=subprocess.PIPE)
|
child = subprocess.Popen(" ".join( args ), shell=True, stdout=subprocess.PIPE)
|
||||||
lines = []
|
lines = []
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -42,9 +42,9 @@ namespace Catch {
|
|||||||
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
||||||
++counter;
|
++counter;
|
||||||
|
|
||||||
|
stream << "# " << currentTestCaseInfo->name << std::endl;
|
||||||
AssertionPrinter printer( stream, _assertionStats, counter );
|
AssertionPrinter printer( stream, _assertionStats, counter );
|
||||||
printer.print();
|
printer.print();
|
||||||
stream << " # " << currentTestCaseInfo->name ;
|
|
||||||
|
|
||||||
stream << std::endl;
|
stream << std::endl;
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user