1
0
mirror of https://github.com/catchorg/Catch2.git synced 2025-01-15 22:58:02 +00:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Martin Hořeňovský
b2a6523d85
Fix Clang-3.8 compilation of tests
As far as I know, the compilation error is a compiler bug, but I
do not want to just drop the support for something that is trivial
to work around.
2020-02-13 16:57:37 +01:00
Martin Hořeňovský
b009d190bf
Avoid detecting Clang as having MSVC's traditional preprocessor
Fixes #1806
2020-02-13 16:28:30 +01:00
ptc-tgamper
ac83087bc2
catch_debugger.h - implement break into debugger assembler instructions for iOS 2020-02-13 16:28:02 +01:00
ptc-tgamper
123b449f8d
catch_console_colour.cpp - adjust useColourOnPlatform for iOS 2020-02-13 16:27:56 +01:00
ptc-tgamper
6ad743a62b
catch_debugger.cpp - debugger detection is identical on Mac OS X and iOS 2020-02-13 16:27:46 +01:00
Martin Hořeňovský
0f47fe16bd
Provide const overload of ObjectStorage::stored_object()
Fixes #1820
2020-02-13 16:26:06 +01:00
Joe Burzinski
82baef62e2
Fix forwarding in SingleValueGenerator and generator creation
Fixes #1809
2020-02-13 16:19:50 +01:00
Joe Burzinski
0fbf4f3e15
Fix wrong namespacing of benchmarking constructor helpers 2020-02-13 16:15:50 +01:00
Martin Hořeňovský
ad3f50bbc1
Suppress using-namespace lint in GENERATE* macros
Closes #1799
2020-02-13 15:31:09 +01:00
Martin Hořeňovský
13e01d273a
Cherry pick v2.11.0 release notes and docs 2020-02-13 15:30:46 +01:00
Martin Hořeňovský
2788897051
Minor cleanup in the benchmarking tests 2020-02-13 15:12:57 +01:00
Martin Hořeňovský
2945b80f61
Add more constexpr to StringRef 2020-02-13 15:01:03 +01:00
Martin Hořeňovský
63b7d6f98e
Improve erasure of test numbers in TAP approvals 2020-02-13 14:22:18 +01:00
Martin Hořeňovský
c50ba09cde
Split [.foo] into [.][foo] when parsing test specs
b77cec05c0 fixed this problem for tagging tests, so that a test
case tagged with `[.foo]` would be parsed as tagged with `[.][foo]`.
This does the same for the test spec parsing.

Fixes #1798
2020-02-13 13:35:10 +01:00
Martin Hořeňovský
c165bd15c5
Forbid copying ReusableStringStream
Copying a `ReusableStringStream` would lead to "double free" of
the stream, and thus it could be used in multiple places at the
same time, breaking the output.
2020-02-12 19:21:15 +01:00
cericks0n
4f0de7bbad
Fix error when period of steady_clock is not nano
On systems where std::chrono::steady_clock::period is not std::nano, benchmark tests fail to compile due to trying to convert analysis.samples from a vector of duration<double, clock::period> to a vector of std::chrono::duration<double, std::nano>.
2020-02-12 19:20:41 +01:00
Martin Hořeňovský
21b24e8326
Remove catch_external_interfaces.h
Its intent was to show which headers are expected to be useable by
Catch2's users, and to enforce their inclusion in the single header
distribution at the right place.

Given the new library model, the second use case is not needed and
the first one is better served with documentation and physical file
layout.
2020-02-12 16:57:15 +01:00
31 changed files with 501 additions and 180 deletions

View File

@ -164,7 +164,7 @@ Note that it is not possible to simply use the same instance for different runs
and resetting it between each run since that would pollute the measurements with
the resetting code.
It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get
It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get
the same semantics as providing a callable to `meter.measure` with `int` argument:
```c++
@ -185,19 +185,17 @@ construct and destroy objects without dynamic allocation and in a way that lets
you measure construction and destruction separately.
```c++
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter)
{
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); });
})
};
BENCHMARK_ADVANCED("destroy", [](Catch::Benchmark::Chronometer meter)
{
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
for(auto&& o : storage)
o.construct("thing");
meter.measure([&](int i) { storage[i].destruct(); });
})
};
```
`Catch::Benchmark::storage_for<T>` objects are just pieces of raw storage suitable for `T`

View File

@ -78,7 +78,7 @@ type, making their usage much nicer. These are
> `from_range` has been introduced in Catch 2.10.0
> `range()` for floating point numbers has been introduced in Catch X.Y.Z
> `range()` for floating point numbers has been introduced in Catch 2.11.0
And can be used as shown in the example below to create a generator
that returns 100 odd random number:

View File

@ -2,6 +2,7 @@
# Release notes
**Contents**<br>
[2.11.0](#2110)<br>
[2.10.2](#2102)<br>
[2.10.1](#2101)<br>
[2.10.0](#2100)<br>
@ -62,6 +63,23 @@
* `CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER` no longer exists.
* `StringMaker` specializations for <chrono> are always provided
## 2.11.0
### Improvements
* JUnit reporter output now contains more details in case of failure (#1347, #1719)
* Added SonarQube Test Data reporter (#1738)
* It is in a separate header, just like the TAP, Automake, and TeamCity reporters
* `range` generator now allows floating point numbers (#1776)
* Reworked part of internals to increase throughput
### Fixes
* The single header version should contain full benchmarking support (#1800)
* `[.foo]` is now properly parsed as `[.][foo]` when used on the command line (#1798)
* Fixed compilation of benchmarking on platforms where `steady_clock::period` is not `std::nano` (#1794)
## 2.10.2
### Improvements

View File

@ -55,7 +55,6 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/catch_enum_values_registry.h
${SOURCES_DIR}/catch_errno_guard.h
${SOURCES_DIR}/catch_exception_translator_registry.h
${SOURCES_DIR}/catch_external_interfaces.h
${SOURCES_DIR}/catch_fatal_condition.h
${SOURCES_DIR}/catch_generators.hpp
${SOURCES_DIR}/catch_generators_generic.hpp

View File

@ -79,7 +79,7 @@ namespace Catch {
});
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
BenchmarkStats<std::chrono::duration<double, std::nano>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
getResultCapture().benchmarkEnded(stats);
} CATCH_CATCH_ALL{

View File

@ -14,60 +14,66 @@
#include <type_traits>
namespace Catch {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other)
namespace Benchmark {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
new(&data) T(other.stored_object());
}
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
ObjectStorage() : data() {}
~ObjectStorage() { destruct_on_exit<T>(); }
ObjectStorage(const ObjectStorage& other)
{
new(&data) T(other.stored_object());
}
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
~ObjectStorage() { destruct_on_exit<T>(); }
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
T& stored_object()
{
return *static_cast<T*>(static_cast<void*>(&data));
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
TStorage data;
};
}
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
T& stored_object() {
return *static_cast<T*>(static_cast<void*>(&data));
}
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
}
T const& stored_object() const {
return *static_cast<T*>(static_cast<void*>(&data));
}
TStorage data;
};
} // namespace Detail
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
} // namespace Benchmark
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED

View File

@ -40,8 +40,6 @@
#include <catch2/catch_objc.hpp>
#endif
#include <catch2/catch_external_interfaces.h>
#endif // ! CATCH_CONFIG_IMPL_ONLY
#if !defined(CATCH_CONFIG_IMPL_ONLY)

View File

@ -149,9 +149,12 @@
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif
# if !defined(__clang__) // Handle Clang masquerading for msvc
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif // MSVC_TRADITIONAL
# endif // __clang__
#endif // _MSC_VER
#if defined(_REENTRANT) || defined(_MSC_VER)

View File

@ -167,7 +167,7 @@ namespace {
bool useColourOnPlatform() {
return
#ifdef CATCH_PLATFORM_MAC
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
!isDebuggerActive() &&
#endif
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))

View File

@ -12,7 +12,7 @@
#include <catch2/catch_stream.h>
#include <catch2/catch_platform.h>
#ifdef CATCH_PLATFORM_MAC
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
# include <assert.h>
# include <stdbool.h>

View File

@ -19,6 +19,17 @@ namespace Catch {
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(CATCH_PLATFORM_IPHONE)
// use inline assembler
#if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3")
#elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000")
#elif defined(__arm__)
#define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
#endif
#elif defined(CATCH_PLATFORM_LINUX)
// If we can use inline assembler, do it because this allows us to break
// directly at the location of the failing check instead of breaking inside

View File

@ -1,20 +0,0 @@
/*
* Created by Martin on 17/08/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_EXTERNAL_INTERFACES_H_INCLUDED
#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED
#include <catch2/reporters/catch_reporter_bases.hpp>
#include <catch2/catch_console_colour.h>
#include <catch2/catch_reporter_registrars.hpp>
// Allow users to base their work off existing reporters
#include <catch2/reporters/catch_reporter_compact.h>
#include <catch2/reporters/catch_reporter_console.h>
#include <catch2/reporters/catch_reporter_junit.h>
#include <catch2/reporters/catch_reporter_xml.h>
#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED

View File

@ -49,7 +49,6 @@ namespace Generators {
class SingleValueGenerator final : public IGenerator<T> {
T m_value;
public:
SingleValueGenerator(T const& value) : m_value( value ) {}
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
T const& get() const override {
@ -112,21 +111,21 @@ namespace Generators {
m_generators.emplace_back(std::move(generator));
}
void populate(T&& val) {
m_generators.emplace_back(value(std::move(val)));
m_generators.emplace_back(value(std::forward<T>(val)));
}
template<typename U>
void populate(U&& val) {
populate(T(std::move(val)));
populate(T(std::forward<U>(val)));
}
template<typename U, typename... Gs>
void populate(U&& valueOrGenerator, Gs... moreGenerators) {
void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
populate(std::forward<U>(valueOrGenerator));
populate(std::forward<Gs>(moreGenerators)...);
}
public:
template <typename... Gs>
Generators(Gs... moreGenerators) {
Generators(Gs &&... moreGenerators) {
m_generators.reserve(sizeof...(Gs));
populate(std::forward<Gs>(moreGenerators)...);
}
@ -158,7 +157,7 @@ namespace Generators {
struct as {};
template<typename T, typename... Gs>
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
}
template<typename T>
@ -166,11 +165,11 @@ namespace Generators {
return Generators<T>(std::move(generator));
}
template<typename T, typename... Gs>
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
}
template<typename T, typename U, typename... Gs>
auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
}
@ -196,10 +195,10 @@ namespace Generators {
} // namespace Catch
#define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_COPY( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_REF( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED

View File

@ -9,6 +9,8 @@
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#include "catch_common.h"
#include <iosfwd>
#include <cstddef>
#include <ostream>
@ -28,7 +30,7 @@ namespace Catch {
auto makeStream( StringRef const &filename ) -> IStream const*;
class ReusableStringStream {
class ReusableStringStream : NonCopyable {
std::size_t m_index;
std::ostream* m_oss;
public:

View File

@ -22,17 +22,7 @@ namespace Catch {
CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance");
return m_start;
}
auto StringRef::data() const noexcept -> char const* {
return m_start;
}
auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
if (start < m_size) {
return StringRef(m_start + start, (std::min)(m_size - start, size));
} else {
return StringRef();
}
}
auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
return m_size == other.m_size
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);

View File

@ -74,12 +74,21 @@ namespace Catch {
public: // substrings and searches
// Returns a substring of [start, start + length).
// If start + length > size(), then the substring is [start, size()).
// If start + length > size(), then the substring is [start, start + size()).
// If start > size(), then the substring is empty.
auto substr( size_type start, size_type length ) const noexcept -> StringRef;
constexpr StringRef substr(size_type start, size_type length) const noexcept {
if (start < m_size) {
const auto shortened_size = m_size - start;
return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length);
} else {
return StringRef();
}
}
// Returns the current start pointer. May not be null-terminated.
auto data() const noexcept -> char const*;
constexpr char const* data() const noexcept {
return m_start;
}
constexpr auto isNullTerminated() const noexcept -> bool {
return m_start[m_size] == '\0';

View File

@ -113,9 +113,9 @@ namespace Catch {
switch( m_mode ) {
case Name:
case QuotedName:
return addPattern<TestSpec::NamePattern>();
return addNamePattern();
case Tag:
return addPattern<TestSpec::TagPattern>();
return addTagPattern();
case EscapedName:
revertBackToLastMode();
return;
@ -175,6 +175,63 @@ namespace Catch {
return true; //success
}
std::string TestSpecParser::preprocessPattern() {
std::string token = m_patternName;
for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
m_escapeChars.clear();
if (startsWith(token, "exclude:")) {
m_exclusion = true;
token = token.substr(8);
}
m_patternName.clear();
return token;
}
void TestSpecParser::addNamePattern() {
auto token = preprocessPattern();
if (!token.empty()) {
if (m_exclusion) {
m_currentFilter.m_forbidden.emplace_back(std::make_unique<TestSpec::NamePattern>(token, m_substring));
} else {
m_currentFilter.m_required.emplace_back(std::make_unique<TestSpec::NamePattern>(token, m_substring));
}
}
m_substring.clear();
m_exclusion = false;
m_mode = None;
}
void TestSpecParser::addTagPattern() {
auto token = preprocessPattern();
if (!token.empty()) {
// If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
// we have to create a separate hide tag and shorten the real one
if (token.size() > 1 && token[0] == '.') {
token.erase(token.begin());
if (m_exclusion) {
m_currentFilter.m_forbidden.emplace_back(std::make_unique<TestSpec::TagPattern>(".", m_substring));
m_currentFilter.m_forbidden.emplace_back(std::make_unique<TestSpec::TagPattern>(token, m_substring));
} else {
m_currentFilter.m_required.emplace_back(std::make_unique<TestSpec::TagPattern>(".", m_substring));
m_currentFilter.m_required.emplace_back(std::make_unique<TestSpec::TagPattern>(token, m_substring));
}
}
if (m_exclusion) {
m_currentFilter.m_forbidden.emplace_back(std::make_unique<TestSpec::TagPattern>(token, m_substring));
} else {
m_currentFilter.m_required.emplace_back(std::make_unique<TestSpec::TagPattern>(token, m_substring));
}
}
m_substring.clear();
m_exclusion = false;
m_mode = None;
}
TestSpec parseTestSpec( std::string const& arg ) {
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
}

View File

@ -54,28 +54,12 @@ namespace Catch {
void addFilter();
bool separate();
template<typename T>
void addPattern() {
std::string token = m_patternName;
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
token = token.substr( 8 );
}
if( !token.empty() ) {
if (m_exclusion) {
m_currentFilter.m_forbidden.emplace_back(std::make_unique<T>(token, m_substring));
} else {
m_currentFilter.m_required.emplace_back(std::make_unique<T>(token, m_substring));
}
}
m_substring.clear();
m_patternName.clear();
m_exclusion = false;
m_mode = None;
}
// Handles common preprocessing of the pattern for name/tag patterns
std::string preprocessPattern();
// Adds the current pattern as a test name
void addNamePattern();
// Adds the current pattern as a tag
void addTagPattern();
inline void addCharToPattern(char c) {
m_substring += c;

View File

@ -28,14 +28,6 @@ TEST_CASE("Benchmark factorial", "[benchmark]") {
BENCHMARK("factorial 14") {
return factorial(14);
};
//
// BENCHMARK("factorial 20") {
// return factorial(20);
// };
//
// BENCHMARK("factorial 35") {
// return factorial(35);
// };
}
TEST_CASE("Benchmark containers", "[.][benchmark]") {

View File

@ -1028,6 +1028,12 @@ CmdLine.tests.cpp:<line number>: passed: spec.matches( *fakeTestCase( " aardvar
CmdLine.tests.cpp:<line number>: passed: spec.matches( *fakeTestCase( " aardvark " ) ) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches( *fakeTestCase( "aardvark " ) ) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches( *fakeTestCase( "aardvark" ) ) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")) for: true
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("hidden and foo", "[.][foo]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true
Condition.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
Condition.tests.cpp:<line number>: passed: p == pNULL for: 0 == 0
Condition.tests.cpp:<line number>: passed: p != 0 for: 0x<hex digits> != 0
@ -1187,6 +1193,7 @@ String.tests.cpp:<line number>: passed: s.data() == s2.data() for: "hello world!
String.tests.cpp:<line number>: passed: s.data() == ss.data() for: "hello world!" == "hello world!"
String.tests.cpp:<line number>: passed: s.substr(s.size() + 1, 123).empty() for: true
String.tests.cpp:<line number>: passed: std::strcmp(ss.c_str(), "world!") == 0 for: 0 == 0
String.tests.cpp:<line number>: passed: s.substr(1'000'000, 1).empty() for: true
String.tests.cpp:<line number>: passed: (char*)buffer1 != (char*)buffer2 for: "Hello" != "Hello"
String.tests.cpp:<line number>: passed: left == right for: Hello == Hello
String.tests.cpp:<line number>: passed: left != left.substr(0, 3) for: Hello != Hel
@ -1200,11 +1207,20 @@ String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringre
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{}.size() == 0'
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{ "abc", 3 }.size() == 3'
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{ "abc", 3 }.isNullTerminated()'
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{ "abc", 2 }.size() == 2'
String.tests.cpp:<line number>: passed: with 1 message: '!(StringRef{ "abc", 2 }.isNullTerminated())'
String.tests.cpp:<line number>: passed: with 1 message: 'empty.size() == 0'
String.tests.cpp:<line number>: passed: with 1 message: 'empty.begin() == empty.end()'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.size() == 3'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.isNullTerminated()'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.data() == abc'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.begin() == abc'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.begin() != stringref.end()'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.substr(10, 0).empty()'
String.tests.cpp:<line number>: passed: with 1 message: 'stringref.substr(2, 1).data() == abc + 2'
String.tests.cpp:<line number>: passed: with 1 message: 'shortened.size() == 2'
String.tests.cpp:<line number>: passed: with 1 message: 'shortened.data() == abc'
String.tests.cpp:<line number>: passed: with 1 message: 'shortened.begin() != shortened.end()'
String.tests.cpp:<line number>: passed: with 1 message: '!(shortened.isNullTerminated())'
String.tests.cpp:<line number>: passed: with 1 message: '!(shortened.substr(1, 3).isNullTerminated())'
String.tests.cpp:<line number>: passed: with 1 message: '!(sr1.empty())'
String.tests.cpp:<line number>: passed: with 1 message: 'sr1.size() == 3'
String.tests.cpp:<line number>: passed: with 1 message: 'sr1.isNullTerminated()'

View File

@ -1381,5 +1381,5 @@ due to unexpected exception with message:
===============================================================================
test cases: 320 | 246 passed | 70 failed | 4 failed as expected
assertions: 1776 | 1624 passed | 131 failed | 21 failed as expected
assertions: 1792 | 1640 passed | 131 failed | 21 failed as expected

View File

@ -7370,6 +7370,50 @@ CmdLine.tests.cpp:<line number>: PASSED:
with expansion:
true
-------------------------------------------------------------------------------
Parse test names and tags
Shortened hide tags are split apart when parsing
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
CHECK( spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
CHECK_FALSE( spec.matches(*fakeTestCase("only foo", "[foo]")) )
with expansion:
!false
-------------------------------------------------------------------------------
Parse test names and tags
Shortened hide tags also properly handle exclusion
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
CHECK_FALSE( spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")) )
with expansion:
!false
CmdLine.tests.cpp:<line number>: PASSED:
CHECK_FALSE( spec.matches(*fakeTestCase("only foo", "[foo]")) )
with expansion:
!false
CmdLine.tests.cpp:<line number>: PASSED:
CHECK_FALSE( spec.matches(*fakeTestCase("only hidden", "[.]")) )
with expansion:
!false
CmdLine.tests.cpp:<line number>: PASSED:
CHECK( spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) )
with expansion:
true
-------------------------------------------------------------------------------
Pointers can be compared to null
-------------------------------------------------------------------------------
@ -8671,6 +8715,19 @@ String.tests.cpp:<line number>: PASSED:
with expansion:
0 == 0
-------------------------------------------------------------------------------
StringRef
Substrings
substring start after the end is empty
-------------------------------------------------------------------------------
String.tests.cpp:<line number>
...............................................................................
String.tests.cpp:<line number>: PASSED:
REQUIRE( s.substr(1'000'000, 1).empty() )
with expansion:
true
-------------------------------------------------------------------------------
StringRef
Comparisons are deep
@ -8792,23 +8849,59 @@ String.tests.cpp:<line number>
String.tests.cpp:<line number>: PASSED:
with message:
StringRef{}.size() == 0
empty.size() == 0
String.tests.cpp:<line number>: PASSED:
with message:
StringRef{ "abc", 3 }.size() == 3
empty.begin() == empty.end()
String.tests.cpp:<line number>: PASSED:
with message:
StringRef{ "abc", 3 }.isNullTerminated()
stringref.size() == 3
String.tests.cpp:<line number>: PASSED:
with message:
StringRef{ "abc", 2 }.size() == 2
stringref.isNullTerminated()
String.tests.cpp:<line number>: PASSED:
with message:
!(StringRef{ "abc", 2 }.isNullTerminated())
stringref.data() == abc
String.tests.cpp:<line number>: PASSED:
with message:
stringref.begin() == abc
String.tests.cpp:<line number>: PASSED:
with message:
stringref.begin() != stringref.end()
String.tests.cpp:<line number>: PASSED:
with message:
stringref.substr(10, 0).empty()
String.tests.cpp:<line number>: PASSED:
with message:
stringref.substr(2, 1).data() == abc + 2
String.tests.cpp:<line number>: PASSED:
with message:
shortened.size() == 2
String.tests.cpp:<line number>: PASSED:
with message:
shortened.data() == abc
String.tests.cpp:<line number>: PASSED:
with message:
shortened.begin() != shortened.end()
String.tests.cpp:<line number>: PASSED:
with message:
!(shortened.isNullTerminated())
String.tests.cpp:<line number>: PASSED:
with message:
!(shortened.substr(1, 3).isNullTerminated())
-------------------------------------------------------------------------------
StringRef at compilation time
@ -13961,5 +14054,5 @@ Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 320 | 230 passed | 86 failed | 4 failed as expected
assertions: 1793 | 1624 passed | 148 failed | 21 failed as expected
assertions: 1809 | 1640 passed | 148 failed | 21 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="132" tests="1794" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="132" tests="1810" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
<property name="random-seed" value="1"/>
@ -983,6 +983,8 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Parse test names and tags/quoted string followed by tag exclusion" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test spec" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test name" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags are split apart when parsing" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags also properly handle exclusion" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Pointers can be compared to null" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Precision of floating point stringification can be set/Floats" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Precision of floating point stringification can be set/Double" time="{duration}"/>
@ -1112,6 +1114,7 @@ Matchers.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="StringRef/Substrings/Pointer values of substring refs should also match" time="{duration}"/>
<testcase classname="<exe-name>.global" name="StringRef/Substrings/Past the end substring" time="{duration}"/>
<testcase classname="<exe-name>.global" name="StringRef/Substrings/Substring off the end are trimmed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="StringRef/Substrings/substring start after the end is empty" time="{duration}"/>
<testcase classname="<exe-name>.global" name="StringRef/Comparisons are deep" time="{duration}"/>
<testcase classname="<exe-name>.global" name="StringRef/from std::string/implicitly constructed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="StringRef/from std::string/explicitly constructed" time="{duration}"/>

View File

@ -35,6 +35,8 @@
<testCase name="Parse test names and tags/quoted string followed by tag exclusion" duration="{duration}"/>
<testCase name="Parse test names and tags/Leading and trailing spaces in test spec" duration="{duration}"/>
<testCase name="Parse test names and tags/Leading and trailing spaces in test name" duration="{duration}"/>
<testCase name="Parse test names and tags/Shortened hide tags are split apart when parsing" duration="{duration}"/>
<testCase name="Parse test names and tags/Shortened hide tags also properly handle exclusion" duration="{duration}"/>
<testCase name="Process can be configured on command line/empty args don't cause a crash" duration="{duration}"/>
<testCase name="Process can be configured on command line/default - no arguments" duration="{duration}"/>
<testCase name="Process can be configured on command line/test lists/Specify one test case using" duration="{duration}"/>
@ -140,6 +142,7 @@
<testCase name="StringRef/Substrings/Pointer values of substring refs should also match" duration="{duration}"/>
<testCase name="StringRef/Substrings/Past the end substring" duration="{duration}"/>
<testCase name="StringRef/Substrings/Substring off the end are trimmed" duration="{duration}"/>
<testCase name="StringRef/Substrings/substring start after the end is empty" duration="{duration}"/>
<testCase name="StringRef/Comparisons are deep" duration="{duration}"/>
<testCase name="StringRef/from std::string/implicitly constructed" duration="{duration}"/>
<testCase name="StringRef/from std::string/explicitly constructed" duration="{duration}"/>

View File

@ -37,7 +37,7 @@ ok {test-number} -
# #1403
ok {test-number} - h1 == h2 for: [1403 helper] == [1403 helper]
# #1455 - INFO and WARN can start with a linebreak
warning 20 - '
warning {test-number} - '
This info message starts with a linebreak' with 1 message: '
This warning message starts with a linebreak'
This would not be caught previously
@ -795,7 +795,7 @@ not ok {test-number} - explicitly
# FAIL_CHECK does not abort the test
not ok {test-number} - explicitly with 1 message: 'This is a failure'
# FAIL_CHECK does not abort the test
warning 397 - 'This message appears in the output'
warning {test-number} - 'This message appears in the output'
# Factorials are computed
ok {test-number} - Factorial(0) == 1 for: 1 == 1
# Factorials are computed
@ -1443,7 +1443,7 @@ ok {test-number} - !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))
# Greater-than inequalities with different epsilons
ok {test-number} - d >= Approx( 1.24 ).epsilon(0.1) for: 1.23 >= Approx( 1.24 )
# INFO and WARN do not abort tests
warning 721 - 'this is a message' with 1 message: 'this is a warning'
warning {test-number} - 'this is a message' with 1 message: 'this is a warning'
# INFO gets logged on failure
not ok {test-number} - a == 1 for: 2 == 1 with 2 messages: 'this message should be logged' and 'so should this'
# INFO gets logged on failure, even if captured before successful assertions
@ -1569,7 +1569,7 @@ ok {test-number} - values > -6 for: 98 > -6
# Nested generators and captured variables
ok {test-number} - values > -6 for: 99 > -6
# Nice descriptive name
warning 784 - 'This one ran'
warning {test-number} - 'This one ran'
# Non-std exceptions can be translated
not ok {test-number} - unexpected exception with message: 'custom exception'
# Objects that evaluated in boolean contexts can be checked
@ -1978,6 +1978,18 @@ ok {test-number} - spec.matches( *fakeTestCase( " aardvark " ) ) for: true
ok {test-number} - spec.matches( *fakeTestCase( "aardvark " ) ) for: true
# Parse test names and tags
ok {test-number} - spec.matches( *fakeTestCase( "aardvark" ) ) for: true
# Parse test names and tags
ok {test-number} - spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")) for: true
# Parse test names and tags
ok {test-number} - !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false
# Parse test names and tags
ok {test-number} - !(spec.matches(*fakeTestCase("hidden and foo", "[.][foo]"))) for: !false
# Parse test names and tags
ok {test-number} - !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false
# Parse test names and tags
ok {test-number} - !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false
# Parse test names and tags
ok {test-number} - spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true
# Pointers can be compared to null
ok {test-number} - p == 0 for: 0 == 0
# Pointers can be compared to null
@ -2288,6 +2300,8 @@ ok {test-number} - s.substr(s.size() + 1, 123).empty() for: true
# StringRef
ok {test-number} - std::strcmp(ss.c_str(), "world!") == 0 for: 0 == 0
# StringRef
ok {test-number} - s.substr(1'000'000, 1).empty() for: true
# StringRef
ok {test-number} - (char*)buffer1 != (char*)buffer2 for: "Hello" != "Hello"
# StringRef
ok {test-number} - left == right for: Hello == Hello
@ -2314,15 +2328,33 @@ ok {test-number} - stdStr == "a stringref" for: "a stringref" == "a stringref"
# StringRef
ok {test-number} - stdStr.size() == sr.size() for: 11 == 11
# StringRef at compilation time
ok {test-number} - with 1 message: 'StringRef{}.size() == 0'
ok {test-number} - with 1 message: 'empty.size() == 0'
# StringRef at compilation time
ok {test-number} - with 1 message: 'StringRef{ "abc", 3 }.size() == 3'
ok {test-number} - with 1 message: 'empty.begin() == empty.end()'
# StringRef at compilation time
ok {test-number} - with 1 message: 'StringRef{ "abc", 3 }.isNullTerminated()'
ok {test-number} - with 1 message: 'stringref.size() == 3'
# StringRef at compilation time
ok {test-number} - with 1 message: 'StringRef{ "abc", 2 }.size() == 2'
ok {test-number} - with 1 message: 'stringref.isNullTerminated()'
# StringRef at compilation time
ok {test-number} - with 1 message: '!(StringRef{ "abc", 2 }.isNullTerminated())'
ok {test-number} - with 1 message: 'stringref.data() == abc'
# StringRef at compilation time
ok {test-number} - with 1 message: 'stringref.begin() == abc'
# StringRef at compilation time
ok {test-number} - with 1 message: 'stringref.begin() != stringref.end()'
# StringRef at compilation time
ok {test-number} - with 1 message: 'stringref.substr(10, 0).empty()'
# StringRef at compilation time
ok {test-number} - with 1 message: 'stringref.substr(2, 1).data() == abc + 2'
# StringRef at compilation time
ok {test-number} - with 1 message: 'shortened.size() == 2'
# StringRef at compilation time
ok {test-number} - with 1 message: 'shortened.data() == abc'
# StringRef at compilation time
ok {test-number} - with 1 message: 'shortened.begin() != shortened.end()'
# StringRef at compilation time
ok {test-number} - with 1 message: '!(shortened.isNullTerminated())'
# StringRef at compilation time
ok {test-number} - with 1 message: '!(shortened.substr(1, 3).isNullTerminated())'
# StringRef at compilation time
ok {test-number} - with 1 message: '!(sr1.empty())'
# StringRef at compilation time
@ -2928,9 +2960,9 @@ not ok {test-number} - unexpected exception with message: 'expected exception';
# When unchecked exceptions are thrown from sections they are always failures
not ok {test-number} - unexpected exception with message: 'unexpected exception'
# Where the LHS is not a simple value
warning 1461 - 'Uncomment the code in this test to check that it gives a sensible compiler error'
warning {test-number} - 'Uncomment the code in this test to check that it gives a sensible compiler error'
# Where there is more to the expression after the RHS
warning 1462 - 'Uncomment the code in this test to check that it gives a sensible compiler error'
warning {test-number} - 'Uncomment the code in this test to check that it gives a sensible compiler error'
# X/level/0/a
ok {test-number} -
# X/level/0/b
@ -3197,9 +3229,9 @@ ok {test-number} - s.result == 17 for: 17 == 17
# measure
ok {test-number} - s.iterations == 1 for: 1 == 1
# mix info, unscoped info and warning
warning 1595 - 'info' with 2 messages: 'unscoped info' and 'and warn may mix'
warning {test-number} - 'info' with 2 messages: 'unscoped info' and 'and warn may mix'
# mix info, unscoped info and warning
warning 1596 - 'info' with 2 messages: 'unscoped info' and 'they are not cleared after warnings'
warning {test-number} - 'info' with 2 messages: 'unscoped info' and 'they are not cleared after warnings'
# more nested SECTION tests
not ok {test-number} - a == b for: 1 == 2
# more nested SECTION tests
@ -3578,5 +3610,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} -
# xmlentitycheck
ok {test-number} -
1..1785
1..1801

View File

@ -8025,7 +8025,7 @@ Nor would this
</Section>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Parse test names and tags" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<TestCase name="Parse test names and tags" tags="[command-line][test-spec]" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Section name="Empty test spec should have no filters" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
@ -9285,6 +9285,60 @@ Nor would this
</Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
</Section>
<Section name="Shortened hide tags are split apart when parsing" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(*fakeTestCase("hidden and foo", "[.][foo]"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="CHECK_FALSE" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(*fakeTestCase("only foo", "[foo]")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="Shortened hide tags also properly handle exclusion" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="CHECK_FALSE" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<Expression success="true" type="CHECK_FALSE" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(*fakeTestCase("only foo", "[foo]")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<Expression success="true" type="CHECK_FALSE" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(*fakeTestCase("only hidden", "[.]")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Pointers can be compared to null" filename="tests/<exe-name>/UsageTests/Condition.tests.cpp" >
@ -10852,6 +10906,20 @@ Message from section two
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Substrings" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Section name="substring start after the end is empty" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
s.substr(1'000'000, 1).empty()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Comparisons are deep" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
@ -10993,7 +11061,7 @@ Message from section two
</TestCase>
<TestCase name="StringRef at compilation time" tags="[constexpr][StringRef][Strings]" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Section name="Simple constructors" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<OverallResults successes="5" failures="0" expectedFailures="0"/>
<OverallResults successes="14" failures="0" expectedFailures="0"/>
</Section>
<Section name="UDL construction" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<OverallResults successes="6" failures="0" expectedFailures="0"/>
@ -16841,7 +16909,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="1624" failures="149" expectedFailures="21"/>
<OverallResults successes="1640" failures="149" expectedFailures="21"/>
</Group>
<OverallResults successes="1624" failures="148" expectedFailures="21"/>
<OverallResults successes="1640" failures="148" expectedFailures="21"/>
</Catch>

View File

@ -19,7 +19,7 @@ namespace {
auto fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCaseInfo("", { name, desc }, CATCH_INTERNAL_LINEINFO); }
}
TEST_CASE( "Parse test names and tags" ) {
TEST_CASE( "Parse test names and tags", "[command-line][test-spec]" ) {
using Catch::parseTestSpec;
using Catch::TestSpec;
@ -280,7 +280,18 @@ TEST_CASE( "Parse test names and tags" ) {
CHECK( spec.matches( *fakeTestCase( " aardvark " ) ) );
CHECK( spec.matches( *fakeTestCase( "aardvark " ) ) );
CHECK( spec.matches( *fakeTestCase( "aardvark" ) ) );
}
SECTION("Shortened hide tags are split apart when parsing") {
TestSpec spec = parseTestSpec("[.foo]");
CHECK(spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")));
CHECK_FALSE(spec.matches(*fakeTestCase("only foo", "[foo]")));
}
SECTION("Shortened hide tags also properly handle exclusion") {
TestSpec spec = parseTestSpec("~[.foo]");
CHECK_FALSE(spec.matches(*fakeTestCase("hidden and foo", "[.][foo]")));
CHECK_FALSE(spec.matches(*fakeTestCase("only foo", "[foo]")));
CHECK_FALSE(spec.matches(*fakeTestCase("only hidden", "[.]")));
CHECK(spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")));
}
}

View File

@ -315,6 +315,21 @@ TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
REQUIRE(value == value2);
}
TEST_CASE("#1809 - GENERATE_COPY and SingleValueGenerator does not compile", "[generators][compilation][approvals]") {
// Verify Issue #1809 fix, only needs to compile.
auto a = GENERATE_COPY(1, 2);
(void)a;
auto b = GENERATE_COPY(as<long>{}, 1, 2);
(void)b;
int i = 1;
int j = 2;
auto c = GENERATE_COPY(i, j);
(void)c;
auto d = GENERATE_COPY(as<long>{}, i, j);
(void)d;
SUCCEED();
}
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
SECTION("Integer") {
auto random1 = Catch::Generators::random(0, 1000);

View File

@ -72,7 +72,9 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
ss = s.substr(6, 123);
REQUIRE(std::strcmp(ss.c_str(), "world!") == 0);
}
// TODO: substring into string + size is longer than end
SECTION("substring start after the end is empty") {
REQUIRE(s.substr(1'000'000, 1).empty());
}
}
SECTION( "Comparisons are deep" ) {
@ -124,15 +126,32 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
}
TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") {
//TODO:
// * substr
using Catch::StringRef;
SECTION("Simple constructors") {
STATIC_REQUIRE(StringRef{}.size() == 0);
constexpr StringRef empty{};
STATIC_REQUIRE(empty.size() == 0);
STATIC_REQUIRE(empty.begin() == empty.end());
STATIC_REQUIRE(StringRef{ "abc", 3 }.size() == 3);
STATIC_REQUIRE(StringRef{ "abc", 3 }.isNullTerminated());
constexpr char const* const abc = "abc";
STATIC_REQUIRE(StringRef{ "abc", 2 }.size() == 2);
STATIC_REQUIRE_FALSE(StringRef{ "abc", 2 }.isNullTerminated());
constexpr StringRef stringref(abc, 3);
STATIC_REQUIRE(stringref.size() == 3);
STATIC_REQUIRE(stringref.isNullTerminated());
STATIC_REQUIRE(stringref.data() == abc);
STATIC_REQUIRE(stringref.begin() == abc);
STATIC_REQUIRE(stringref.begin() != stringref.end());
STATIC_REQUIRE(stringref.substr(10, 0).empty());
STATIC_REQUIRE(stringref.substr(2, 1).data() == abc + 2);
constexpr StringRef shortened(abc, 2);
STATIC_REQUIRE(shortened.size() == 2);
STATIC_REQUIRE(shortened.data() == abc);
STATIC_REQUIRE(shortened.begin() != shortened.end());
STATIC_REQUIRE_FALSE(shortened.isNullTerminated());
STATIC_REQUIRE_FALSE(shortened.substr(1, 3).isNullTerminated());
}
SECTION("UDL construction") {
constexpr auto sr1 = "abc"_catch_sr;

View File

@ -1,5 +1,6 @@
#include <catch2/catch_test_macros.hpp>
#include <catch2/benchmark/catch_benchmark.hpp>
#include <catch2/benchmark/catch_constructor.hpp>
#include <catch2/catch_generators_specific.hpp>
#include <map>
@ -127,4 +128,18 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
REQUIRE(v[i] == generated);
}
}
SECTION("construct and destroy example") {
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); });
};
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
for(auto&& o : storage)
o.construct("thing");
meter.measure([&](int i) { storage[i].destruct(); });
};
}
}

View File

@ -71,7 +71,7 @@ nanParser = re.compile(r'''
''', re.VERBOSE)
# The weird OR is there to always have at least empty string for group 1
tapTestNumParser = re.compile(r'^(not |)?ok (\d+) -')
tapTestNumParser = re.compile(r'^((?:not ok)|(?:ok)|(?:warning)|(?:info)) (\d+) -')
if len(sys.argv) == 2:
cmdPath = sys.argv[1]
@ -128,7 +128,7 @@ def filterLine(line, isCompact):
line = line.replace(': PASSED', ': passed')
# strip out the test order number in TAP to avoid massive diffs for every change
line = tapTestNumParser.sub("\g<1>ok {test-number} -", line)
line = tapTestNumParser.sub("\g<1> {test-number} -", line)
# strip Catch version number
line = versionParser.sub("<version>", line)