Compare commits

...

16 Commits

Author SHA1 Message Date
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
Martin Hořeňovský
0a34cc201e v2.2.1 2018-03-11 12:04:28 +01:00
Martin Hořeňovský
11c89a5f7d Bring in Clara v1.1.4
This fixes #1214
2018-03-09 10:37:56 +01:00
Martin Hořeňovský
dc3e7f9cf7 Fix incorrectly clamped return value
Fixes #1215
2018-03-09 10:00:55 +01:00
34 changed files with 1716 additions and 127 deletions

View File

@@ -232,27 +232,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.0)
project(Catch2 LANGUAGES CXX VERSION 2.2.2)
include(GNUInstallDirs)
@@ -152,6 +152,7 @@ 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
@@ -221,6 +222,7 @@ 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_registry_hub.cpp

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/vOtfjd7LKmcj4JqD)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/fRDMfYjUnrbOFwLn)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.2.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.2.2/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

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

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

@@ -1,5 +1,39 @@
<a id="top"></a>
# 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
* Fixed compilation error when compiling Catch2 with `std=c++17` against libc++ (#1214)
* Clara (Catch2's CLI parsing library) used `std::optional` without including it explicitly
* Fixed Catch2 return code always being 0 (#1215)
* In the words of STL, "We feel superbad about letting this in"
# 2.2.0
## Fixes

View File

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

View File

@@ -5,7 +5,7 @@
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.3
// Clara v1.1.4
#ifndef CATCH_CLARA_HPP_INCLUDED
#define CATCH_CLARA_HPP_INCLUDED
@@ -21,6 +21,7 @@
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#include <optional>
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
#endif
#endif
@@ -665,11 +666,11 @@ namespace detail {
}
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
template<typename T>
inline auto convertInto( std::string const &source, std::optional<T>& target ) -> ParserResult {
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
T temp;
auto result = convertInto( source, temp );
if( result )
target = temp;
target = std::move(temp);
return result;
}
#endif // CLARA_CONFIG_OPTIONAL_TYPE

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

@@ -88,7 +88,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 {

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

@@ -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

@@ -277,7 +277,7 @@ namespace Catch {
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
return (std::min)( { MaxExitCode, totals.error, static_cast<int>( totals.assertions.failed ) } );
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;

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

@@ -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

@@ -75,6 +75,19 @@ namespace Catch {
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
@@ -112,6 +125,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 +155,7 @@ namespace Catch {
struct StringMaker<char *> {
static std::string convert(char * str);
};
#ifdef CATCH_CONFIG_WCHAR
template<>
struct StringMaker<wchar_t const *> {
@@ -146,22 +167,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 +268,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 +406,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, 0, "", 0 );
static Version version( 2, 2, 2, "", 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

@@ -10,6 +10,8 @@ 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"'
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 +99,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
@@ -235,6 +241,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 +265,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
@@ -897,6 +911,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 }"

View File

@@ -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: 205 | 152 passed | 49 failed | 4 failed as expected
assertions: 1063 | 935 passed | 107 failed | 21 failed as expected

View File

@@ -102,6 +102,30 @@ 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"
-------------------------------------------------------------------------------
#748 - captures with unexpected exceptions
outside assertions
@@ -814,6 +838,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
-------------------------------------------------------------------------------
@@ -1858,6 +1920,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 +2084,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
@@ -7064,6 +7174,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
-------------------------------------------------------------------------------
@@ -8550,6 +8959,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: 205 | 139 passed | 62 failed | 4 failed as expected
assertions: 1077 | 935 passed | 121 failed | 21 failed as expected

View File

@@ -102,6 +102,30 @@ 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"
-------------------------------------------------------------------------------
#748 - captures with unexpected exceptions
outside assertions
@@ -308,6 +332,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: 13 | 10 passed | 1 failed | 2 failed as expected
assertions: 37 | 30 passed | 4 failed | 3 failed as expected

View File

@@ -1,12 +1,13 @@
<?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="1078" 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>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
<error type="TEST_CASE">
expected exception
@@ -110,6 +111,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}"/>
@@ -706,6 +709,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}"/>

View File

@@ -96,6 +96,37 @@
<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="#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 +901,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>
@@ -2108,7 +2180,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 +2387,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" >
@@ -7817,7 +7953,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 +8066,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>
@@ -9405,7 +9913,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="879" failures="122" expectedFailures="21"/>
<OverallResults successes="935" failures="122" expectedFailures="21"/>
</Group>
<OverallResults successes="879" failures="121" expectedFailures="21"/>
<OverallResults successes="935" failures="121" expectedFailures="21"/>
</Catch>

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
@@ -134,4 +136,15 @@ 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);
}
}} // 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
@@ -321,6 +324,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 +366,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 +399,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

@@ -1,6 +1,6 @@
/*
* Catch v2.2.0
* Generated: 2018-03-07 10:56:32.217228
* Catch v2.2.2
* Generated: 2018-04-06 12:05:03.186665
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 2
#define CATCH_VERSION_PATCH 0
#define CATCH_VERSION_PATCH 2
#ifdef __clang__
# pragma clang system_header
@@ -37,9 +37,9 @@
# 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
// end catch_suppress_warnings.h
@@ -783,6 +783,18 @@ namespace Catch {
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
// If we decide for C++14, change these to enable_if_ts
@@ -819,6 +831,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
@@ -842,6 +861,7 @@ namespace Catch {
struct StringMaker<char *> {
static std::string convert(char * str);
};
#ifdef CATCH_CONFIG_WCHAR
template<>
struct StringMaker<wchar_t const *> {
@@ -853,22 +873,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) });
}
};
@@ -952,6 +974,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) {
@@ -1080,6 +1111,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 ) );
@@ -2357,6 +2395,54 @@ namespace Matchers {
} // namespace Catch
// end catch_matchers_floating.h
// start catch_matchers_generic.hpp
#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
// end catch_matchers_generic.hpp
// start catch_matchers_string.h
#include <string>
@@ -4830,7 +4916,7 @@ namespace Catch {
public:
// !TBD We need to do this another way!
bool aborting() const override;
bool aborting() const final;
private:
@@ -5134,7 +5220,7 @@ namespace Catch {
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.3
// Clara v1.1.4
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
@@ -5148,6 +5234,7 @@ namespace Catch {
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#include <optional>
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
#endif
#endif
@@ -5784,11 +5871,11 @@ namespace detail {
}
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
template<typename T>
inline auto convertInto( std::string const &source, std::optional<T>& target ) -> ParserResult {
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
T temp;
auto result = convertInto( source, temp );
if( result )
target = temp;
target = std::move(temp);
return result;
}
#endif // CLARA_CONFIG_OPTIONAL_TYPE
@@ -7879,7 +7966,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 {
@@ -7926,6 +8013,16 @@ Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
} // namespace Catch
// end catch_matchers_floating.cpp
// start catch_matchers_generic.cpp
std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
if (desc.empty()) {
return "matches undescribed predicate";
} else {
return "matches predicate: \"" + desc + '"';
}
}
// end catch_matchers_generic.cpp
// start catch_matchers_string.cpp
#include <regex>
@@ -9237,7 +9334,7 @@ namespace Catch {
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
return (std::min)( { MaxExitCode, totals.error, static_cast<int>( totals.assertions.failed ) } );
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;
@@ -10424,6 +10521,8 @@ namespace Catch {
#include <chrono>
static const uint64_t nanosecondsInSecond = 1000000000;
namespace Catch {
auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
@@ -10434,17 +10533,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
@@ -10806,7 +10913,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 2, 0, "", 0 );
static Version version( 2, 2, 2, "", 0 );
return version;
}
@@ -10857,49 +10964,141 @@ namespace Catch {
#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

@@ -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.0@%s/%s" % (username, channel)
requires = "Catch/2.2.2@%s/%s" % (username, channel)
def build(self):
cmake = CMake(self)

View File

@@ -5,7 +5,7 @@
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.3
// Clara v1.1.4
#ifndef CLARA_HPP_INCLUDED
#define CLARA_HPP_INCLUDED
@@ -21,6 +21,7 @@
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#include <optional>
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
#endif
#endif
@@ -665,11 +666,11 @@ namespace detail {
}
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
template<typename T>
inline auto convertInto( std::string const &source, std::optional<T>& target ) -> ParserResult {
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
T temp;
auto result = convertInto( source, temp );
if( result )
target = temp;
target = std::move(temp);
return result;
}
#endif // CLARA_CONFIG_OPTIONAL_TYPE