Compare commits

..

48 Commits

Author SHA1 Message Date
Martin Hořeňovský
d2a130f243 v2.2.3 2018-06-06 23:19:06 +02:00
Julien Nitard
7be8a41adf Fix ambiguity in stringification
Happening when using clang and templated operators, clang cannot decide
between the operator provided by ReusableStringStream and the one provided
by the value value as both are templates. This is easily solved by calling
the operator<< through the member syntax.

Fixes #1285
2018-06-06 22:33:03 +02:00
Lyashenko Arsenii Maksimovich
021fcee636 Finish fixing invalid compilation using MinGW 2018-06-04 23:49:40 +02:00
Martin Hořeňovský
3a47b8b072 Add missing catch_platform include to compiler capabilities
This was removed in 64be2ad, to fix OS X approval tests. At the time
I couldn't investigate because I didn't have access to OS X, but this
fixed it (and since we don't have MinGW in CI, the breakage went
unnoticed).

As it turns out, piece-wise compilation of the Compact
reporter had broken OS X detection for a long time, and fixing it
was what broke the approvals. After the approval scripts were
changed to compensate, this change passes approval tests and fixes
2018-06-04 23:19:55 +02:00
Martin Hořeňovský
2771a8ee9a Normalize OS X specific pass/fail strings in approvals 2018-06-04 23:19:55 +02:00
Cristian Morales Vega
7abd7db2c8 Fix minor typo in the documentation 2018-06-01 22:24:49 +02:00
BiCapitalization
88d7b8da25 Ensure stack size for POSIX signal handling is sufficient
Until now, the stack size for POSIX signal handling was determined by
the implementation defined limit `STKSZ`, which in some cases turned out
to be insufficient, leading to stack overflow inside the signal handler.
The new size, which was determined experimentally, is the larger of 32kb
or `MINSTKSZ`.

Fixes #1225
2018-05-29 22:29:04 +02:00
Martin Hořeňovský
df0b0e64e1 Make FALLBACK_STRINGIFIER documentation more explicit
Related to #1024
2018-05-14 21:03:07 +02:00
Martin Hořeňovský
4c7b7d04fe Move FALLBACK_STRINGIFIER to before the enum and range fallbacks
This should align more closely with the intended semantics, where
types without `StringMaker` specialization or `operator<<` overload
are passed down to the user defined fallback stringifier.

Related to #1024
2018-05-14 20:38:05 +02:00
Rupert Steel
90988f578c Enable console colour in the approval tests on windows. 2018-05-14 09:41:18 +02:00
Martin Hořeňovský
e5fe3e877a Ensure platform-independent output from SpecialException::what 2018-05-12 20:37:13 +02:00
Martin Hořeňovský
6c5c4c43a0 Add stringification support to std::exception and deriving classes
This support is based on overriden `std::exception::what` method, so
if an exception does not do so meaningfully, the message is still
pointless.

This is only used as a fallback, both `StringMaker` specialization and
`operator<<` overload have priority..
2018-05-12 17:46:25 +02:00
Martin Hořeňovský
c323658483 Fix broken YAML in a way that codecov understands
Theoretically the previous was not a valid YAML at all, but it is
fairly common for parsers to accept it, just in a wrong way. This
results in a configuration where only the last value for duplicate
keys is taken, instead of a hard error.
2018-05-10 14:49:40 +02:00
Martin Hořeňovský
db570b7e24 Split list of examples into "done" and "planned".
Closes #1282
2018-05-09 22:49:04 +02:00
Martin Hořeňovský
0074926e5c Provide a polyfill over std::to_string
Android apparently does not support `std::to_string`, so we add a
small polyfill over it. Right now only the ULP matcher uses it,
but we have had plans to use it in `StringMaker<int>` and friends,
as it performs a lot better than `std::stringstream` based
stringification on MSVC.

See #1280 for more details
2018-05-09 21:47:42 +02:00
Markus Reitboeck
6496c51c95 do not strip spaces from cmake discovered test names
this fixes #1265
2018-05-09 18:00:05 +02:00
Markus Reitboeck
3dd523bdf5 Add gdbinit and lldbinit files with commands to skip stepping into Catch code during debugging
The commands provided have to be executed in the current gdb/lldb session or copied
into the users ~/.gdbinit ~/.lldbinit files to permanently skip debugging Catch code.

Fixes #904
2018-05-09 17:46:31 +02:00
Christopher Di Bella
8d5d49299b Added GCC 8 to Travis. Updated test so that it warning isn't triggered. 2018-05-06 12:06:39 +02:00
Christopher Di Bella
d0287e3b56 Updated Travis for LLVM 6.0 2018-05-06 11:50:03 +02:00
Palotás Boldizsár
dd99a66cf4 Add documentation for --use-colour
The documentation added is based on output from `-?` (help),
and comments to #590.
2018-05-06 11:37:00 +02:00
Martin Hořeňovský
ae590fe216 Only use tmpfile workaround for MSVC and not MinGW and friends
Fixes #1270
2018-04-30 23:19:39 +02:00
Christian Berger
7f791fa08f Suggestion for adding libcluon that is also using Catch2 for testing 2018-04-30 16:02:41 +02:00
Martin Hořeňovský
0510d4755f Fix missing include and wrong comment format
While the comment format was valid C++, it breaks our tooling badly.
I opened up a github issue for our tooling, because unexpected
formatting of a block comment should not silently generate invalid
single header file, see #1269.
2018-04-30 15:15:59 +02:00
Martin Hořeňovský
e92b9c07c3 Add an experimental new way of capturing stdout/stderr
Unlike the relatively non-invasive old way of capturing stdout/stderr,
this new way is also able to capture output from C's stdlib functions
such as `printf`. This is done by redirecting stdout and stderr file
descriptors to a file, and then reading this file back.

This approach has two sizeable drawbacks:
1) Performance, obviously. Previously an installed capture made the
program run faster (as long as it was then discarded), because a call
to `std::cout` did not result in text output to the console. This new
capture method in fact forces disk IO. While it is likely that any
modern OS will keep this file in memory-cache and might never actually
issue the IO to the backing storage, it is still a possibility and
calls to the file system are not free.

2) Nonportability. While POSIX is usually assumed portable, and this
implementation relies only on a very common parts of it, it is no
longer standard C++ (or just plain C) and thus might not be available
on some obscure platforms. Different C libs might also implement the
relevant functions in a less-than-useful ways (e.g. MS's `tmpfile`
generates a temp file inside system folder, so it will not work
without elevated privileges and thus is useless).

These two drawbacks mean that, at least for now, the new capture is
opt-in. To opt-in, `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` needs to be
defined in the implementation file.

Closes #1243
2018-04-29 22:25:49 +02:00
Ian Hattendorf
88a6ff0b65 Cast to unsigned char when using std::isalnum
std::isalnum expects an int in the range of unsigned char or -1 (EOF),
otherwise it exhibits undefined behavior. Casting from char to unsigned
char avoids this.

MSVC warns about this when compiling with /analyze.
2018-04-29 20:28:35 +02:00
Marcus Näslund
9e7c281e6e Minor fixes to python scripts by pycodestyle 2018-04-27 18:57:18 +02:00
Martin Hořeňovský
64be2ad96c Remove superfluous include and fix comment 2018-04-26 21:44:07 +02:00
Martin Hořeňovský
c651f239f0 Detect MinGW as Windows platform w/o SEH
Fixes #1257
2018-04-22 18:46:54 +02:00
Marcus Näslund
43769a19f7 Changed to c++ style includes 2018-04-21 15:58:05 +02:00
Barry
200d3ad824 Support for parenthesizing types with commas. 2018-04-20 15:11:09 +02:00
Martin Hořeňovský
aa7b0c9104 Fix generating single header using Python3 2018-04-19 22:03:25 +02:00
Martin Hořeňovský
375f2052bd Use io.open in approvalTests.py regardless of Python version
Both Python 2.7 and 3.x support full-featured io.open, so we
can avoid using a polyfill over this.
2018-04-19 22:02:31 +02:00
Tom Hughes
dc6b83bec9 Support Python3 in approval tests 2018-04-16 21:19:13 +02:00
Martin Hořeňovský
f00257e374 Call listeners before calling reporters
Catch2's documentation promises that listeners are called _before_
reporters, but because of the previous implementation, they were
called _after_ reporters. This commit fixes that.

Closes #1234
2018-04-07 12:25:03 +02:00
Martin Hořeňovský
414dcae34a Allow only 1 reporter at a time 2018-04-07 12:05:29 +02:00
Martin Hořeňovský
d2d8455b57 v2.2.2 2018-04-06 12:11:22 +02:00
Martin Hořeňovský
ab30621138 Fix stringifying static array of unsigned chars
The fix leaves an open question: should we keep treating refs
to static array of chars as strings, or should we instead
use `strnlen` to check if it is null-terminated within the buffer

Fixes #1238
2018-04-06 11:43:12 +02:00
Martin Hořeňovský
1ca8f43b01 Add PredicateMatcher that takes an arbitrary predicate functions
Also adds `Predicate` helper function to create `PredicateMatcher`.
Because of limitations in type inference it needs to be explicitly
typed, like so
`Predicate<std::string>([](std::string const& str) { ... })`.
It also takes an optional second argument for description of the
predicate.

It is possible to infer the argument with sufficient TMP, see
https://stackoverflow.com/questions/43560492/how-to-extract-lambdas-return-type-and-variadic-parameters-pack-back-from-gener/43561563#43561563
but I don't think that the magic is worth introducing ATM.

Closes #1236
2018-04-04 11:14:19 +02:00
David Aue
dfb83f20e9 Add stringification methods for CLR objects 2018-04-03 19:06:16 +02:00
Alexis Jeandet
319bddd5b8 Small fix to generate pc with include path
In CMake module both include and include/catch are added includes
lookup path. Examples are built with #include "catch.hpp" not
#include "catch/catch.hpp". This should be the same with pkg-config.

Signed-off-by: Alexis Jeandet <alexis.jeandet@member.fsf.org>
2018-04-02 21:38:17 +02:00
Martin Hořeňovský
931441251e Add an early bailout out of benchmark timer calibration
Specific platforms (e.g. TDM-GCC) can have terrible timer resolution,
and our checking code will then loop for an inordinate amount of time.
This change will make it so that the calibration gives up after 3
seconds and just uses the already measured values.

This leaves one open question, how to signal that the resolution
is terrible and benchmarking should not happen?

Fixes #1237
2018-04-01 22:50:39 +02:00
Martin Hořeňovský
ea1f326261 Fix potential for false negative CI results on coverage collection 2018-04-01 14:36:55 +02:00
Mike
3641706923 Leak less GCC warnings suppressions out of Catch 2018-04-01 13:57:05 +02:00
Martin Hořeňovský
3b801c4fda Modify XML encoder to hex-encode invalid UTF-8 sequences
There are still some holes, e.g. we leave surrogate pairs be
even though they are not a part of valid UTF-8, but this might
be for the better -- WTF-8 does support surrogate pairs inside
text.

Closes #1207
2018-03-27 16:49:14 +02:00
Martin Hořeňovský
e11508b48a Disable PIP's version check on AppVeyor 2018-03-22 15:19:09 +01:00
Zsolt Parragi
886d799b79 Fix clang-tidy 6 diagnostic about virtual call in destructor 2018-03-21 17:05:15 +01:00
jsc
8b78087412 Fix bug in WithinAbs::match() and add tests for it 2018-03-21 13:47:12 +01:00
Martin Hořeňovský
6c99b04c87 Allow VS 2017 failures
VS 2017 has an annoying bug, where the result of `__FILE__`
substitution is always lower-cased. This breaks approval tests
and I am not quite convinced that we should fully normalized paths
to accomodate this bug.

We need to remember to undo this in the future though.
2018-03-21 13:41:20 +01:00
76 changed files with 3102 additions and 696 deletions

View File

@@ -11,6 +11,7 @@ common_sources: &all_sources
- llvm-toolchain-trusty-3.9
- llvm-toolchain-trusty-4.0
- llvm-toolchain-trusty-5.0
- llvm-toolchain-trusty-6.0
matrix:
include:
@@ -67,6 +68,14 @@ matrix:
packages: ['clang-5.0']
env: COMPILER='clang++-5.0'
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-6.0']
env: COMPILER='clang++-6.0'
# 2/ Linux GCC Builds
- os: linux
compiler: gcc
@@ -108,6 +117,14 @@ matrix:
packages: ['g++-7']
env: COMPILER='g++-7'
- os: linux
compiler: gcc
addons: &gcc8
apt:
sources: *all_sources
packages: ['g++-8']
env: COMPILER='g++-8'
# 3b/ Linux C++14 Clang builds
# Note that we need newer libstdc++ for C++14 support
- os: linux
@@ -144,6 +161,14 @@ matrix:
packages: ['clang-5.0', 'libstdc++-6-dev']
env: COMPILER='clang++-5.0' CPP14=1
- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-6.0', 'libstdc++-6-dev']
env: COMPILER='clang++-6.0' CPP14=1
# 4a/ Linux C++14 GCC builds
- os: linux
@@ -156,6 +181,11 @@ matrix:
addons: *gcc7
env: COMPILER='g++-7' CPP14=1
- os: linux
compiler: gcc
addons: *gcc8
env: COMPILER='g++-8' CPP14=1
# 5/ OSX Clang Builds
- os: osx
osx_image: xcode7.3
@@ -232,27 +262,24 @@ before_script:
# Regenerate single header file, so it is tested in the examples...
- python scripts/generateSingleHeader.py
- |
# Use Debug builds for running Valgrind and building examples
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE}
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE}
# 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}
script:
- |
cd Build-Debug
make -j 2
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
- cd Build-Debug
- make -j 2
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
# Coverage collection does not work for OS X atm
echo "${TRAVIS_OS_NAME}";
echo "${COVERAGE}";
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]] && [[ "${COVERAGE}" == "1" ]]; then
make gcov
make lcov
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
fi
# Go to release build
cd ../Build-Release
make -j 2
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
- # Go to release build
- cd ../Build-Release
- make -j 2
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2

View File

@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.2.1)
project(Catch2 LANGUAGES CXX VERSION 2.2.3)
include(GNUInstallDirs)
@@ -152,12 +152,14 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_list.h
${HEADER_DIR}/internal/catch_matchers.h
${HEADER_DIR}/internal/catch_matchers_floating.h
${HEADER_DIR}/internal/catch_matchers_generic.hpp
${HEADER_DIR}/internal/catch_matchers_string.h
${HEADER_DIR}/internal/catch_matchers_vector.h
${HEADER_DIR}/internal/catch_message.h
${HEADER_DIR}/internal/catch_objc.hpp
${HEADER_DIR}/internal/catch_objc_arc.hpp
${HEADER_DIR}/internal/catch_option.hpp
${HEADER_DIR}/internal/catch_output_redirect.h
${HEADER_DIR}/internal/catch_platform.h
${HEADER_DIR}/internal/catch_random_number_generator.h
${HEADER_DIR}/internal/catch_reenable_warnings.h
@@ -185,6 +187,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_test_spec_parser.h
${HEADER_DIR}/internal/catch_text.h
${HEADER_DIR}/internal/catch_timer.h
${HEADER_DIR}/internal/catch_to_string.hpp
${HEADER_DIR}/internal/catch_tostring.h
${HEADER_DIR}/internal/catch_totals.h
${HEADER_DIR}/internal/catch_uncaught_exceptions.h
@@ -221,8 +224,10 @@ set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_leak_detector.cpp
${HEADER_DIR}/internal/catch_matchers.cpp
${HEADER_DIR}/internal/catch_matchers_floating.cpp
${HEADER_DIR}/internal/catch_matchers_generic.cpp
${HEADER_DIR}/internal/catch_matchers_string.cpp
${HEADER_DIR}/internal/catch_message.cpp
${HEADER_DIR}/internal/catch_output_redirect.cpp
${HEADER_DIR}/internal/catch_registry_hub.cpp
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
${HEADER_DIR}/internal/catch_random_number_generator.cpp
@@ -263,7 +268,7 @@ set(REPORTER_HEADERS
${HEADER_DIR}/reporters/catch_reporter_compact.h
${HEADER_DIR}/reporters/catch_reporter_console.h
${HEADER_DIR}/reporters/catch_reporter_junit.h
${HEADER_DIR}/reporters/catch_reporter_multi.h
${HEADER_DIR}/reporters/catch_reporter_listening.h
${HEADER_DIR}/reporters/catch_reporter_tap.hpp
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
${HEADER_DIR}/reporters/catch_reporter_xml.h
@@ -273,7 +278,7 @@ set(REPORTER_SOURCES
${HEADER_DIR}/reporters/catch_reporter_compact.cpp
${HEADER_DIR}/reporters/catch_reporter_console.cpp
${HEADER_DIR}/reporters/catch_reporter_junit.cpp
${HEADER_DIR}/reporters/catch_reporter_multi.cpp
${HEADER_DIR}/reporters/catch_reporter_listening.cpp
${HEADER_DIR}/reporters/catch_reporter_xml.cpp
)
set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})

View File

@@ -5,9 +5,9 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/zDKMK3eGMC9IP2jy)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/u7qF77qgv9YqOr55)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.2.1/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.2.3/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!

View File

@@ -33,6 +33,8 @@ environment:
matrix:
allow_failures:
- os: Visual Studio 2017
exclude:
- os: Visual Studio 2015
additional_flags: "/permissive- /std:c++latest"
@@ -62,7 +64,7 @@ matrix:
install:
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip install codecov }
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
# Win32 and x64 are CMake-compatible solution platform names.

View File

@@ -3,4 +3,4 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: Catch
Description: Testing library for C++
Version: @Catch2_VERSION@
Cflags: -I${includedir}
Cflags: -I${includedir} -I${includedir}/catch

View File

@@ -9,6 +9,12 @@ coverage:
patch:
default:
target: 80%
ignore:
- "projects/SelfTest"
- "**/catch_reporter_tap.hpp"
- "**/catch_reporter_automake.hpp"
- "**/catch_reporter_teamcity.hpp"
- "**/external/clara.hpp"
codecov:
@@ -16,11 +22,3 @@ codecov:
comment:
layout: "diff"
coverage:
ignore:
- "projects/SelfTest"
- "**/catch_reporter_tap.hpp"
- "**/catch_reporter_automake.hpp"
- "**/catch_reporter_teamcity.hpp"
- "**/external/clara.hpp"

View File

@@ -4,7 +4,7 @@ from conans import ConanFile
class CatchConan(ConanFile):
name = "Catch"
version = "2.2.1"
version = "2.2.3"
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
author = "philsquared"
generators = "cmake"

View File

@@ -50,8 +50,7 @@ string(REPLACE "\n" ";" output "${output}")
# Parse output
foreach(line ${output})
# Test name; strip spaces to get just the name...
string(REGEX REPLACE " +" "" test "${line}")
set(test ${line})
# ...and add to script
add_command(add_test
"${prefix}${test}${suffix}"

16
contrib/gdbinit Normal file
View File

@@ -0,0 +1,16 @@
#
# This file provides a way to skip stepping into Catch code when debugging with gdb.
#
# With the gdb "skip" command you can tell gdb to skip files or functions during debugging.
# see https://xaizek.github.io/2016-05-26/skipping-standard-library-in-gdb/ for an example
#
# Basically the following line tells gdb to skip all functions containing the
# regexp "Catch", which matches the complete Catch namespace.
# If you want to skip just some parts of the Catch code you can modify the
# regexp accordingly.
#
# If you want to permanently skip stepping into Catch code copy the following
# line into your ~/.gdbinit file
#
skip -rfu Catch

16
contrib/lldbinit Normal file
View File

@@ -0,0 +1,16 @@
#
# This file provides a way to skip stepping into Catch code when debugging with lldb.
#
# With the setting "target.process.thread.step-avoid-regexp" you can tell lldb
# to skip functions matching the regexp
#
# Basically the following line tells lldb to skip all functions containing the
# regexp "Catch", which matches the complete Catch namespace.
# If you want to skip just some parts of the Catch code you can modify the
# regexp accordingly.
#
# If you want to permanently skip stepping into Catch code copy the following
# line into your ~/.lldbinit file
#
settings set target.process.thread.step-avoid-regexp Catch

View File

@@ -6,6 +6,7 @@
[Exceptions](#exceptions)<br>
[Matcher expressions](#matcher-expressions)<br>
[Thread Safety](#thread-safety)<br>
[Expressions with commas](#expressions-with-commas)<br>
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
@@ -155,6 +156,34 @@ Matchers can be composed using `&&`, `||` and `!` operators.
Currently assertions in Catch are not thread safe.
For more details, along with workarounds, see the section on [the limitations page](limitations.md#thread-safe-assertions).
## Expressions with commas
Because the preprocessor parses code using different rules than the
compiler, multiple-argument assertions (e.g. `REQUIRE_THROWS_AS`) have
problems with commas inside the provided expressions. As an example
`REQUIRE_THROWS_AS(std::pair<int, int>(1, 2), std::invalid_argument);`
will fail to compile, because the preprocessor sees 3 arguments provided,
but the macro accepts only 2. There are two possible workarounds.
1) Use typedef:
```cpp
using int_pair = std::pair<int, int>;
REQUIRE_THROWS_AS(int_pair(1, 2), std::invalid_argument);
```
This solution is always applicable, but makes the meaning of the code
less clear.
2) Parenthesize the expression:
```cpp
TEST_CASE_METHOD((Fixture<int, int>), "foo", "[bar]") {
SUCCEED();
}
```
This solution is not always applicable, because it might require extra
changes on the Catch's side to work.
---
[Home](Readme.md#top)

View File

@@ -24,6 +24,7 @@
[Usage](#usage)<br>
[Specify the section to run](#specify-the-section-to-run)<br>
[Filenames as tags](#filenames-as-tags)<br>
[Override output colouring](#use-colour)<br>
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
@@ -57,6 +58,7 @@ Click one of the followings links to take you straight to that option - or scrol
<a href="#libidentify"> ` --libidentify`</a><br />
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
<a href="#use-colour"> ` --use-colour`</a><br />
</br>
@@ -329,6 +331,16 @@ filename it is found in, with any extension stripped, prefixed with the `#` char
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
<a id="use-colour"></a>
## Override output colouring
<pre>--use-colour &lt;yes|no|auto&gt;</pre>
Catch colours output for terminals, but omits colouring when it detects that
output is being sent to a pipe. This is done to avoid interfering with automated
processing of output.
`--use-colour yes` forces coloured output, `--use-colour no` disables coloured
output. The default behaviour is `--use-colour auto`.
---

View File

@@ -77,13 +77,16 @@ This can be useful on certain platforms that do not provide the standard iostrea
## Fallback stringifier
By default Catch's stringification machinery falls back to a "{?}". To
let projects reuse their own existing stringification machinery, this
fallback can be overridden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER`
to a name of a function that should perform the stringification instead.
By default, when Catch's stringification machinery has to stringify
a type that does not specialize `StringMaker`, does not overload `operator<<`,
is not an enumeration and is not a range, it uses `"{?}"`. This can be
overriden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER` to name of a
function that should perform the stringification instead.
The provided function must return std::string and must accept any type
(e.g. via overloading).
All types that do not provide `StringMaker` specialization or `operator<<`
overload will be sent to this function (this includes enums and ranges).
The provided function must return `std::string` and must accept any type,
e.g. via overloading.
_Note that if the provided function does not handle a type and this type
requires to be stringified, the compilation will fail._
@@ -99,6 +102,19 @@ This means that defining `CATCH_CONFIG_DEFAULT_REPORTER` to `"console"`
is equivalent with the out-of-the-box experience.
## C++11 toggles
CATCH_CONFIG_CPP11_TO_STRING // Use `std::to_string`
Because we support platforms whose standard library does not contain
`std::to_string`, it is possible to force Catch to use a workaround
based on `std::stringstream`. On platforms other than Android,
the default is to use `std::to_string`. On Android, the default is to
use the `stringstream` workaround. As always, it is possible to override
Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
`CATCH_CONFIG_NO_CPP11_TO_STRING`.
## C++17 toggles
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception
@@ -121,6 +137,7 @@ by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`.
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
CATCH_CONFIG_DISABLE // Disables assertions and test case registration
CATCH_CONFIG_WCHAR // Enables use of wchart_t
CATCH_CONFIG_EXPERIMENTAL_REDIRECT // Enables the new (experimental) way of capturing stdout/stderr
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
@@ -131,7 +148,9 @@ Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC,
`CATCH_CONFIG_WCHAR` is on by default, but can be disabled. Currently
it is only used in support for DJGPP cross-compiler.
These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
With the exception of `CATCH_CONFIG_EXPERIMENTAL_REDIRECT`,
these toggles can be disabled by using `_NO_` form of the toggle,
e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
### `CATCH_CONFIG_FAST_COMPILE`
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:

View File

@@ -1,18 +1,25 @@
<a id="top"></a>
# List of examples
## Already available
- Test Case: [Single-file](../examples/010-TestCase.cpp)
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-1.cpp)
- Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)
- Fixture: [Sections](../examples/100-Fix-Section.cpp)
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
## Planned
- Assertion: [REQUIRE_THAT and Matchers](../examples/040-Asn-RequireThat.cpp)
- Assertion: [REQUIRE_NO_THROW](../examples/050-Asn-RequireNoThrow.cpp)
- Assertion: [REQUIRE_THROWS](../examples/050-Asn-RequireThrows.cpp)
- Assertion: [REQUIRE_THROWS_AS](../examples/070-Asn-RequireThrowsAs.cpp)
- Assertion: [REQUIRE_THROWS_WITH](../examples/080-Asn-RequireThrowsWith.cpp)
- Assertion: [REQUIRE_THROWS_MATCHES](../examples/090-Asn-RequireThrowsMatches.cpp)
- Fixture: [Sections](../examples/100-Fix-Section.cpp)
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
- Floating point: [Approx - Comparisons](../examples/130-Fpt-Approx.cpp)
- Logging: [CAPTURE - Capture expression](../examples/140-Log-Capture.cpp)
- Logging: [INFO - Provide information with failure](../examples/150-Log-Info.cpp)
@@ -21,7 +28,6 @@
- Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
- Report: [Reporter](../examples/200-Rpt-UserDefinedReporter.cpp)
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
- Configuration: [Provide your own main()](../examples/220-Cfg-OwnMain.cpp)
- Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
- Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)

View File

@@ -53,6 +53,25 @@ The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts
Do note that ULP-based checks only make sense when both compared numbers are of the same type and `WithinULP` will use type of its argument as the target type. This means that `WithinULP(1.f, 1)` will expect to compare `float`s, but `WithinULP(1., 1)` will expect to compare `double`s.
### Generic matchers
Catch also aims to provide a set of generic matchers. Currently this set
contains only a matcher that takes arbitrary callable predicate and applies
it onto the provided object.
Because of type inference limitations, the argument type of the predicate
has to be provided explicitly. Example:
```cpp
REQUIRE_THAT("Hello olleH",
Predicate<std::string>(
[] (std::string const& str) -> bool { return str.front() == str.back(); },
"First and last character should be equal")
);
```
The second argument is an optional description of the predicate, and is
used only during reporting of the result.
## Custom matchers
It's easy to provide your own matchers to extend Catch or just to work with your own types.

View File

@@ -47,6 +47,9 @@ A header-only template engine for modern C++.
### [JSON for Modern C++](https://github.com/nlohmann/json)
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
### [libcluon](https://github.com/chrberger/libcluon)
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
### [MNMLSTC Core](https://github.com/mnmlstc/core)
A small and easy to use C++11 library that adds a functionality set that will be available in C++14 and later, as well as some useful additions.

View File

@@ -1,5 +1,68 @@
<a id="top"></a>
# 2.2.3
**To fix some of the bugs, some behavior had to change in potentially breaking manner.**
**This means that even though this is a patch release, it might not be a drop-in replacement.**
## Fixes
* Listeners are now called before reporter
* This was always documented to be the case, now it actually works that way
* Catch's commandline will no longer accept multiple reporters
* This was done because multiple reporters never worked properly and broke things in non-obvious ways
* **This has potential to be a breaking change**
* MinGW is now detected as Windows platform w/o SEH support (#1257)
* This means that Catch2 no longer tries to use POSIX signal handling when compiled with MinGW
* Fixed potential UB in parsing tags using non-ASCII characters (#1266)
* Note that Catch2 still supports only ASCII test names/tags/etc
* `TEST_CASE_METHOD` can now be used on classnames containing commas (#1245)
* You have to enclose the classname in extra set of parentheses
* Fixed insufficient alt stack size for POSIX signal handling (#1225)
* Fixed compilation error on Android due to missing `std::to_string` in C++11 mode (#1280)
* Fixed the order of user-provided `FALLBACK_STRINGIFIER` in stringification machinery (#1024)
* It was intended to be replacement for built-in fallbacks, but it was used _after_ them.
* **This has potential to be a breaking change**
* Fixed compilation error when a type has an `operator<<` with templated lhs (#1285, #1306)
## Improvements
* Added a new, experimental, output capture (#1243)
* This capture can also redirect output written via C apis, e.g. `printf`
* To opt-in, define `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` in the implementation file
* Added a new fallback stringifier for classes derived from `std::exception`
* Both `StringMaker` specialization and `operator<<` overload are given priority
## Miscellaneous
* `contrib/` now contains dbg scripts that skip over Catch's internals (#904, #1283)
* `gdbinit` for gdb `lldbinit` for lldb
* `CatchAddTests.cmake` no longer strips whitespace from tests (#1265, #1281)
* Online documentation now describes `--use-colour` option (#1263)
# 2.2.2
## Fixes
* Fixed bug in `WithinAbs::match()` failing spuriously (#1228)
* Fixed clang-tidy diagnostic about virtual call in destructor (#1226)
* Reduced the number of GCC warnings suppression leaking out of the header (#1090, #1091)
* Only `-Wparentheses` should be leaking now
* Added upper bound on the time benchmark timer calibration is allowed to take (#1237)
* On platforms where `std::chrono::high_resolution_clock`'s resolution is low, the calibration would appear stuck
* Fixed compilation error when stringifying static arrays of `unsigned char`s (#1238)
## Improvements
* XML encoder now hex-encodes invalid UTF-8 sequences (#1207)
* This affects xml and junit reporters
* Some invalid UTF-8 parts are left as is, e.g. surrogate pairs. This is because certain extensions of UTF-8 allow them, such as WTF-8.
* CLR objects (`T^`) can now be stringified (#1216)
* This affects code compiled as C++/CLI
* Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236)
* See [documentation for details](https://github.com/catchorg/Catch2/blob/master/docs/matchers.md)
## Others
* Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239)
* The plans to standardize on `#include <catch2/catch.hpp>` are still in effect
# 2.2.1
## Fixes

View File

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

View File

@@ -11,6 +11,7 @@
#include "catch_capture.hpp"
#include "catch_matchers.h"
#include "catch_matchers_floating.h"
#include "catch_matchers_generic.hpp"
#include "catch_matchers_string.h"
#include "catch_matchers_vector.h"

View File

@@ -130,7 +130,7 @@ namespace Catch {
| Opt( config.outputFilename, "filename" )
["-o"]["--out"]
( "output filename" )
| Opt( config.reporterNames, "name" )
| Opt( config.reporterName, "name" )
["-r"]["--reporter"]
( "reporter to use (defaults to console)" )
| Opt( config.name, "name" )

View File

@@ -24,6 +24,7 @@
// Many features, at point of detection, define an _INTERNAL_ macro, so they
// can be combined, en-mass, with the _NO_ forms later.
#include "catch_platform.h"
#ifdef __cplusplus
@@ -76,6 +77,18 @@
# define CATCH_CONFIG_COLOUR_NONE
#endif
////////////////////////////////////////////////////////////////////////////////
// Android somehow still does not support std::to_string
#if defined(__ANDROID__)
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
#endif
////////////////////////////////////////////////////////////////////////////////
// Not all Windows environments support SEH properly
#if defined(__MINGW32__)
# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
#endif
////////////////////////////////////////////////////////////////////////////////
// Cygwin
#ifdef __CYGWIN__
@@ -126,7 +139,7 @@
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
# define CATCH_CONFIG_WINDOWS_SEH
#endif
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
@@ -138,6 +151,10 @@
# define CATCH_CONFIG_WCHAR
#endif
#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
# define CATCH_CONFIG_CPP11_TO_STRING
#endif
#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
#endif

View File

@@ -37,8 +37,8 @@ namespace Catch {
bool Config::listReporters() const { return m_data.listReporters; }
std::string Config::getProcessName() const { return m_data.processName; }
std::string const& Config::getReporterName() const { return m_data.reporterName; }
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }

View File

@@ -54,8 +54,12 @@ namespace Catch {
std::string outputFilename;
std::string name;
std::string processName;
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
#undef CATCH_CONFIG_DEFAULT_REPORTER
std::vector<std::string> reporterNames;
std::vector<std::string> testsOrTags;
std::vector<std::string> sectionsToRun;
};
@@ -76,8 +80,8 @@ namespace Catch {
bool listReporters() const;
std::string getProcessName() const;
std::string const& getReporterName() const;
std::vector<std::string> const& getReporterNames() const;
std::vector<std::string> const& getTestsOrTags() const;
std::vector<std::string> const& getSectionsToRun() const override;

View File

@@ -94,6 +94,11 @@ namespace Catch {
int id;
const char* name;
};
// 32kb for the alternate stack seems to be sufficient. However, this value
// is experimentally determined, so that's not guaranteed.
constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
static SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" },
@@ -121,7 +126,7 @@ namespace Catch {
isSet = true;
stack_t sigStack;
sigStack.ss_sp = altStackMem;
sigStack.ss_size = SIGSTKSZ;
sigStack.ss_size = sigStackSize;
sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { };
@@ -153,7 +158,7 @@ namespace Catch {
bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
char FatalConditionHandler::altStackMem[sigStackSize] = {};
} // namespace Catch

View File

@@ -6,7 +6,7 @@
*/
#include "catch_interfaces_reporter.h"
#include "../reporters/catch_reporter_multi.h"
#include "../reporters/catch_reporter_listening.h"
namespace Catch {
@@ -111,25 +111,4 @@ namespace Catch {
IReporterFactory::~IReporterFactory() = default;
IReporterRegistry::~IReporterRegistry() = default;
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
if( !existingReporter ) {
existingReporter = std::move( additionalReporter );
return;
}
MultipleReporters* multi = nullptr;
if( existingReporter->isMulti() ) {
multi = static_cast<MultipleReporters*>( existingReporter.get() );
}
else {
auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters );
newMulti->add( std::move( existingReporter ) );
multi = newMulti.get();
existingReporter = std::move( newMulti );
}
multi->add( std::move( additionalReporter ) );
}
} // end namespace Catch

View File

@@ -226,8 +226,6 @@ namespace Catch {
virtual Listeners const& getListeners() const = 0;
};
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED

View File

@@ -6,6 +6,7 @@
*/
#include "catch_matchers_floating.h"
#include "catch_to_string.hpp"
#include "catch_tostring.h"
#include <cstdlib>
@@ -88,7 +89,7 @@ namespace Floating {
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
// But without the subtraction to allow for INFINITY in comparison
bool WithinAbsMatcher::match(double const& matchee) const {
return (matchee + m_margin >= m_target) && (m_target + m_margin >= m_margin);
return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
}
std::string WithinAbsMatcher::describe() const {
@@ -115,7 +116,7 @@ namespace Floating {
}
std::string WithinUlpsMatcher::describe() const {
return "is within " + std::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
}
}// namespace Floating

View File

@@ -0,0 +1,9 @@
#include "catch_matchers_generic.hpp"
std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
if (desc.empty()) {
return "matches undescribed predicate";
} else {
return "matches predicate: \"" + desc + '"';
}
}

View File

@@ -0,0 +1,58 @@
/*
* Created by Martin Hořeňovský on 03/04/2017.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
#include "catch_common.h"
#include "catch_matchers.h"
#include <functional>
#include <string>
namespace Catch {
namespace Matchers {
namespace Generic {
namespace Detail {
std::string finalizeDescription(const std::string& desc);
}
template <typename T>
class PredicateMatcher : public MatcherBase<T> {
std::function<bool(T const&)> m_predicate;
std::string m_description;
public:
PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
:m_predicate(std::move(elem)),
m_description(Detail::finalizeDescription(descr))
{}
bool match( T const& item ) const override {
return m_predicate(item);
}
std::string describe() const override {
return m_description;
}
};
} // namespace Generic
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
// infering std::function<bool(T const&)> is hard (but possible) and
// requires a lot of TMP.
template<typename T>
Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
return Generic::PredicateMatcher<T>(predicate, description);
}
} // namespace Matchers
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED

View File

@@ -0,0 +1,132 @@
/*
* Created by Martin on 28/04/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)
*/
#include "catch_output_redirect.h"
#include <cstdio>
#include <cstring>
#include <fstream>
#include <sstream>
#include <stdexcept>
#if defined(_MSC_VER)
#include <io.h> //_dup and _dup2
#define dup _dup
#define dup2 _dup2
#define fileno _fileno
#else
#include <unistd.h> // dup and dup2
#endif
namespace Catch {
RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
: m_originalStream( originalStream ),
m_redirectionStream( redirectionStream ),
m_prevBuf( m_originalStream.rdbuf() )
{
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
}
RedirectedStream::~RedirectedStream() {
m_originalStream.rdbuf( m_prevBuf );
}
RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
RedirectedStdErr::RedirectedStdErr()
: m_cerr( Catch::cerr(), m_rss.get() ),
m_clog( Catch::clog(), m_rss.get() )
{}
auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
#if defined(_MSC_VER)
TempFile::TempFile() {
if (tmpnam_s(m_buffer)) {
throw std::runtime_error("Could not get a temp filename");
}
if (fopen_s(&m_file, m_buffer, "w")) {
char buffer[100];
if (strerror_s(buffer, errno)) {
throw std::runtime_error("Could not translate errno to string");
}
throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer);
}
}
#else
TempFile::TempFile() {
m_file = std::tmpfile();
if (!m_file) {
throw std::runtime_error("Could not create a temp file.");
}
}
#endif
TempFile::~TempFile() {
// TBD: What to do about errors here?
std::fclose(m_file);
// We manually create the file on Windows only, on Linux
// it will be autodeleted
#if defined(_MSC_VER)
std::remove(m_buffer);
#endif
}
FILE* TempFile::getFile() {
return m_file;
}
std::string TempFile::getContents() {
std::stringstream sstr;
char buffer[100] = {};
std::rewind(m_file);
while (std::fgets(buffer, sizeof(buffer), m_file)) {
sstr << buffer;
}
return sstr.str();
}
OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
m_originalStdout(dup(1)),
m_originalStderr(dup(2)),
m_stdoutDest(stdout_dest),
m_stderrDest(stderr_dest) {
dup2(fileno(m_stdoutFile.getFile()), 1);
dup2(fileno(m_stderrFile.getFile()), 2);
}
OutputRedirect::~OutputRedirect() {
Catch::cout() << std::flush;
fflush(stdout);
// Since we support overriding these streams, we flush cerr
// even though std::cerr is unbuffered
Catch::cerr() << std::flush;
Catch::clog() << std::flush;
fflush(stderr);
dup2(m_originalStdout, 1);
dup2(m_originalStderr, 2);
m_stdoutDest += m_stdoutFile.getContents();
m_stderrDest += m_stderrFile.getContents();
}
} // namespace Catch
#if defined(_MSC_VER)
#undef dup
#undef dup2
#undef fileno
#endif

View File

@@ -0,0 +1,98 @@
/*
* Created by Martin on 28/04/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_OUTPUT_REDIRECT_H
#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
#include "catch_platform.h"
#include "catch_stream.h"
#include <cstdio>
#include <iosfwd>
#include <string>
namespace Catch {
class RedirectedStream {
std::ostream& m_originalStream;
std::ostream& m_redirectionStream;
std::streambuf* m_prevBuf;
public:
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
~RedirectedStream();
};
class RedirectedStdOut {
ReusableStringStream m_rss;
RedirectedStream m_cout;
public:
RedirectedStdOut();
auto str() const -> std::string;
};
// StdErr has two constituent streams in C++, std::cerr and std::clog
// This means that we need to redirect 2 streams into 1 to keep proper
// order of writes
class RedirectedStdErr {
ReusableStringStream m_rss;
RedirectedStream m_cerr;
RedirectedStream m_clog;
public:
RedirectedStdErr();
auto str() const -> std::string;
};
// Windows's implementation of std::tmpfile is terrible (it tries
// to create a file inside system folder, thus requiring elevated
// privileges for the binary), so we have to use tmpnam(_s) and
// create the file ourselves there.
class TempFile {
public:
TempFile(TempFile const&) = delete;
TempFile& operator=(TempFile const&) = delete;
TempFile(TempFile&&) = delete;
TempFile& operator=(TempFile&&) = delete;
TempFile();
~TempFile();
std::FILE* getFile();
std::string getContents();
private:
std::FILE* m_file = nullptr;
#if defined(_MSC_VER)
char m_buffer[L_tmpnam] = { 0 };
#endif
};
class OutputRedirect {
public:
OutputRedirect(OutputRedirect const&) = delete;
OutputRedirect& operator=(OutputRedirect const&) = delete;
OutputRedirect(OutputRedirect&&) = delete;
OutputRedirect& operator=(OutputRedirect&&) = delete;
OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
~OutputRedirect();
private:
int m_originalStdout = -1;
int m_originalStderr = -1;
TempFile m_stdoutFile;
TempFile m_stderrFile;
std::string& m_stdoutDest;
std::string& m_stderrDest;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H

View File

@@ -20,7 +20,7 @@
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
# define CATCH_PLATFORM_WINDOWS
#endif

View File

@@ -3,6 +3,7 @@
#include "catch_enforce.h"
#include "catch_random_number_generator.h"
#include "catch_stream.h"
#include "catch_output_redirect.h"
#include <cassert>
#include <algorithm>
@@ -10,48 +11,6 @@
namespace Catch {
class RedirectedStream {
std::ostream& m_originalStream;
std::ostream& m_redirectionStream;
std::streambuf* m_prevBuf;
public:
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
: m_originalStream( originalStream ),
m_redirectionStream( redirectionStream ),
m_prevBuf( m_originalStream.rdbuf() )
{
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
}
~RedirectedStream() {
m_originalStream.rdbuf( m_prevBuf );
}
};
class RedirectedStdOut {
ReusableStringStream m_rss;
RedirectedStream m_cout;
public:
RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
auto str() const -> std::string { return m_rss.str(); }
};
// StdErr has two constituent streams in C++, std::cerr and std::clog
// This means that we need to redirect 2 streams into 1 to keep proper
// order of writes
class RedirectedStdErr {
ReusableStringStream m_rss;
RedirectedStream m_cerr;
RedirectedStream m_clog;
public:
RedirectedStdErr()
: m_cerr( Catch::cerr(), m_rss.get() ),
m_clog( Catch::clog(), m_rss.get() )
{}
auto str() const -> std::string { return m_rss.str(); }
};
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
: m_runInfo(_config->name()),
m_context(getCurrentMutableContext()),
@@ -299,13 +258,19 @@ namespace Catch {
Timer timer;
try {
if (m_reporter->getPreferences().shouldRedirectStdOut) {
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
RedirectedStdOut redirectedStdOut;
RedirectedStdErr redirectedStdErr;
timer.start();
invokeActiveTestCase();
redirectedCout += redirectedStdOut.str();
redirectedCerr += redirectedStdErr.str();
#else
OutputRedirect r(redirectedCout, redirectedCerr);
timer.start();
invokeActiveTestCase();
#endif
} else {
timer.start();
invokeActiveTestCase();

View File

@@ -99,7 +99,7 @@ namespace Catch {
public:
// !TBD We need to do this another way!
bool aborting() const override;
bool aborting() const final;
private:

View File

@@ -20,6 +20,7 @@
#include "catch_text.h"
#include "catch_stream.h"
#include "catch_windows_h_proxy.h"
#include "../reporters/catch_reporter_listening.h"
#include <cstdlib>
#include <iomanip>
@@ -36,33 +37,26 @@ namespace Catch {
return reporter;
}
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
auto const& reporterNames = config->getReporterNames();
if (reporterNames.empty())
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
return createReporter(config->getReporterName(), config);
}
IStreamingReporterPtr reporter;
for (auto const& name : reporterNames)
addReporter(reporter, createReporter(name, config));
return reporter;
}
auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
#undef CATCH_CONFIG_DEFAULT_REPORTER
void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
for (auto const& listener : listeners)
addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
for (auto const& listener : listeners) {
multi->addListener(listener->create(Catch::ReporterConfig(config)));
}
multi->addReporter(createReporter(config->getReporterName(), config));
return std::move(multi);
}
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
IStreamingReporterPtr reporter = makeReporter(config);
addListeners(reporter, config);
// FixMe: Add listeners in order first, then add reporters.
auto reporter = makeReporter(config);
RunContext context(config, std::move(reporter));

View File

@@ -17,8 +17,8 @@
# pragma clang diagnostic ignored "-Wcovered-switch-default"
# endif
#elif defined __GNUC__
# pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic ignored "-Wparentheses"
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic ignored "-Wpadded"
#endif

View File

@@ -37,7 +37,7 @@ namespace Catch {
return TestCaseInfo::None;
}
bool isReservedTag( std::string const& tag ) {
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
}
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),

View File

@@ -10,7 +10,7 @@
#include "catch_enforce.h"
#include <algorithm>
#include <assert.h>
#include <cassert>
#include <stdexcept>
#include <memory>
#include <sstream>

View File

@@ -47,12 +47,17 @@ struct AutoReg : NonCopyable {
} // end namespace Catch
#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
#if defined(CATCH_CONFIG_DISABLE)
#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
static void TestName()
#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
namespace{ \
struct TestName : ClassName { \
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
void test(); \
}; \
} \
@@ -80,7 +85,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ \
struct TestName : ClassName{ \
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \

View File

@@ -10,6 +10,8 @@
#include <chrono>
static const uint64_t nanosecondsInSecond = 1000000000;
namespace Catch {
auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
@@ -20,17 +22,25 @@ namespace Catch {
uint64_t sum = 0;
static const uint64_t iterations = 1000000;
auto startTime = getCurrentNanosecondsSinceEpoch();
for( std::size_t i = 0; i < iterations; ++i ) {
uint64_t ticks;
uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
do {
ticks = getCurrentNanosecondsSinceEpoch();
}
while( ticks == baseTicks );
} while( ticks == baseTicks );
auto delta = ticks - baseTicks;
sum += delta;
// If we have been calibrating for over 3 seconds -- the clock
// is terrible and we should move on.
// TBD: How to signal that the measured resolution is probably wrong?
if (ticks > startTime + 3 * nanosecondsInSecond) {
return sum / i;
}
}
// We're just taking the mean, here. To do better we could take the std. dev and exclude outliers

View File

@@ -0,0 +1,28 @@
/*
* Created by Martin on 9/5/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_TO_STRING_H_INCLUDED
#define TWOBLUECUBES_CATCH_TO_STRING_H_INCLUDED
#include <string>
#include "catch_compiler_capabilities.h"
#include "catch_stream.h"
namespace Catch {
template <typename T>
std::string to_string(T const& t) {
#if defined(CATCH_CONFIG_CPP11_TO_STRING)
return std::to_string(t);
#else
ReusableStringStream rss;
rss << t;
return rss.str();
#endif
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_TO_STRING_H_INCLUDED

View File

@@ -62,19 +62,38 @@ namespace Catch {
std::string convertUnknownEnumToString( E e );
template<typename T>
typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) {
#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
(void)value;
typename std::enable_if<
!std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
std::string>::type convertUnstreamable( T const& ) {
return Detail::unprintableString;
#else
return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
#endif
}
template<typename T>
typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) {
typename std::enable_if<
!std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
std::string>::type convertUnstreamable(T const& ex) {
return ex.what();
}
template<typename T>
typename std::enable_if<
std::is_enum<T>::value
, std::string>::type convertUnstreamable( T const& value ) {
return convertUnknownEnumToString( value );
}
#if defined(_MANAGED)
//! Convert a CLR string to a utf8 std::string
template<typename T>
std::string clrReferenceToString( T^ ref ) {
if (ref == nullptr)
return std::string("null");
auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
cli::pin_ptr<System::Byte> p = &bytes[0];
return std::string(reinterpret_cast<char const *>(p), bytes->Length);
}
#endif
} // namespace Detail
@@ -86,7 +105,9 @@ namespace Catch {
typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
convert(const Fake& value) {
ReusableStringStream rss;
rss << value;
// NB: call using the function-like syntax to avoid ambiguity with
// user-defined templated operator<< under clang.
rss.operator<<(value);
return rss.str();
}
@@ -94,7 +115,11 @@ namespace Catch {
static
typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
convert( const Fake& value ) {
return Detail::convertUnstreamable( value );
#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
return Detail::convertUnstreamable(value);
#else
return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
#endif
}
};
@@ -112,6 +137,13 @@ namespace Catch {
return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
}
#if defined(_MANAGED)
template <typename T>
std::string stringify( T^ e ) {
return ::Catch::StringMaker<T^>::convert(e);
}
#endif
} // namespace Detail
// Some predefined specializations
@@ -135,6 +167,7 @@ namespace Catch {
struct StringMaker<char *> {
static std::string convert(char * str);
};
#ifdef CATCH_CONFIG_WCHAR
template<>
struct StringMaker<wchar_t const *> {
@@ -146,22 +179,24 @@ namespace Catch {
};
#endif
// TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
// while keeping string semantics?
template<int SZ>
struct StringMaker<char[SZ]> {
static std::string convert(const char* str) {
static std::string convert(char const* str) {
return ::Catch::Detail::stringify(std::string{ str });
}
};
template<int SZ>
struct StringMaker<signed char[SZ]> {
static std::string convert(const char* str) {
return ::Catch::Detail::stringify(std::string{ str });
static std::string convert(signed char const* str) {
return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
}
};
template<int SZ>
struct StringMaker<unsigned char[SZ]> {
static std::string convert(const char* str) {
return ::Catch::Detail::stringify(std::string{ str });
static std::string convert(unsigned char const* str) {
return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
}
};
@@ -245,6 +280,15 @@ namespace Catch {
}
};
#if defined(_MANAGED)
template <typename T>
struct StringMaker<T^> {
static std::string convert( T^ ref ) {
return ::Catch::Detail::clrReferenceToString(ref);
}
};
#endif
namespace Detail {
template<typename InputIterator>
std::string rangeToString(InputIterator first, InputIterator last) {
@@ -374,6 +418,13 @@ namespace Catch {
!std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
};
#if defined(_MANAGED) // Managed types are never ranges
template <typename T>
struct is_range<T^> {
static const bool value = false;
};
#endif
template<typename Range>
std::string rangeToString( Range const& range ) {
return ::Catch::Detail::rangeToString( begin( range ), end( range ) );

View File

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

View File

@@ -7,51 +7,145 @@
#include "catch_xmlwriter.h"
#include "catch_enforce.h"
#include <iomanip>
using uchar = unsigned char;
namespace Catch {
namespace {
size_t trailingBytes(unsigned char c) {
if ((c & 0xE0) == 0xC0) {
return 2;
}
if ((c & 0xF0) == 0xE0) {
return 3;
}
if ((c & 0xF8) == 0xF0) {
return 4;
}
CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
}
uint32_t headerValue(unsigned char c) {
if ((c & 0xE0) == 0xC0) {
return c & 0x1F;
}
if ((c & 0xF0) == 0xE0) {
return c & 0x0F;
}
if ((c & 0xF8) == 0xF0) {
return c & 0x07;
}
CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
}
void hexEscapeChar(std::ostream& os, unsigned char c) {
os << "\\x"
<< std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>(c);
}
} // anonymous namespace
XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
: m_str( str ),
m_forWhat( forWhat )
{}
void XmlEncode::encodeTo( std::ostream& os ) const {
// Apostrophe escaping not necessary if we always use " to write attributes
// (see: http://www.w3.org/TR/xml/#syntax)
for( std::size_t i = 0; i < m_str.size(); ++ i ) {
char c = m_str[i];
switch( c ) {
case '<': os << "&lt;"; break;
case '&': os << "&amp;"; break;
for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
uchar c = m_str[idx];
switch (c) {
case '<': os << "&lt;"; break;
case '&': os << "&amp;"; break;
case '>':
// See: http://www.w3.org/TR/xml/#syntax
if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
os << "&gt;";
else
os << c;
case '>':
// See: http://www.w3.org/TR/xml/#syntax
if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
os << "&gt;";
else
os << c;
break;
case '\"':
if (m_forWhat == ForAttributes)
os << "&quot;";
else
os << c;
break;
default:
// Check for control characters and invalid utf-8
// Escape control characters in standard ascii
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
hexEscapeChar(os, c);
break;
}
case '\"':
if( m_forWhat == ForAttributes )
os << "&quot;";
else
os << c;
// Plain ASCII: Write it to stream
if (c < 0x7F) {
os << c;
break;
}
default:
// Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>( c );
}
else
os << c;
// UTF-8 territory
// Check if the encoding is valid and if it is not, hex escape bytes.
// Important: We do not check the exact decoded values for validity, only the encoding format
// First check that this bytes is a valid lead byte:
// This means that it is not encoded as 1111 1XXX
// Or as 10XX XXXX
if (c < 0xC0 ||
c >= 0xF8) {
hexEscapeChar(os, c);
break;
}
auto encBytes = trailingBytes(c);
// Are there enough bytes left to avoid accessing out-of-bounds memory?
if (idx + encBytes - 1 >= m_str.size()) {
hexEscapeChar(os, c);
break;
}
// The header is valid, check data
// The next encBytes bytes must together be a valid utf-8
// This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
bool valid = true;
uint32_t value = headerValue(c);
for (std::size_t n = 1; n < encBytes; ++n) {
uchar nc = m_str[idx + n];
valid &= ((nc & 0xC0) == 0x80);
value = (value << 6) | (nc & 0x3F);
}
if (
// Wrong bit pattern of following bytes
(!valid) ||
// Overlong encodings
(value < 0x80) ||
(0x80 <= value && value < 0x800 && encBytes > 2) ||
(0x800 < value && value < 0x10000 && encBytes > 3) ||
// Encoded value out of range
(value >= 0x110000)
) {
hexEscapeChar(os, c);
break;
}
// If we got here, this is in fact a valid(ish) utf-8 sequence
for (std::size_t n = 0; n < encBytes; ++n) {
os << m_str[idx + n];
}
idx += encBytes - 1;
break;
}
}
}

View File

@@ -56,7 +56,7 @@ namespace Catch {
XmlWriter( std::ostream& os = Catch::cout() );
~XmlWriter();
XmlWriter( XmlWriter const& ) = delete;
XmlWriter& operator=( XmlWriter const& ) = delete;

View File

@@ -13,7 +13,7 @@
#include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h>
#include <cassert>
#include <memory>
namespace Catch {

View File

@@ -14,7 +14,7 @@
#include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h>
#include <cassert>
#include <memory>
#include <ostream>

View File

@@ -13,7 +13,7 @@
#include "../internal/catch_tostring.h"
#include "../internal/catch_reporter_registrars.hpp"
#include <assert.h>
#include <cassert>
#include <sstream>
#include <ctime>
#include <algorithm>

View File

@@ -0,0 +1,136 @@
/*
* Created by Phil on 5/08/2015.
* Copyright 2015 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)
*/
#include "catch_reporter_listening.h"
#include <cassert>
namespace Catch {
void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
m_listeners.push_back( std::move( listener ) );
}
void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
m_reporter = std::move( reporter );
}
ReporterPreferences ListeningReporter::getPreferences() const {
return m_reporter->getPreferences();
}
std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
return std::set<Verbosity>{ };
}
void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
for ( auto const& listener : m_listeners ) {
listener->noMatchingTestCases( spec );
}
m_reporter->noMatchingTestCases( spec );
}
void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
for ( auto const& listener : m_listeners ) {
listener->benchmarkStarting( benchmarkInfo );
}
m_reporter->benchmarkStarting( benchmarkInfo );
}
void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
for ( auto const& listener : m_listeners ) {
listener->benchmarkEnded( benchmarkStats );
}
m_reporter->benchmarkEnded( benchmarkStats );
}
void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
for ( auto const& listener : m_listeners ) {
listener->testRunStarting( testRunInfo );
}
m_reporter->testRunStarting( testRunInfo );
}
void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
for ( auto const& listener : m_listeners ) {
listener->testGroupStarting( groupInfo );
}
m_reporter->testGroupStarting( groupInfo );
}
void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
for ( auto const& listener : m_listeners ) {
listener->testCaseStarting( testInfo );
}
m_reporter->testCaseStarting( testInfo );
}
void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
for ( auto const& listener : m_listeners ) {
listener->sectionStarting( sectionInfo );
}
m_reporter->sectionStarting( sectionInfo );
}
void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
for ( auto const& listener : m_listeners ) {
listener->assertionStarting( assertionInfo );
}
m_reporter->assertionStarting( assertionInfo );
}
// The return value indicates if the messages buffer should be cleared:
bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
for( auto const& listener : m_listeners ) {
static_cast<void>( listener->assertionEnded( assertionStats ) );
}
return m_reporter->assertionEnded( assertionStats );
}
void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
for ( auto const& listener : m_listeners ) {
listener->sectionEnded( sectionStats );
}
m_reporter->sectionEnded( sectionStats );
}
void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
for ( auto const& listener : m_listeners ) {
listener->testCaseEnded( testCaseStats );
}
m_reporter->testCaseEnded( testCaseStats );
}
void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
for ( auto const& listener : m_listeners ) {
listener->testGroupEnded( testGroupStats );
}
m_reporter->testGroupEnded( testGroupStats );
}
void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
for ( auto const& listener : m_listeners ) {
listener->testRunEnded( testRunStats );
}
m_reporter->testRunEnded( testRunStats );
}
void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
for ( auto const& listener : m_listeners ) {
listener->skipTest( testInfo );
}
m_reporter->skipTest( testInfo );
}
bool ListeningReporter::isMulti() const {
return true;
}
} // end namespace Catch

View File

@@ -11,12 +11,14 @@
namespace Catch {
class MultipleReporters : public IStreamingReporter {
class ListeningReporter : public IStreamingReporter {
using Reporters = std::vector<IStreamingReporterPtr>;
Reporters m_reporters;
Reporters m_listeners;
IStreamingReporterPtr m_reporter = nullptr;
public:
void add( IStreamingReporterPtr&& reporter );
void addListener( IStreamingReporterPtr&& listener );
void addReporter( IStreamingReporterPtr&& reporter );
public: // IStreamingReporter

View File

@@ -1,104 +0,0 @@
/*
* Created by Phil on 5/08/2015.
* Copyright 2015 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)
*/
#include "catch_reporter_multi.h"
namespace Catch {
void MultipleReporters::add( IStreamingReporterPtr&& reporter ) {
m_reporters.push_back( std::move( reporter ) );
}
ReporterPreferences MultipleReporters::getPreferences() const {
return m_reporters[0]->getPreferences();
}
std::set<Verbosity> MultipleReporters::getSupportedVerbosities() {
return std::set<Verbosity>{ };
}
void MultipleReporters::noMatchingTestCases( std::string const& spec ) {
for( auto const& reporter : m_reporters )
reporter->noMatchingTestCases( spec );
}
void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
for( auto const& reporter : m_reporters )
reporter->benchmarkStarting( benchmarkInfo );
}
void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
for( auto const& reporter : m_reporters )
reporter->benchmarkEnded( benchmarkStats );
}
void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) {
for( auto const& reporter : m_reporters )
reporter->testRunStarting( testRunInfo );
}
void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) {
for( auto const& reporter : m_reporters )
reporter->testGroupStarting( groupInfo );
}
void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) {
for( auto const& reporter : m_reporters )
reporter->testCaseStarting( testInfo );
}
void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) {
for( auto const& reporter : m_reporters )
reporter->sectionStarting( sectionInfo );
}
void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) {
for( auto const& reporter : m_reporters )
reporter->assertionStarting( assertionInfo );
}
// The return value indicates if the messages buffer should be cleared:
bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) {
bool clearBuffer = false;
for( auto const& reporter : m_reporters )
clearBuffer |= reporter->assertionEnded( assertionStats );
return clearBuffer;
}
void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) {
for( auto const& reporter : m_reporters )
reporter->sectionEnded( sectionStats );
}
void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) {
for( auto const& reporter : m_reporters )
reporter->testCaseEnded( testCaseStats );
}
void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) {
for( auto const& reporter : m_reporters )
reporter->testGroupEnded( testGroupStats );
}
void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) {
for( auto const& reporter : m_reporters )
reporter->testRunEnded( testRunStats );
}
void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) {
for( auto const& reporter : m_reporters )
reporter->skipTest( testInfo );
}
bool MultipleReporters::isMulti() const {
return true;
}
} // end namespace Catch

View File

@@ -10,6 +10,9 @@ Compilation.tests.cpp:<line number>: passed: t1 > t2 for: {?} > {?}
Compilation.tests.cpp:<line number>: passed: t1 <= t2 for: {?} <= {?}
Compilation.tests.cpp:<line number>: passed: t1 >= t2 for: {?} >= {?}
Misc.tests.cpp:<line number>: passed:
Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
Compilation.tests.cpp:<line number>: passed:
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>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -97,6 +100,10 @@ Approx.tests.cpp:<line number>: passed: 0 == Approx( dZero) for: 0 == Approx( 0.
Approx.tests.cpp:<line number>: passed: 0 == Approx( dSmall ).margin( 0.001 ) for: 0 == Approx( 0.00001 )
Approx.tests.cpp:<line number>: passed: 1.234f == Approx( dMedium ) for: 1.234f == Approx( 1.234 )
Approx.tests.cpp:<line number>: passed: dMedium == Approx( 1.234f ) for: 1.234 == Approx( 1.2339999676 )
Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always true") for: 1 matches predicate: "always true"
Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true
@@ -204,14 +211,21 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" (case insensitive)
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("this string contains 'ABC' as a substring") for: "this string contains 'abc' as a substring" equals: "this string contains 'ABC' as a substring"
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("something else", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "something else" (case insensitive)
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" for: "This exception has overriden what() method"
==
"This exception has overriden what() method"
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" for: "OperatorException" == "OperatorException"
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException" for: "StringMakerException"
==
"StringMakerException"
Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: {?} special exception has value of 2
Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
@@ -235,6 +249,10 @@ Matchers.tests.cpp:<line number>: passed: 0., WithinAbs(1., 1) for: 0.0 is withi
Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
Matchers.tests.cpp:<line number>: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan
Matchers.tests.cpp:<line number>: passed: 11., !WithinAbs(10., 0.5) for: 11.0 not is within 0.5 of 10.0
Matchers.tests.cpp:<line number>: passed: 10., !WithinAbs(11., 0.5) for: 10.0 not is within 0.5 of 11.0
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-10., 0.5) for: -10.0 is within 0.5 of -10.0
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-9.6, 0.5) for: -10.0 is within 0.5 of -9.6
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
Matchers.tests.cpp:<line number>: passed: nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
@@ -255,6 +273,10 @@ Matchers.tests.cpp:<line number>: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f
Matchers.tests.cpp:<line number>: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f not is within 0.9900000095 of 1.0
Matchers.tests.cpp:<line number>: passed: 0.f, WithinAbs(-0.f, 0) for: 0.0f is within 0.0 of -0.0
Matchers.tests.cpp:<line number>: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan
Matchers.tests.cpp:<line number>: passed: 11.f, !WithinAbs(10.f, 0.5f) for: 11.0f not is within 0.5 of 10.0
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs(11.f, 0.5f) for: 10.0f not is within 0.5 of 11.0
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-10.f, 0.5f) for: -10.0f is within 0.5 of -10.0
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-9.6f, 0.5f) for: -10.0f is within 0.5 of -9.6000003815
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
@@ -514,7 +536,7 @@ CmdLine.tests.cpp:<line number>: passed: config.processName == "test" for: "test
CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == false for: false == false
CmdLine.tests.cpp:<line number>: passed: config.abortAfter == -1 for: -1 == -1
CmdLine.tests.cpp:<line number>: passed: config.noThrow == false for: false == false
CmdLine.tests.cpp:<line number>: passed: config.reporterNames.empty() for: true
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "console" for: "console" == "console"
CmdLine.tests.cpp:<line number>: passed: !(cfg.hasTestFilters()) for: !false
CmdLine.tests.cpp:<line number>: passed: result for: {?}
CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
@@ -529,15 +551,12 @@ CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) == false for: false == false
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) for: true
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "console"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "console" for: "console" == "console"
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "console" for: "console" == "console"
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "xml"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "xml" for: "xml" == "xml"
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "xml", "-r", "junit"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.reporterNames.size() == 2 for: 2 == 2
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "xml" for: "xml" == "xml"
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[1] == "junit" for: "junit" == "junit"
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "xml" for: "xml" == "xml"
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--reporter", "junit"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "junit" for: "junit" == "junit"
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "junit" for: "junit" == "junit"
CmdLine.tests.cpp:<line number>: passed: !(cli.parse({ "test", "-r", "xml", "-r", "junit" })) for: !{?}
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-b"}) for: {?}
CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == true for: true == true
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--break"}) for: {?}
@@ -897,6 +916,48 @@ Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode:
"don't &quot;quote&quot; me on that"
Xml.tests.cpp:<line number>: passed: encode( "[/x01]" ) == "[//x01]" for: "[/x01]" == "[/x01]"
Xml.tests.cpp:<line number>: passed: encode( "[/x7F]" ) == "[//x7F]" for: "[/x7F]" == "[/x7F]"
Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾"
Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš"
Xml.tests.cpp:<line number>: passed: encode("/xDF/xBF") == "/xDF/xBF" for: "߿" == "߿"
Xml.tests.cpp:<line number>: passed: encode("/xE0/xA0/x80") == "/xE0/xA0/x80" for: "ࠀ" == "ࠀ"
Xml.tests.cpp:<line number>: passed: encode("/xED/x9F/xBF") == "/xED/x9F/xBF" for: "퟿" == "퟿"
Xml.tests.cpp:<line number>: passed: encode("/xEE/x80/x80") == "/xEE/x80/x80" for: "" == ""
Xml.tests.cpp:<line number>: passed: encode("/xEF/xBF/xBF") == "/xEF/xBF/xBF" for: "￿" == "￿"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x90/x80/x80") == "/xF0/x90/x80/x80" for: "𐀀" == "𐀀"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x8F/xBF/xBF") == "/xF4/x8F/xBF/xBF" for: "􏿿" == "􏿿"
Xml.tests.cpp:<line number>: passed: encode("Here /xFF be 👾") == u8"Here //xFF be 👾" for: "Here /xFF be 👾" == "Here /xFF be 👾"
Xml.tests.cpp:<line number>: passed: encode("/xFF") == "//xFF" for: "/xFF" == "/xFF"
Xml.tests.cpp:<line number>: passed: encode("/xC5/xC5/xA0") == u8"//xC5Š" for: "/xC5Š" == "/xC5Š"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x90/x80/x80") == u8"//xF4//x90//x80//x80" for: "/xF4/x90/x80/x80" == "/xF4/x90/x80/x80"
Xml.tests.cpp:<line number>: passed: encode("/xC0/x80") == u8"//xC0//x80" for: "/xC0/x80" == "/xC0/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80/x80/x80") == u8"//xF0//x80//x80//x80" for: "/xF0/x80/x80/x80" == "/xF0/x80/x80/x80"
Xml.tests.cpp:<line number>: passed: encode("/xC1/xBF") == u8"//xC1//xBF" for: "/xC1/xBF" == "/xC1/xBF"
Xml.tests.cpp:<line number>: passed: encode("/xE0/x9F/xBF") == u8"//xE0//x9F//xBF" for: "/xE0/x9F/xBF" == "/xE0/x9F/xBF"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x8F/xBF/xBF") == u8"//xF0//x8F//xBF//xBF" for: "/xF0/x8F/xBF/xBF" == "/xF0/x8F/xBF/xBF"
Xml.tests.cpp:<line number>: passed: encode("/xED/xA0/x80") == "/xED/xA0/x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/xED/xAF/xBF") == "/xED/xAF/xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/xED/xB0/x80") == "/xED/xB0/x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/xED/xBF/xBF") == "/xED/xBF/xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>: passed: encode("/x80") == u8"//x80" for: "/x80" == "/x80"
Xml.tests.cpp:<line number>: passed: encode("/x81") == u8"//x81" for: "/x81" == "/x81"
Xml.tests.cpp:<line number>: passed: encode("/xBC") == u8"//xBC" for: "/xBC" == "/xBC"
Xml.tests.cpp:<line number>: passed: encode("/xBF") == u8"//xBF" for: "/xBF" == "/xBF"
Xml.tests.cpp:<line number>: passed: encode("/xF5/x80/x80/x80") == u8"//xF5//x80//x80//x80" for: "/xF5/x80/x80/x80" == "/xF5/x80/x80/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF6/x80/x80/x80") == u8"//xF6//x80//x80//x80" for: "/xF6/x80/x80/x80" == "/xF6/x80/x80/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF7/x80/x80/x80") == u8"//xF7//x80//x80//x80" for: "/xF7/x80/x80/x80" == "/xF7/x80/x80/x80"
Xml.tests.cpp:<line number>: passed: encode("/xDE") == u8"//xDE" for: "/xDE" == "/xDE"
Xml.tests.cpp:<line number>: passed: encode("/xDF") == u8"//xDF" for: "/xDF" == "/xDF"
Xml.tests.cpp:<line number>: passed: encode("/xE0") == u8"//xE0" for: "/xE0" == "/xE0"
Xml.tests.cpp:<line number>: passed: encode("/xEF") == u8"//xEF" for: "/xEF" == "/xEF"
Xml.tests.cpp:<line number>: passed: encode("/xF0") == u8"//xF0" for: "/xF0" == "/xF0"
Xml.tests.cpp:<line number>: passed: encode("/xF4") == u8"//xF4" for: "/xF4" == "/xF4"
Xml.tests.cpp:<line number>: passed: encode("/xE0/x80") == u8"//xE0//x80" for: "/xE0/x80" == "/xE0/x80"
Xml.tests.cpp:<line number>: passed: encode("/xE0/xBF") == u8"//xE0//xBF" for: "/xE0/xBF" == "/xE0/xBF"
Xml.tests.cpp:<line number>: passed: encode("/xE1/x80") == u8"//xE1//x80" for: "/xE1/x80" == "/xE1/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80") == u8"//xF0//x80" for: "/xF0/x80" == "/xF0/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x80") == u8"//xF4//x80" for: "/xF4/x80" == "/xF4/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80/x80") == u8"//xF0//x80//x80" for: "/xF0/x80/x80" == "/xF0/x80/x80"
Xml.tests.cpp:<line number>: passed: encode("/xF4/x80/x80") == u8"//xF4//x80//x80" for: "/xF4/x80/x80" == "/xF4/x80/x80"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
@@ -1004,6 +1065,9 @@ ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(item)
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" for: "operator<<( has_operator )"
==
"operator<<( has_operator )"
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" for: "operator<<( has_template_operator )"
==
"operator<<( has_template_operator )"
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" for: "{ StringMaker<has_maker> }"
==
"{ StringMaker<has_maker> }"

View File

@@ -335,12 +335,12 @@ Matchers.tests.cpp:<line number>
Matchers.tests.cpp:<line number>: FAILED:
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
with expansion:
{?} special exception has value of 1
SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: FAILED:
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
with expansion:
{?} special exception has value of 1
SpecialException::what special exception has value of 1
-------------------------------------------------------------------------------
Expected exceptions that don't throw or unexpected exceptions fail the test
@@ -1084,6 +1084,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 202 | 149 passed | 49 failed | 4 failed as expected
assertions: 1007 | 879 passed | 107 failed | 21 failed as expected
test cases: 208 | 155 passed | 49 failed | 4 failed as expected
assertions: 1065 | 937 passed | 107 failed | 21 failed as expected

View File

@@ -102,6 +102,39 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>:
PASSED:
-------------------------------------------------------------------------------
#1238
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>:
PASSED:
REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
with expansion:
0 == 0
with messages:
uarr := "123"
sarr := "456"
Compilation.tests.cpp:<line number>:
PASSED:
REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
with expansion:
0 == 0
with messages:
uarr := "123"
sarr := "456"
-------------------------------------------------------------------------------
#1245
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>:
PASSED:
-------------------------------------------------------------------------------
#748 - captures with unexpected exceptions
outside assertions
@@ -814,6 +847,44 @@ PASSED:
with expansion:
1.234 == Approx( 1.2339999676 )
-------------------------------------------------------------------------------
Arbitrary predicate matcher
Function pointer
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( 1, Predicate<int>(alwaysTrue, "always true") )
with expansion:
1 matches predicate: "always true"
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( 1, !Predicate<int>(alwaysFalse, "always false") )
with expansion:
1 not matches predicate: "always false"
-------------------------------------------------------------------------------
Arbitrary predicate matcher
Lambdas + different type
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") )
with expansion:
"Hello olleH" matches predicate: "First and last character should be equal"
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) )
with expansion:
"This wouldn't pass" not matches undescribed predicate
-------------------------------------------------------------------------------
Assertions then sections
-------------------------------------------------------------------------------
@@ -1609,6 +1680,34 @@ with expansion:
"this string contains 'abc' as a substring" equals: "something else" (case
insensitive)
-------------------------------------------------------------------------------
Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified
-------------------------------------------------------------------------------
ToStringGeneral.tests.cpp:<line number>
...............................................................................
ToStringGeneral.tests.cpp:<line number>:
PASSED:
REQUIRE( ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" )
with expansion:
"This exception has overriden what() method"
==
"This exception has overriden what() method"
ToStringGeneral.tests.cpp:<line number>:
PASSED:
REQUIRE( ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" )
with expansion:
"OperatorException" == "OperatorException"
ToStringGeneral.tests.cpp:<line number>:
PASSED:
REQUIRE( ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException" )
with expansion:
"StringMakerException"
==
"StringMakerException"
-------------------------------------------------------------------------------
Exception matchers that fail
No exception
@@ -1651,12 +1750,12 @@ Matchers.tests.cpp:<line number>
Matchers.tests.cpp:<line number>: FAILED:
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
with expansion:
{?} special exception has value of 1
SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: FAILED:
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
with expansion:
{?} special exception has value of 1
SpecialException::what special exception has value of 1
-------------------------------------------------------------------------------
Exception matchers that succeed
@@ -1668,13 +1767,13 @@ Matchers.tests.cpp:<line number>:
PASSED:
CHECK_THROWS_MATCHES( throws(1), SpecialException, ExceptionMatcher{1} )
with expansion:
{?} special exception has value of 1
SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_MATCHES( throws(2), SpecialException, ExceptionMatcher{2} )
with expansion:
{?} special exception has value of 2
SpecialException::what special exception has value of 2
-------------------------------------------------------------------------------
Exception messages can be tested for
@@ -1858,6 +1957,30 @@ PASSED:
with expansion:
nanf not is within 0.0 of nan
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( 11., !WithinAbs(10., 0.5) )
with expansion:
11.0 not is within 0.5 of 10.0
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( 10., !WithinAbs(11., 0.5) )
with expansion:
10.0 not is within 0.5 of 11.0
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( -10., WithinAbs(-10., 0.5) )
with expansion:
-10.0 is within 0.5 of -10.0
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( -10., WithinAbs(-9.6, 0.5) )
with expansion:
-10.0 is within 0.5 of -9.6
-------------------------------------------------------------------------------
Floating point matchers: double
ULPs
@@ -1998,6 +2121,30 @@ PASSED:
with expansion:
nanf not is within 0.0 of nan
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( 11.f, !WithinAbs(10.f, 0.5f) )
with expansion:
11.0f not is within 0.5 of 10.0
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( 10.f, !WithinAbs(11.f, 0.5f) )
with expansion:
10.0f not is within 0.5 of 11.0
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( -10.f, WithinAbs(-10.f, 0.5f) )
with expansion:
-10.0f is within 0.5 of -10.0
Matchers.tests.cpp:<line number>:
PASSED:
REQUIRE_THAT( -10.f, WithinAbs(-9.6f, 0.5f) )
with expansion:
-10.0f is within 0.5 of -9.6000003815
-------------------------------------------------------------------------------
Floating point matchers: float
ULPs
@@ -3970,9 +4117,9 @@ with expansion:
CmdLine.tests.cpp:<line number>:
PASSED:
CHECK( config.reporterNames.empty() )
CHECK( config.reporterName == "console" )
with expansion:
true
"console" == "console"
CmdLine.tests.cpp:<line number>:
PASSED:
@@ -4092,7 +4239,7 @@ with expansion:
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE( config.reporterNames[0] == "console" )
REQUIRE( config.reporterName == "console" )
with expansion:
"console" == "console"
@@ -4112,42 +4259,10 @@ with expansion:
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE( config.reporterNames[0] == "xml" )
REQUIRE( config.reporterName == "xml" )
with expansion:
"xml" == "xml"
-------------------------------------------------------------------------------
Process can be configured on command line
reporter
-r xml and junit
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>:
PASSED:
CHECK( cli.parse({"test", "-r", "xml", "-r", "junit"}) )
with expansion:
{?}
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE( config.reporterNames.size() == 2 )
with expansion:
2 == 2
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE( config.reporterNames[0] == "xml" )
with expansion:
"xml" == "xml"
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE( config.reporterNames[1] == "junit" )
with expansion:
"junit" == "junit"
-------------------------------------------------------------------------------
Process can be configured on command line
reporter
@@ -4164,10 +4279,24 @@ with expansion:
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE( config.reporterNames[0] == "junit" )
REQUIRE( config.reporterName == "junit" )
with expansion:
"junit" == "junit"
-------------------------------------------------------------------------------
Process can be configured on command line
reporter
Only one reporter is accepted
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>:
PASSED:
REQUIRE_FALSE( cli.parse({ "test", "-r", "xml", "-r", "junit" }) )
with expansion:
!{?}
-------------------------------------------------------------------------------
Process can be configured on command line
debugger
@@ -7064,6 +7193,305 @@ PASSED:
with expansion:
"[\x7F]" == "[\x7F]"
-------------------------------------------------------------------------------
XmlEncode: UTF-8
Valid utf-8 strings
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode(u8"Here be 👾") == u8"Here be 👾" )
with expansion:
"Here be 👾" == "Here be 👾"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode(u8"šš") == u8"šš" )
with expansion:
"šš" == "šš"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xDF\xBF") == "\xDF\xBF" )
with expansion:
"߿" == "߿"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xE0\xA0\x80") == "\xE0\xA0\x80" )
with expansion:
"ࠀ" == "ࠀ"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xED\x9F\xBF") == "\xED\x9F\xBF" )
with expansion:
"퟿" == "퟿"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xEE\x80\x80") == "\xEE\x80\x80" )
with expansion:
"" == ""
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" )
with expansion:
"￿" == "￿"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" )
with expansion:
"𐀀" == "𐀀"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" )
with expansion:
"􏿿" == "􏿿"
-------------------------------------------------------------------------------
XmlEncode: UTF-8
Invalid utf-8 strings
Various broken strings
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" )
with expansion:
"Here \xFF be 👾" == "Here \xFF be 👾"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xFF") == "\\xFF" )
with expansion:
"\xFF" == "\xFF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xC5\xC5\xA0") == u8"\\xC5Š" )
with expansion:
"\xC5Š" == "\xC5Š"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" )
with expansion:
"\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
-------------------------------------------------------------------------------
XmlEncode: UTF-8
Invalid utf-8 strings
Overlong encodings
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xC0\x80") == u8"\\xC0\\x80" )
with expansion:
"\xC0\x80" == "\xC0\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" )
with expansion:
"\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xC1\xBF") == u8"\\xC1\\xBF" )
with expansion:
"\xC1\xBF" == "\xC1\xBF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" )
with expansion:
"\xE0\x9F\xBF" == "\xE0\x9F\xBF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" )
with expansion:
"\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
-------------------------------------------------------------------------------
XmlEncode: UTF-8
Invalid utf-8 strings
Surrogate pairs
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xED\xA0\x80") == "\xED\xA0\x80" )
with expansion:
"<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xED\xAF\xBF") == "\xED\xAF\xBF" )
with expansion:
"<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xED\xB0\x80") == "\xED\xB0\x80" )
with expansion:
"<22><><EFBFBD>" == "<22><><EFBFBD>"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xED\xBF\xBF") == "\xED\xBF\xBF" )
with expansion:
"<22><><EFBFBD>" == "<22><><EFBFBD>"
-------------------------------------------------------------------------------
XmlEncode: UTF-8
Invalid utf-8 strings
Invalid start byte
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\x80") == u8"\\x80" )
with expansion:
"\x80" == "\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\x81") == u8"\\x81" )
with expansion:
"\x81" == "\x81"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xBC") == u8"\\xBC" )
with expansion:
"\xBC" == "\xBC"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xBF") == u8"\\xBF" )
with expansion:
"\xBF" == "\xBF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" )
with expansion:
"\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" )
with expansion:
"\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" )
with expansion:
"\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
-------------------------------------------------------------------------------
XmlEncode: UTF-8
Invalid utf-8 strings
Missing continuation byte(s)
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xDE") == u8"\\xDE" )
with expansion:
"\xDE" == "\xDE"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xDF") == u8"\\xDF" )
with expansion:
"\xDF" == "\xDF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xE0") == u8"\\xE0" )
with expansion:
"\xE0" == "\xE0"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xEF") == u8"\\xEF" )
with expansion:
"\xEF" == "\xEF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF0") == u8"\\xF0" )
with expansion:
"\xF0" == "\xF0"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF4") == u8"\\xF4" )
with expansion:
"\xF4" == "\xF4"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xE0\x80") == u8"\\xE0\\x80" )
with expansion:
"\xE0\x80" == "\xE0\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xE0\xBF") == u8"\\xE0\\xBF" )
with expansion:
"\xE0\xBF" == "\xE0\xBF"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xE1\x80") == u8"\\xE1\\x80" )
with expansion:
"\xE1\x80" == "\xE1\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF0\x80") == u8"\\xF0\\x80" )
with expansion:
"\xF0\x80" == "\xF0\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF4\x80") == u8"\\xF4\\x80" )
with expansion:
"\xF4\x80" == "\xF4\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" )
with expansion:
"\xF0\x80\x80" == "\xF0\x80\x80"
Xml.tests.cpp:<line number>:
PASSED:
CHECK( encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" )
with expansion:
"\xF4\x80\x80" == "\xF4\x80\x80"
-------------------------------------------------------------------------------
array<int, N> -> toString
-------------------------------------------------------------------------------
@@ -7979,6 +8407,20 @@ with expansion:
==
"operator<<( has_operator )"
-------------------------------------------------------------------------------
stringify( has_template_operator )
-------------------------------------------------------------------------------
ToStringWhich.tests.cpp:<line number>
...............................................................................
ToStringWhich.tests.cpp:<line number>:
PASSED:
REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" )
with expansion:
"operator<<( has_template_operator )"
==
"operator<<( has_template_operator )"
-------------------------------------------------------------------------------
stringify( vectors<has_maker> )
-------------------------------------------------------------------------------
@@ -8550,6 +8992,6 @@ Misc.tests.cpp:<line number>:
PASSED:
===============================================================================
test cases: 202 | 136 passed | 62 failed | 4 failed as expected
assertions: 1021 | 879 passed | 121 failed | 21 failed as expected
test cases: 208 | 142 passed | 62 failed | 4 failed as expected
assertions: 1079 | 937 passed | 121 failed | 21 failed as expected

View File

@@ -102,6 +102,39 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>:
PASSED:
-------------------------------------------------------------------------------
#1238
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>:
PASSED:
REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
with expansion:
0 == 0
with messages:
uarr := "123"
sarr := "456"
Compilation.tests.cpp:<line number>:
PASSED:
REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
with expansion:
0 == 0
with messages:
uarr := "123"
sarr := "456"
-------------------------------------------------------------------------------
#1245
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>:
PASSED:
-------------------------------------------------------------------------------
#748 - captures with unexpected exceptions
outside assertions
@@ -308,6 +341,6 @@ with expansion:
!true
===============================================================================
test cases: 12 | 9 passed | 1 failed | 2 failed as expected
assertions: 35 | 28 passed | 4 failed | 3 failed as expected
test cases: 14 | 11 passed | 1 failed | 2 failed as expected
assertions: 38 | 31 passed | 4 failed | 3 failed as expected

View File

@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="105" tests="1022" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="105" tests="1080" 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="#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="#1147" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1175 - Hidden Test" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
<testcase classname="<exe-name>.(Fixture_1245&lt;int, int>)" name="#1245" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
<error type="TEST_CASE">
expected exception
@@ -110,6 +112,8 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Approximate comparisons with floats" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Approximate comparisons with ints" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>
@@ -214,6 +218,7 @@ Matchers.tests.cpp:<line number>
Matchers.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Exception matchers that fail/No exception" time="{duration}">
<failure message="doesNotThrow(), SpecialException, ExceptionMatcher{1}" type="CHECK_THROWS_MATCHES">
Matchers.tests.cpp:<line number>
@@ -233,10 +238,10 @@ Matchers.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="Exception matchers that fail/Contents are wrong" time="{duration}">
<failure message="{?} special exception has value of 1" type="CHECK_THROWS_MATCHES">
<failure message="SpecialException::what special exception has value of 1" type="CHECK_THROWS_MATCHES">
Matchers.tests.cpp:<line number>
</failure>
<failure message="{?} special exception has value of 1" type="REQUIRE_THROWS_MATCHES">
<failure message="SpecialException::what special exception has value of 1" type="REQUIRE_THROWS_MATCHES">
Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -471,8 +476,8 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case exclusion using ~" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/console" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/xml" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r xml and junit" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/--reporter/junit" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/Only one reporter is accepted" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/-b" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/--break" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-a aborts after first failure" time="{duration}"/>
@@ -706,6 +711,12 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="XmlEncode/string with quotes" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (1)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (x7F)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Valid utf-8 strings" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Various broken strings" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Overlong encodings" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Surrogate pairs" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Invalid start byte" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Missing continuation byte(s)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="array&lt;int, N> -> toString" time="{duration}"/>
<testcase classname="<exe-name>.global" name="atomic if" time="{duration}"/>
<testcase classname="<exe-name>.global" name="boolean member" time="{duration}"/>
@@ -827,6 +838,7 @@ Tricky.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="stringify( has_maker_and_operator )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( has_neither )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( has_operator )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( has_template_operator )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_maker> )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_maker_and_operator> )" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_operator> )" time="{duration}"/>

View File

@@ -96,6 +96,40 @@
<TestCase name="#1175 - Hidden Test" tags="[.]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1238" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Info>
uarr := "123"
</Info>
<Info>
sarr := "456"
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
std::memcmp(uarr, "123", sizeof(uarr)) == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<Info>
uarr := "123"
</Info>
<Info>
sarr := "456"
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
std::memcmp(sarr, "456", sizeof(sarr)) == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1245" tags="[compilation]" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<OverallResult success="true"/>
</TestCase>
<TestCase name="#748 - captures with unexpected exceptions" tags="[!shouldfail][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Section name="outside assertions" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Info>
@@ -870,6 +904,47 @@
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Arbitrary predicate matcher" tags="[generic][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Function pointer" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
1, Predicate&lt;int>(alwaysTrue, "always true")
</Original>
<Expanded>
1 matches predicate: "always true"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
1, !Predicate&lt;int>(alwaysFalse, "always false")
</Original>
<Expanded>
1 not matches predicate: "always false"
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="Lambdas + different type" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
"Hello olleH", Predicate&lt;std::string>( [] (std::string const&amp; str) -> bool { return str.front() == str.back(); }, "First and last character should be equal")
</Original>
<Expanded>
"Hello olleH" matches predicate: "First and last character should be equal"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
"This wouldn't pass", !Predicate&lt;std::string>( [] (std::string const&amp; str) -> bool { return str.front() == str.back(); } )
</Original>
<Expanded>
"This wouldn't pass" not matches undescribed predicate
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Assertions then sections" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Original>
@@ -1826,6 +1901,37 @@
</Expression>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified" tags="[exception][toString]" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
<Original>
::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method"
</Original>
<Expanded>
"This exception has overriden what() method"
==
"This exception has overriden what() method"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
<Original>
::Catch::Detail::stringify(OperatorException{}) == "OperatorException"
</Original>
<Expanded>
"OperatorException" == "OperatorException"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
<Original>
::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException"
</Original>
<Expanded>
"StringMakerException"
==
"StringMakerException"
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Exception matchers that fail" tags="[!throws][.][.failing][exceptions][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="No exception" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -1877,7 +1983,7 @@
throws(3), SpecialException, ExceptionMatcher{1}
</Original>
<Expanded>
{?} special exception has value of 1
SpecialException::what special exception has value of 1
</Expanded>
</Expression>
<Expression success="false" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -1885,7 +1991,7 @@
throws(4), SpecialException, ExceptionMatcher{1}
</Original>
<Expanded>
{?} special exception has value of 1
SpecialException::what special exception has value of 1
</Expanded>
</Expression>
<OverallResults successes="0" failures="2" expectedFailures="0"/>
@@ -1898,7 +2004,7 @@
throws(1), SpecialException, ExceptionMatcher{1}
</Original>
<Expanded>
{?} special exception has value of 1
SpecialException::what special exception has value of 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -1906,7 +2012,7 @@
throws(2), SpecialException, ExceptionMatcher{2}
</Original>
<Expanded>
{?} special exception has value of 2
SpecialException::what special exception has value of 2
</Expanded>
</Expression>
<OverallResult success="true"/>
@@ -2108,7 +2214,39 @@
nanf not is within 0.0 of nan
</Expanded>
</Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
11., !WithinAbs(10., 0.5)
</Original>
<Expanded>
11.0 not is within 0.5 of 10.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
10., !WithinAbs(11., 0.5)
</Original>
<Expanded>
10.0 not is within 0.5 of 11.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
-10., WithinAbs(-10., 0.5)
</Original>
<Expanded>
-10.0 is within 0.5 of -10.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
-10., WithinAbs(-9.6, 0.5)
</Original>
<Expanded>
-10.0 is within 0.5 of -9.6
</Expanded>
</Expression>
<OverallResults successes="9" failures="0" expectedFailures="0"/>
</Section>
<Section name="ULPs" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -2283,7 +2421,39 @@
nanf not is within 0.0 of nan
</Expanded>
</Expression>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
11.f, !WithinAbs(10.f, 0.5f)
</Original>
<Expanded>
11.0f not is within 0.5 of 10.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
10.f, !WithinAbs(11.f, 0.5f)
</Original>
<Expanded>
10.0f not is within 0.5 of 11.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
-10.f, WithinAbs(-10.f, 0.5f)
</Original>
<Expanded>
-10.0f is within 0.5 of -10.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
-10.f, WithinAbs(-9.6f, 0.5f)
</Original>
<Expanded>
-10.0f is within 0.5 of -9.6000003815
</Expanded>
</Expression>
<OverallResults successes="10" failures="0" expectedFailures="0"/>
</Section>
<Section name="ULPs" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -4621,10 +4791,10 @@
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames.empty()
config.reporterName == "console"
</Original>
<Expanded>
true
"console" == "console"
</Expanded>
</Expression>
<Expression success="true" type="CHECK_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -4763,7 +4933,7 @@
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames[0] == "console"
config.reporterName == "console"
</Original>
<Expanded>
"console" == "console"
@@ -4785,7 +4955,7 @@
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames[0] == "xml"
config.reporterName == "xml"
</Original>
<Expanded>
"xml" == "xml"
@@ -4795,44 +4965,6 @@
</Section>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Section name="-r xml and junit" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
cli.parse({"test", "-r", "xml", "-r", "junit"})
</Original>
<Expanded>
{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames.size() == 2
</Original>
<Expanded>
2 == 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames[0] == "xml"
</Original>
<Expanded>
"xml" == "xml"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames[1] == "junit"
</Original>
<Expanded>
"junit" == "junit"
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Section name="--reporter/junit" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -4845,7 +4977,7 @@
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
config.reporterNames[0] == "junit"
config.reporterName == "junit"
</Original>
<Expanded>
"junit" == "junit"
@@ -4855,6 +4987,20 @@
</Section>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Section name="Only one reporter is accepted" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(cli.parse({ "test", "-r", "xml", "-r", "junit" }))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="debugger" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Section name="-b" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -7817,7 +7963,7 @@ Message from section two
<TestCase name="X/level/1/b" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<OverallResult success="true"/>
</TestCase>
<TestCase name="XmlEncode" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<TestCase name="XmlEncode" tags="[XML]" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="normal string" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
@@ -7930,6 +8076,378 @@ Message from section two
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="XmlEncode: UTF-8" tags="[UTF-8][XML]" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="Valid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode(u8"Here be 👾") == u8"Here be 👾"
</Original>
<Expanded>
"Here be 👾" == "Here be 👾"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode(u8"šš") == u8"šš"
</Original>
<Expanded>
"šš" == "šš"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xDF\xBF") == "\xDF\xBF"
</Original>
<Expanded>
"߿" == "߿"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xE0\xA0\x80") == "\xE0\xA0\x80"
</Original>
<Expanded>
"ࠀ" == "ࠀ"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xED\x9F\xBF") == "\xED\x9F\xBF"
</Original>
<Expanded>
"퟿" == "퟿"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xEE\x80\x80") == "\xEE\x80\x80"
</Original>
<Expanded>
"" == ""
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF"
</Original>
<Expanded>
"￿" == "￿"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80"
</Original>
<Expanded>
"𐀀" == "𐀀"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF"
</Original>
<Expanded>
"􏿿" == "􏿿"
</Expanded>
</Expression>
<OverallResults successes="9" failures="0" expectedFailures="0"/>
</Section>
<Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="Various broken strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("Here \xFF be 👾") == u8"Here \\xFF be 👾"
</Original>
<Expanded>
"Here \xFF be 👾" == "Here \xFF be 👾"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xFF") == "\\xFF"
</Original>
<Expanded>
"\xFF" == "\xFF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xC5\xC5\xA0") == u8"\\xC5Š"
</Original>
<Expanded>
"\xC5Š" == "\xC5Š"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"
</Original>
<Expanded>
"\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="Overlong encodings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xC0\x80") == u8"\\xC0\\x80"
</Original>
<Expanded>
"\xC0\x80" == "\xC0\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"
</Original>
<Expanded>
"\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xC1\xBF") == u8"\\xC1\\xBF"
</Original>
<Expanded>
"\xC1\xBF" == "\xC1\xBF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"
</Original>
<Expanded>
"\xE0\x9F\xBF" == "\xE0\x9F\xBF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"
</Original>
<Expanded>
"\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
</Expanded>
</Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
</Section>
<Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="Surrogate pairs" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xED\xA0\x80") == "\xED\xA0\x80"
</Original>
<Expanded>
"<22><><EFBFBD>" == "<22><><EFBFBD>"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xED\xAF\xBF") == "\xED\xAF\xBF"
</Original>
<Expanded>
"<22><><EFBFBD>" == "<22><><EFBFBD>"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xED\xB0\x80") == "\xED\xB0\x80"
</Original>
<Expanded>
"<22><><EFBFBD>" == "<22><><EFBFBD>"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xED\xBF\xBF") == "\xED\xBF\xBF"
</Original>
<Expanded>
"<22><><EFBFBD>" == "<22><><EFBFBD>"
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="Invalid start byte" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\x80") == u8"\\x80"
</Original>
<Expanded>
"\x80" == "\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\x81") == u8"\\x81"
</Original>
<Expanded>
"\x81" == "\x81"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xBC") == u8"\\xBC"
</Original>
<Expanded>
"\xBC" == "\xBC"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xBF") == u8"\\xBF"
</Original>
<Expanded>
"\xBF" == "\xBF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80"
</Original>
<Expanded>
"\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80"
</Original>
<Expanded>
"\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80"
</Original>
<Expanded>
"\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
</Expanded>
</Expression>
<OverallResults successes="7" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="7" failures="0" expectedFailures="0"/>
</Section>
<Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Section name="Missing continuation byte(s)" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xDE") == u8"\\xDE"
</Original>
<Expanded>
"\xDE" == "\xDE"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xDF") == u8"\\xDF"
</Original>
<Expanded>
"\xDF" == "\xDF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xE0") == u8"\\xE0"
</Original>
<Expanded>
"\xE0" == "\xE0"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xEF") == u8"\\xEF"
</Original>
<Expanded>
"\xEF" == "\xEF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF0") == u8"\\xF0"
</Original>
<Expanded>
"\xF0" == "\xF0"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF4") == u8"\\xF4"
</Original>
<Expanded>
"\xF4" == "\xF4"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xE0\x80") == u8"\\xE0\\x80"
</Original>
<Expanded>
"\xE0\x80" == "\xE0\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xE0\xBF") == u8"\\xE0\\xBF"
</Original>
<Expanded>
"\xE0\xBF" == "\xE0\xBF"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xE1\x80") == u8"\\xE1\\x80"
</Original>
<Expanded>
"\xE1\x80" == "\xE1\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF0\x80") == u8"\\xF0\\x80"
</Original>
<Expanded>
"\xF0\x80" == "\xF0\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF4\x80") == u8"\\xF4\\x80"
</Original>
<Expanded>
"\xF4\x80" == "\xF4\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80"
</Original>
<Expanded>
"\xF0\x80\x80" == "\xF0\x80\x80"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80"
</Original>
<Expanded>
"\xF4\x80\x80" == "\xF4\x80\x80"
</Expanded>
</Expression>
<OverallResults successes="13" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="13" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="array&lt;int, N> -> toString" tags="[array][containers][toString]" filename="projects/<exe-name>/UsageTests/ToStringVector.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringVector.tests.cpp" >
<Original>
@@ -8848,6 +9366,19 @@ loose text artifact
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="stringify( has_template_operator )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
<Original>
::Catch::Detail::stringify( item ) == "operator&lt;&lt;( has_template_operator )"
</Original>
<Expanded>
"operator&lt;&lt;( has_template_operator )"
==
"operator&lt;&lt;( has_template_operator )"
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="stringify( vectors&lt;has_maker> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
<Original>
@@ -9405,7 +9936,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="879" failures="122" expectedFailures="21"/>
<OverallResults successes="937" failures="122" expectedFailures="21"/>
</Group>
<OverallResults successes="879" failures="121" expectedFailures="21"/>
<OverallResults successes="937" failures="121" expectedFailures="21"/>
</Catch>

View File

@@ -288,7 +288,7 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
CHECK(config.shouldDebugBreak == false);
CHECK(config.abortAfter == -1);
CHECK(config.noThrow == false);
CHECK(config.reporterNames.empty());
CHECK(config.reporterName == "console");
Catch::Config cfg(config);
CHECK_FALSE(cfg.hasTestFilters());
@@ -330,24 +330,20 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
SECTION("-r/console") {
CHECK(cli.parse({"test", "-r", "console"}));
REQUIRE(config.reporterNames[0] == "console");
REQUIRE(config.reporterName == "console");
}
SECTION("-r/xml") {
CHECK(cli.parse({"test", "-r", "xml"}));
REQUIRE(config.reporterNames[0] == "xml");
}
SECTION("-r xml and junit") {
CHECK(cli.parse({"test", "-r", "xml", "-r", "junit"}));
REQUIRE(config.reporterNames.size() == 2);
REQUIRE(config.reporterNames[0] == "xml");
REQUIRE(config.reporterNames[1] == "junit");
REQUIRE(config.reporterName == "xml");
}
SECTION("--reporter/junit") {
CHECK(cli.parse({"test", "--reporter", "junit"}));
REQUIRE(config.reporterNames[0] == "junit");
REQUIRE(config.reporterName == "junit");
}
SECTION("Only one reporter is accepted") {
REQUIRE_FALSE(cli.parse({ "test", "-r", "xml", "-r", "junit" }));
}
}

View File

@@ -1,5 +1,4 @@
#include "catch.hpp"
#include "internal/catch_xmlwriter.h"
#include <sstream>
@@ -10,7 +9,7 @@ inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat for
return oss.str();
}
TEST_CASE( "XmlEncode" ) {
TEST_CASE( "XmlEncode", "[XML]" ) {
SECTION( "normal string" ) {
REQUIRE( encode( "normal string" ) == "normal string" );
}
@@ -38,4 +37,76 @@ TEST_CASE( "XmlEncode" ) {
SECTION( "string with control char (x7F)" ) {
REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" );
}
}
}
// Thanks to Peter Bindels (dascandy) for some of the tests
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
SECTION("Valid utf-8 strings") {
CHECK(encode(u8"Here be 👾") == u8"Here be 👾");
CHECK(encode(u8"šš") == u8"šš");
CHECK(encode("\xDF\xBF") == "\xDF\xBF"); // 0x7FF
CHECK(encode("\xE0\xA0\x80") == "\xE0\xA0\x80"); // 0x800
CHECK(encode("\xED\x9F\xBF") == "\xED\x9F\xBF"); // 0xD7FF
CHECK(encode("\xEE\x80\x80") == "\xEE\x80\x80"); // 0xE000
CHECK(encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF"); // 0xFFFF
CHECK(encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80"); // 0x10000
CHECK(encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF"); // 0x10FFFF
}
SECTION("Invalid utf-8 strings") {
SECTION("Various broken strings") {
CHECK(encode("Here \xFF be 👾") == u8"Here \\xFF be 👾");
CHECK(encode("\xFF") == "\\xFF");
CHECK(encode("\xC5\xC5\xA0") == u8"\\xC5Š");
CHECK(encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"); // 0x110000 -- out of unicode range
}
SECTION("Overlong encodings") {
CHECK(encode("\xC0\x80") == u8"\\xC0\\x80"); // \0
CHECK(encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"); // Super-over-long \0
CHECK(encode("\xC1\xBF") == u8"\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
CHECK(encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"); // 0x7FF
CHECK(encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
}
// Note that we actually don't modify surrogate pairs, as we do not do strict checking
SECTION("Surrogate pairs") {
CHECK(encode("\xED\xA0\x80") == "\xED\xA0\x80"); // Invalid surrogate half 0xD800
CHECK(encode("\xED\xAF\xBF") == "\xED\xAF\xBF"); // Invalid surrogate half 0xDBFF
CHECK(encode("\xED\xB0\x80") == "\xED\xB0\x80"); // Invalid surrogate half 0xDC00
CHECK(encode("\xED\xBF\xBF") == "\xED\xBF\xBF"); // Invalid surrogate half 0xDFFF
}
SECTION("Invalid start byte") {
CHECK(encode("\x80") == u8"\\x80");
CHECK(encode("\x81") == u8"\\x81");
CHECK(encode("\xBC") == u8"\\xBC");
CHECK(encode("\xBF") == u8"\\xBF");
// Out of range
CHECK(encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80");
CHECK(encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80");
CHECK(encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80");
}
SECTION("Missing continuation byte(s)") {
// Missing first continuation byte
CHECK(encode("\xDE") == u8"\\xDE");
CHECK(encode("\xDF") == u8"\\xDF");
CHECK(encode("\xE0") == u8"\\xE0");
CHECK(encode("\xEF") == u8"\\xEF");
CHECK(encode("\xF0") == u8"\\xF0");
CHECK(encode("\xF4") == u8"\\xF4");
// Missing second continuation byte
CHECK(encode("\xE0\x80") == u8"\\xE0\\x80");
CHECK(encode("\xE0\xBF") == u8"\\xE0\\xBF");
CHECK(encode("\xE1\x80") == u8"\\xE1\\x80");
CHECK(encode("\xF0\x80") == u8"\\xF0\\x80");
CHECK(encode("\xF4\x80") == u8"\\xF4\\x80");
// Missing third continuation byte
CHECK(encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80");
CHECK(encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80");
}
}
}

View File

@@ -7,6 +7,8 @@
#include "catch.hpp"
#include <cstring>
namespace { namespace CompilationTests {
#ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
@@ -86,6 +88,9 @@ namespace { namespace CompilationTests {
#pragma clang diagnostic pop
#endif
template <typename, typename>
struct Fixture_1245 {};
#endif
TEST_CASE("#809") {
@@ -134,4 +139,19 @@ namespace { namespace CompilationTests {
REQUIRE(t1 >= t2);
}
// unsigned array
TEST_CASE("#1238") {
unsigned char uarr[] = "123";
CAPTURE(uarr);
signed char sarr[] = "456";
CAPTURE(sarr);
REQUIRE(std::memcmp(uarr, "123", sizeof(uarr)) == 0);
REQUIRE(std::memcmp(sarr, "456", sizeof(sarr)) == 0);
}
TEST_CASE_METHOD((Fixture_1245<int, int>), "#1245", "[compilation]") {
SUCCEED();
}
}} // namespace CompilationTests

View File

@@ -32,6 +32,9 @@ namespace { namespace MatchersTests {
return "some completely different text that contains one common word";
}
inline bool alwaysTrue(int) { return true; }
inline bool alwaysFalse(int) { return false; }
#ifdef _MSC_VER
#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
@@ -42,6 +45,10 @@ namespace { namespace MatchersTests {
struct SpecialException : std::exception {
SpecialException(int i_) : i(i_) {}
char const* what() const noexcept override {
return "SpecialException::what";
}
int i;
};
@@ -321,6 +328,11 @@ namespace { namespace MatchersTests {
REQUIRE_THAT(0.f, WithinAbs(-0.f, 0));
REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
REQUIRE_THAT(11.f, !WithinAbs(10.f, 0.5f));
REQUIRE_THAT(10.f, !WithinAbs(11.f, 0.5f));
REQUIRE_THAT(-10.f, WithinAbs(-10.f, 0.5f));
REQUIRE_THAT(-10.f, WithinAbs(-9.6f, 0.5f));
}
SECTION("ULPs") {
REQUIRE_THAT(1.f, WithinULP(1.f, 0));
@@ -358,6 +370,11 @@ namespace { namespace MatchersTests {
REQUIRE_THAT(0., !WithinAbs(1., 0.99));
REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
REQUIRE_THAT(11., !WithinAbs(10., 0.5));
REQUIRE_THAT(10., !WithinAbs(11., 0.5));
REQUIRE_THAT(-10., WithinAbs(-10., 0.5));
REQUIRE_THAT(-10., WithinAbs(-9.6, 0.5));
}
SECTION("ULPs") {
REQUIRE_THAT(1., WithinULP(1., 0));
@@ -386,6 +403,26 @@ namespace { namespace MatchersTests {
}
}
TEST_CASE("Arbitrary predicate matcher", "[matchers][generic]") {
SECTION("Function pointer") {
REQUIRE_THAT(1, Predicate<int>(alwaysTrue, "always true"));
REQUIRE_THAT(1, !Predicate<int>(alwaysFalse, "always false"));
}
SECTION("Lambdas + different type") {
REQUIRE_THAT("Hello olleH",
Predicate<std::string>(
[] (std::string const& str) -> bool { return str.front() == str.back(); },
"First and last character should be equal")
);
REQUIRE_THAT("This wouldn't pass",
!Predicate<std::string>(
[] (std::string const& str) -> bool { return str.front() == str.back(); }
)
);
}
}
} } // namespace MatchersTests
#endif // CATCH_CONFIG_DISABLE_MATCHERS

View File

@@ -304,7 +304,7 @@ TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[to
}
TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
auto const s = const_cast<wchar_t* const>( L"wide load" );
auto const s = const_cast<wchar_t*>( L"wide load" );
std::string result = ::Catch::Detail::stringify( s );
CHECK( result == "\"wide load\"" );
}

View File

@@ -115,3 +115,46 @@ TEST_CASE("Static arrays are convertible to string", "[toString]") {
REQUIRE(Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })");
}
}
struct WhatException : std::exception {
char const* what() const noexcept override {
return "This exception has overriden what() method";
}
~WhatException() override;
};
struct OperatorException : std::exception {
~OperatorException() override;
};
std::ostream& operator<<(std::ostream& out, OperatorException const&) {
out << "OperatorException";
return out;
}
struct StringMakerException : std::exception {
~StringMakerException() override;
};
namespace Catch {
template <>
struct StringMaker<StringMakerException> {
static std::string convert(StringMakerException const&) {
return "StringMakerException";
}
};
}
// Avoid -Wweak-tables
WhatException::~WhatException() = default;
OperatorException::~OperatorException() = default;
StringMakerException::~StringMakerException() = default;
TEST_CASE("Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified", "[toString][exception]") {
REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method");
REQUIRE(::Catch::Detail::stringify(OperatorException{}) == "OperatorException");
REQUIRE(::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException");
}

View File

@@ -20,6 +20,7 @@ struct has_operator { };
struct has_maker {};
struct has_maker_and_operator {};
struct has_neither {};
struct has_template_operator {};
std::ostream& operator<<(std::ostream& os, const has_operator&) {
os << "operator<<( has_operator )";
@@ -31,6 +32,12 @@ std::ostream& operator<<(std::ostream& os, const has_maker_and_operator&) {
return os;
}
template <typename StreamT>
StreamT& operator<<(StreamT& os, const has_template_operator&) {
os << "operator<<( has_template_operator )";
return os;
}
namespace Catch {
template<>
struct StringMaker<has_maker> {
@@ -69,6 +76,12 @@ TEST_CASE("stringify( has_neither )", "[toString]") {
REQUIRE( ::Catch::Detail::stringify(item) == "{ !!! }" );
}
// Call the templated operator
TEST_CASE( "stringify( has_template_operator )", "[toString]" ) {
has_template_operator item;
REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" );
}
// Vectors...

View File

@@ -2,6 +2,7 @@
from __future__ import print_function
import io
import os
import sys
import subprocess
@@ -11,6 +12,10 @@ import difflib
import scriptCommon
from scriptCommon import catchPath
if os.name == 'nt':
# Enable console colours on windows
os.system('')
rootPath = os.path.join(catchPath, 'projects/SelfTest/Baselines')
@@ -72,10 +77,11 @@ else:
overallResult = 0
def diffFiles(fileA, fileB):
with open(fileA, 'r') as file:
with io.open(fileA, 'r', encoding='utf-8', errors='surrogateescape') as file:
aLines = [line.rstrip() for line in file.readlines()]
with open(fileB, 'r') as file:
with io.open(fileB, 'r', encoding='utf-8', errors='surrogateescape') as file:
bLines = [line.rstrip() for line in file.readlines()]
shortenedFilenameA = fileA.rsplit(os.sep, 1)[-1]
@@ -85,7 +91,7 @@ def diffFiles(fileA, fileB):
return [line for line in diff if line[0] in ('+', '-')]
def filterLine(line):
def filterLine(line, isCompact):
if catchPath in line:
# make paths relative to Catch root
line = line.replace(catchPath + os.sep, '')
@@ -103,6 +109,10 @@ def filterLine(line):
else:
line = lineNumberParser.sub(" ", line)
if isCompact:
line = line.replace(': FAILED', ': failed')
line = line.replace(': PASSED', ': passed')
# strip Catch version number
line = versionParser.sub("<version>", line)
@@ -139,10 +149,10 @@ def approve(baseName, args):
subprocess.call(args, stdout=f, stderr=f)
f.close()
rawFile = open(rawResultsPath, 'r')
filteredFile = open(filteredResultsPath, 'w')
rawFile = io.open(rawResultsPath, 'r', encoding='utf-8', errors='surrogateescape')
filteredFile = io.open(filteredResultsPath, 'w', encoding='utf-8', errors='surrogateescape')
for line in rawFile:
filteredFile.write(filterLine(line).rstrip() + "\n")
filteredFile.write(filterLine(line, 'compact' in baseName).rstrip() + "\n")
filteredFile.close()
rawFile.close()

View File

@@ -11,23 +11,23 @@ from scriptCommon import catchPath
rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' )
if len(sys.argv) > 1:
files = [os.path.join( rootPath, f ) for f in sys.argv[1:]]
files = [os.path.join( rootPath, f ) for f in sys.argv[1:]]
else:
files = glob.glob( os.path.join( rootPath, "*.unapproved.txt" ) )
files = glob.glob( os.path.join( rootPath, "*.unapproved.txt" ) )
def approveFile( approvedFile, unapprovedFile ):
justFilename = unapprovedFile[len(rootPath)+1:]
if os.path.exists( unapprovedFile ):
if os.path.exists( approvedFile ):
os.remove( approvedFile )
os.rename( unapprovedFile, approvedFile )
print( "approved " + justFilename )
else:
print( "approval file " + justFilename + " does not exist" )
justFilename = unapprovedFile[len(rootPath)+1:]
if os.path.exists( unapprovedFile ):
if os.path.exists( approvedFile ):
os.remove( approvedFile )
os.rename( unapprovedFile, approvedFile )
print( "approved " + justFilename )
else:
print( "approval file " + justFilename + " does not exist" )
if len(files) > 0:
for unapprovedFile in files:
approveFile( unapprovedFile.replace( "unapproved.txt", "approved.txt" ), unapprovedFile )
if files:
for unapprovedFile in files:
approveFile( unapprovedFile.replace( "unapproved.txt", "approved.txt" ), unapprovedFile )
else:
print( "no files to approve" )
print( "no files to approve" )

View File

@@ -25,7 +25,7 @@ class LineMapper:
# TBD:
# #if, #ifdef, comments after #else
def mapLine( self, lineNo, line ):
for idFrom, idTo in self.idMap.iteritems():
for idFrom, idTo in self.idMap.items():
r = re.compile("(.*)" + idFrom + "(.*)")
m = r.match( line )
@@ -38,7 +38,7 @@ class LineMapper:
# print("[{0}] originalNs: '{1}' - closing".format(lineNo, originalNs))
# print( " " + line )
# print( " 1:[{0}]\n 2:[{1}]\n 3:[{2}]\n 4:[{3}]\n 5:[{4}]".format( m.group(1), m.group(2), m.group(3), m.group(4), m.group(5) ) )
if self.outerNamespace.has_key(originalNs):
if originalNs in self.outerNamespace:
outerNs, innerNs = self.outerNamespace[originalNs]
return "{0}}}{1}{2}::{3}{4}{5}\n".format( m.group(1), m.group(2), outerNs, innerNs, m.group(4), m.group(5))
m = nsRe.match( line )
@@ -47,7 +47,7 @@ class LineMapper:
# print("[{0}] originalNs: '{1}'".format(lineNo, originalNs))
# print( " " + line )
# print( " 1:[{0}]\n 2:[{1}]\n 3:[{2}]\n 4:[{3}]".format( m.group(1), m.group(2), m.group(3), m.group(4) ) )
if self.outerNamespace.has_key(originalNs):
if originalNs in self.outerNamespace:
outerNs, innerNs = self.outerNamespace[originalNs]
return "{0}{1} {{ namespace {2}{3}{4}\n".format( m.group(1), outerNs, innerNs, m.group(3), m.group(4) )

View File

@@ -4,19 +4,20 @@ from __future__ import print_function
import os
from scriptCommon import catchPath
changedFiles = 0
def isSourceFile( path ):
return path.endswith( ".cpp" ) or path.endswith( ".h" ) or path.endswith( ".hpp" )
def fixAllFilesInDir( dir ):
changedFiles = 0
for f in os.listdir( dir ):
path = os.path.join( dir,f )
if os.path.isfile( path ):
if isSourceFile( path ):
fixFile( path )
if fixFile( path ):
changedFiles += 1
else:
fixAllFilesInDir( path )
return changedFiles
def fixFile( path ):
f = open( path, 'r' )
@@ -41,8 +42,10 @@ def fixFile( path ):
f2.write( line )
f2.close()
os.remove( altPath )
return True
return False
fixAllFilesInDir(catchPath)
changedFiles = fixAllFilesInDir(catchPath)
if changedFiles > 0:
print( "Fixed " + str(changedFiles) + " file(s)" )
else:

View File

@@ -7,7 +7,6 @@ import io
import sys
import re
import datetime
import string
from glob import glob
from scriptCommon import catchPath
@@ -34,7 +33,7 @@ def generate(v):
}
for arg in sys.argv[1:]:
arg = string.lower(arg)
arg = arg.lower()
if arg == "noimpl":
globals['includeImpl'] = False
print( "Not including impl code" )
@@ -51,7 +50,7 @@ def generate(v):
def write( line ):
if globals['includeImpl'] or globals['implIfDefs'] == -1:
out.write( line.decode('utf-8') )
out.write( line )
def insertCpps():
dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']]
@@ -65,9 +64,9 @@ def generate(v):
parseFile(dir, name)
def parseFile( path, filename ):
f = open( os.path.join(path, filename), 'r' )
f = io.open( os.path.join(path, filename), 'r', encoding='utf-8' )
blanks = 0
write( "// start {0}\n".format( filename ) )
write( u"// start {0}\n".format( filename ) )
for line in f:
if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line:
insertCpps()
@@ -82,7 +81,7 @@ def generate(v):
if m:
header = m.group(1)
headerPath, sep, headerFile = header.rpartition( "/" )
if not headerFile in seenHeaders:
if headerFile not in seenHeaders:
if headerFile != "tbc_text_format.h" and headerFile != "clara.h":
seenHeaders.add( headerFile )
if headerPath == "internal" and path.endswith("internal/"):
@@ -102,25 +101,25 @@ def generate(v):
blanks = 0
if blanks < 2 and not defineParser.match(line):
write( line.rstrip() + "\n" )
write( '// end {}\n'.format(filename) )
write( u'// end {}\n'.format(filename) )
write( "/*\n" )
write( " * Catch v{0}\n".format( v.getVersionString() ) )
write( " * Generated: {0}\n".format( datetime.datetime.now() ) )
write( " * ----------------------------------------------------------\n" )
write( " * This file has been merged from multiple headers. Please don't edit it directly\n" )
write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) )
write( " *\n" )
write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
write( " */\n" )
write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
write( u"/*\n" )
write( u" * Catch v{0}\n".format( v.getVersionString() ) )
write( u" * Generated: {0}\n".format( datetime.datetime.now() ) )
write( u" * ----------------------------------------------------------\n" )
write( u" * This file has been merged from multiple headers. Please don't edit it directly\n" )
write( u" * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) )
write( u" *\n" )
write( u" * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
write( u" * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
write( u" */\n" )
write( u"#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
write( u"#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
parseFile( rootPath, 'catch.hpp' )
write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
write( u"#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
out.close()
print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import re
import urllib2
@@ -41,7 +43,6 @@ for line in lines:
pass
elif line.startswith( "Date:"):
dates.append( line[5:].lstrip() )
pass
elif line == "" and prevLine == "":
pass
else:
@@ -58,7 +59,7 @@ for line in lines:
else:
messages.append( line2 )
print "All changes between {0} and {1}:\n".format( dates[-1], dates[0] )
print("All changes between {0} and {1}:\n".format( dates[-1], dates[0] ))
for line in messages:
print line
print(line)

View File

@@ -15,7 +15,7 @@ def runAndCapture( args ):
line = ""
while True:
out = child.stdout.read(1)
if out == '' and child.poll() != None:
if out == '' and child.poll():
break
if out != '':
if out == '\n':

View File

@@ -12,7 +12,6 @@
#
from __future__ import print_function
from scriptCommon import catchPath
import argparse
import glob
@@ -20,6 +19,8 @@ import os
import re
import sys
from scriptCommon import catchPath
# Configuration:
minTocEntries = 4
@@ -431,7 +432,7 @@ def updateDocumentToCMain():
args = parser.parse_args()
paths = args.Input if len(args.Input) > 0 else [documentsDefault]
paths = args.Input if args.Input else [documentsDefault]
changedFiles = updateDocumentToC(paths=paths, min_toc_len=args.minTocEntries, verbose=args.verbose)

View File

@@ -31,7 +31,6 @@ def get_hash(path):
def update_control(path):
v = Version()
ver_string = v.getVersionString()
# Update control
lines = []
@@ -48,7 +47,6 @@ def update_control(path):
def update_portfile(path, header_hash, licence_hash):
print('Updating portfile')
v = Version()
ver_string = v.getVersionString()
# Update portfile
lines = []

View File

@@ -41,7 +41,7 @@ def uploadFiles():
'save': True
})
if 'status' in response and not 'compiler_error' in response:
if 'status' in response and 'compiler_error' not in response:
return True, response['url']
else:
return False, response

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ class CatchConanTest(ConanFile):
settings = "os", "compiler", "arch", "build_type"
username = getenv("CONAN_USERNAME", "philsquared")
channel = getenv("CONAN_CHANNEL", "testing")
requires = "Catch/2.2.1@%s/%s" % (username, channel)
requires = "Catch/2.2.3@%s/%s" % (username, channel)
def build(self):
cmake = CMake(self)