Compare commits

..

16 Commits

Author SHA1 Message Date
Martin Hořeňovský b670de4fe1 v3.14.0 2026-04-05 15:05:38 +02:00
Martin Hořeňovský 465e63dad7 Do not include chrono_clock.hpp in benchmark_stats_fwd.hpp 2026-04-05 14:57:05 +02:00
Christoph Grüninger 34f4f81947 [ci] Update GitHub Actions to latest major release
Fix warning that Node.js 20 is disconinued in June
2026-04-04 22:28:48 +02:00
Martin Hořeňovský 57f738b380 JUnit reporter output single failed assertion node per test case
Ideally JUnit tools would handle multiple failures per test case,
but they don't, so here we are.

Closes #1919
2026-04-04 15:12:56 +02:00
Martin Hořeňovský 1df10d28ae Don't write semicolon after failed expression in separate call 2026-04-03 10:28:32 +02:00
Martin Hořeňovský 9f1b48a94f Inline SKIP/FAIL in RunContext to fix build failure with prefixed macros
Closes #3087
2026-04-03 10:19:05 +02:00
Sung, Po Han f4e83daa18 Fix catch_discover_tests PRE_TEST failure with zero discoverable tests
When using catch_discover_tests() with DISCOVERY_MODE PRE_TEST and a
multi-config generator (e.g. Ninja Multi-Config), if a test target has
zero discoverable tests (e.g. all tests tagged with [.]), ctest fails:

  CMake Error: include could not find requested file:
    .../test-hidden-b12d07c_tests-Release.cmake

The early return added in #2962 (76f70b14) correctly prevented a JSON
parsing crash for zero tests, but skipped writing the ctest file. The
PRE_TEST include script unconditionally includes this file, so the
missing file causes a hard error that aborts all test discovery.

Write an empty file before returning early so the include always
succeeds.
2026-04-02 10:24:46 +02:00
Jan Niklas Hasse 572f96b8fe Fix counting of UTF-8 codepoints in TextFlow
For line-wrapping bytes were counted instead of codepoints. This
resulted in line-breaks being inserted at the wrong position and also
breaking UTF-8 characters.

Fixes #1022.
2026-04-01 16:12:08 +02:00
Martin Hořeňovský 8492fd444e Ignore Wunreachable-code-return in Generators.tests.cpp 2026-04-01 11:02:56 +02:00
Martin Hořeňovský fe2a20ab55 Fix warning suppression block in Condition.tests straddling includes 2026-04-01 10:56:21 +02:00
Martin Hořeňovský 51b0532d1f Suppress __COUNTER__ warning from newest Clang versions
Ideally we could suppress the warning locally in the `UNIQUE_NAME` macro,
but that runs into at least 2 issues:

1) Clang actually does not consider the warning as coming from inside the
   `UNIQUE_NAME` macro, even though it correctly points to its expansion
   as the problem. This means that adding `_Pragma`s inside the macro
   around the __COUNTER__ usage does not actually silence the warning.

2) Adding the local suppressions anyway breaks the expansion of
   `MAKE_NAMESPACE` macro inside the templated test case macros. This can
   be fixed for the newest clang version by removing its use and using
   the uniqued `TestName` for the namespace name directly, but this breaks
   compilation on GCC, and older Clang versions.

Because of these issues, we introduce global warning suppression for
`-Wc2y-extensions` to be done with it. We should revisit this if Clang 23
fixes the local pragma based suppression, when it might be worth the effort
to rework the templated test case macros to support it.

Closes #3076
2026-04-01 10:34:58 +02:00
Joseph Edwards 2ec64d12b1 fix: add missing backslash in macro definition 2026-03-30 14:23:17 +02:00
Martin Hořeňovský ccc49ba664 Merge pull request #3078 from e-kwsm/cstdint
fix: add missed <cstdint> inclusion
2026-03-11 13:44:52 +01:00
Eisuke Kawashima 6f036244e9 fix: add missed <cstdint> inclusion 2026-03-08 19:34:59 +09:00
Vertexwahn 50e9dbfc4e Update bazel_skylib and rules_cc dependencies 2026-02-18 20:14:05 +01:00
Martin Hořeňovský a404f37cec Add quiet verbosity variant to the default listener and tag listing 2026-02-16 22:52:39 +01:00
39 changed files with 473 additions and 1285 deletions
+2 -2
View File
@@ -16,10 +16,10 @@ jobs:
compilation_mode: [fastbuild, dbg, opt]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Mount Bazel cache
uses: actions/cache@v3
uses: actions/cache@v5
with:
path: "/home/runner/.cache/bazel"
key: bazel-ubuntu22-gcc11
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
other_pkgs: clang-11
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Prepare environment
run: |
+2 -2
View File
@@ -75,7 +75,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Prepare environment
run: |
@@ -100,7 +100,7 @@ jobs:
name: clang-tidy
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Prepare environment
run: |
+1 -1
View File
@@ -83,7 +83,7 @@ jobs:
other_pkgs: g++-11
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Add repositories for older compilers
run: |
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
std: [14, 17]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Configure
run: |
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
filter:
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Configure
@@ -18,7 +18,7 @@ jobs:
profile_generate: 'false'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install conan
run: pip install conan==${{matrix.conan_version}}
+2 -2
View File
@@ -9,10 +9,10 @@ jobs:
steps:
- name: Checkout source code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Dependencies
uses: actions/setup-python@v2
uses: actions/setup-python@v6
with:
python-version: '3.7'
- name: Install checkguard
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
build_type: [Debug, Release]
std: [14, 17]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Configure build
run: |
+1 -1
View File
@@ -35,7 +35,7 @@ if(CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
project(Catch2
VERSION 3.13.0 # CML version placeholder, don't delete
VERSION 3.14.0 # CML version placeholder, don't delete
LANGUAGES CXX
HOMEPAGE_URL "https://github.com/catchorg/Catch2"
DESCRIPTION "A modern, C++-native, unit test framework."
+2 -2
View File
@@ -1,5 +1,5 @@
module(name = "catch2")
bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "rules_cc", version = "0.2.16")
bazel_dep(name = "rules_license", version = "1.0.0")
+3 -2
View File
@@ -289,9 +289,10 @@ as follows:
| Option | `normal` (default) | `quiet` | `high` |
|--------------------|---------------------------------|---------------------|-----------------------------------------|
| `--list-tests` | Test names and tags | Test names only | Same as `normal`, plus source code line |
| `--list-tags` | Tags and counts | Same as `normal` | Same as `normal` |
| `--list-tags` | Tags and counts | Tags only | Same as `normal` |
| `--list-reporters` | Reporter names and descriptions | Reporter names only | Same as `normal` |
| `--list-listeners` | Listener names and descriptions | Same as `normal` | Same as `normal` |
| `--list-listeners` | Listener names and descriptions | Listener names only | Same as `normal` |
<a id="sending-output-to-a-file"></a>
## Sending output to a file
+17 -1
View File
@@ -2,6 +2,7 @@
# Release notes
**Contents**<br>
[3.14.0](#3140)<br>
[3.13.0](#3130)<br>
[3.12.0](#3120)<br>
[3.11.0](#3110)<br>
@@ -73,6 +74,22 @@
[Even Older versions](#even-older-versions)<br>
## 3.14.0
### Fixes
* Added missing `<cstdint>` includes. (#3078)
* Fixed suppression of empty variadic macro arguments warning on Clang <19. (#3085)
* Fixed `catch_discover_tests` failing during `PRE_TEST` discovery if a target does not have discoverable tests. (#3075)
* Fixed build of the main library failing with `CATCH_CONFIG_PREFIX_ALL` defined. (#3087)
* JUnit reporter outputs single failed (errored/skipped) assertion per test case. (#1919)
### Improvements
* The default implementation of `--list-tags` and `--list-listeners` has a quiet variant.
* Suppressed the new Clang warning about `__COUNTER__` usage. (#3076)
* Line-wrapping counts utf-8 codepoints instead of bytes. (#1022, #3086)
* Combining character sequences are still miscounted, but Catch2 does not aim to fully support Unicode.
## 3.13.0
### Fixes
@@ -80,7 +97,6 @@
* The CLI validation fails instead.
* Fixed warning suppression macros being doubly defined when using Clang on Windows (#3060)
### Improvements
* Suppressed static analysis 26426 diagnostic for MSVC (#3057)
* Renamed the internal deprecation macro from `DEPRECATED` to `CATCH_DEPRECATED` to avoid conflicts (#3058)
+1
View File
@@ -146,6 +146,7 @@ function(catch_discover_tests_impl)
# Exit early if no tests are detected
if(num_tests STREQUAL "0")
file(WRITE "${_CTEST_FILE}" "")
return()
endif()
+122 -72
View File
@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
// Catch v3.13.0
// Generated: 2026-02-15 22:55:00.269529
// Catch v3.14.0
// Generated: 2026-04-05 15:03:01.631668
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -2397,7 +2397,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 3, 13, 0, "", 0 );
static Version version( 3, 14, 0, "", 0 );
return version;
}
@@ -5888,9 +5888,14 @@ namespace Catch {
// can be, so the tracker has to throw for a wrong
// filter to stop the execution flow.
if (filter.type == PathFilter::For::Section) {
// TBD: Explicit SKIP, or new exception that says
// "don't continue", but doesn't show in totals?
SKIP();
// We want the semantics of `SKIP()`, but we inline it
// to avoid issues with conditionally prefixed macros
INTERNAL_CATCH_MSG(
"SKIP",
Catch::ResultWas::ExplicitSkip,
Catch::ResultDisposition::Normal,
"" );
Catch::Detail::Unreachable();
}
// '*' is the wildcard for "all elements in generator"
// used for filtering sections below the generator, but
@@ -6347,8 +6352,12 @@ namespace Catch {
// TBD: Do we want to avoid the warning if the generator is filtered?
if ( m_config->warnAboutInfiniteGenerators() &&
!generator->isFinite() ) {
// TBD: Would it be better to expand this macro inline?
FAIL( "GENERATE() would run infinitely" );
// We want the semantics of `FAIL()`, but we inline it
// to avoid issues with conditionally prefixed macros
INTERNAL_CATCH_MSG( "FAIL",
Catch::ResultWas::ExplicitFailure,
Catch::ResultDisposition::Normal,
"GENERATE() would run infinitely" );
}
auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo );
@@ -7893,6 +7902,10 @@ namespace {
return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
}
bool isUtf8ContinuationByte( char c ) {
return ( static_cast<unsigned char>( c ) & 0xC0 ) == 0x80;
}
} // namespace
namespace Catch {
@@ -7919,6 +7932,11 @@ namespace Catch {
if ( it != m_string.end() ) {
++m_size;
++it;
// Skip UTF-8 continuation bytes
while ( it != m_string.end() &&
isUtf8ContinuationByte( *it ) ) {
++it;
}
}
}
}
@@ -7981,6 +7999,11 @@ namespace Catch {
void AnsiSkippingString::const_iterator::advance() {
assert( m_it != m_string->end() );
m_it++;
// Skip UTF-8 continuation bytes
while ( m_it != m_string->end() &&
isUtf8ContinuationByte( *m_it ) ) {
m_it++;
}
tryParseAnsiEscapes();
}
@@ -8000,6 +8023,11 @@ namespace Catch {
assert( *m_it == '\033' );
m_it--;
}
// Skip back over UTF-8 continuation bytes to the leading byte
while ( isUtf8ContinuationByte( *m_it ) ) {
assert( m_it != m_string->begin() );
m_it--;
}
}
static bool isBoundary( AnsiSkippingString const& line,
@@ -9152,12 +9180,12 @@ namespace Catch {
void ReporterBase::listReporters(
std::vector<ReporterDescription> const& descriptions ) {
defaultListReporters(m_stream, descriptions, m_config->verbosity());
defaultListReporters( m_stream, descriptions, m_config->verbosity() );
}
void ReporterBase::listListeners(
std::vector<ListenerDescription> const& descriptions ) {
defaultListListeners( m_stream, descriptions );
defaultListListeners( m_stream, descriptions, m_config->verbosity() );
}
void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
@@ -9169,7 +9197,7 @@ namespace Catch {
}
void ReporterBase::listTags(std::vector<TagInfo> const& tags) {
defaultListTags( m_stream, tags, m_config->hasTestFilters() );
defaultListTags( m_stream, tags, m_config->hasTestFilters(), m_config->verbosity() );
}
} // namespace Catch
@@ -10380,7 +10408,15 @@ namespace Catch {
}
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions ) {
std::vector<ListenerDescription> const& descriptions,
Verbosity verbosity ) {
if ( verbosity == Verbosity::Quiet ) {
for ( auto const& desc : descriptions ) {
out << desc.name << '\n';
}
return;
}
out << "Registered listeners:\n";
if(descriptions.empty()) {
@@ -10413,7 +10449,14 @@ namespace Catch {
void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags,
bool isFiltered ) {
bool isFiltered,
Verbosity verbosity ) {
if (verbosity == Verbosity::Quiet) {
for (auto const& tagCount : tags) {
out << tagCount.all() << '\n';
}
return;
}
if ( isFiltered ) {
out << "Tags for matching test cases:\n";
} else {
@@ -10432,7 +10475,7 @@ namespace Catch {
return lhs.count < rhs.count;
} )
->count;
// more padding necessary for 3+ digits
if (maxTagCount >= 100) {
auto numDigits = 1 + std::floor( std::log10( maxTagCount ) );
@@ -11189,70 +11232,77 @@ namespace Catch {
void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
if (assertionOrBenchmark.isAssertion()) {
writeAssertion(assertionOrBenchmark.asAssertion());
// JUnit XML format supports only 1 error/failure/skip
// assertion elements per test case
if (writeAssertion(assertionOrBenchmark.asAssertion())) {
break;
}
}
}
}
void JunitReporter::writeAssertion( AssertionStats const& stats ) {
bool JunitReporter::writeAssertion( AssertionStats const& stats ) {
AssertionResult const& result = stats.assertionResult;
if ( !result.isOk() ||
result.getResultType() == ResultWas::ExplicitSkip ) {
std::string elementName;
switch( result.getResultType() ) {
case ResultWas::ThrewException:
case ResultWas::FatalErrorCondition:
elementName = "error";
break;
case ResultWas::ExplicitFailure:
case ResultWas::ExpressionFailed:
case ResultWas::DidntThrowException:
elementName = "failure";
break;
case ResultWas::ExplicitSkip:
elementName = "skipped";
break;
// We should never see these here:
case ResultWas::Info:
case ResultWas::Warning:
case ResultWas::Ok:
case ResultWas::Unknown:
case ResultWas::FailureBit:
case ResultWas::Exception:
elementName = "internalError";
break;
}
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
xml.writeAttribute( "message"_sr, result.getExpression() );
xml.writeAttribute( "type"_sr, result.getTestMacroName() );
ReusableStringStream rss;
if ( result.getResultType() == ResultWas::ExplicitSkip ) {
rss << "SKIPPED\n";
} else {
rss << "FAILED" << ":\n";
if (result.hasExpression()) {
rss << " ";
rss << result.getExpressionInMacro();
rss << '\n';
}
if (result.hasExpandedExpression()) {
rss << "with expansion:\n";
rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n';
}
}
if( result.hasMessage() )
rss << result.getMessage() << '\n';
for( auto const& msg : stats.infoMessages )
if( msg.type == ResultWas::Info )
rss << msg.message << '\n';
rss << "at " << result.getSourceInfo();
xml.writeText( rss.str(), XmlFormatting::Newline );
if ( result.isOk() &&
result.getResultType() != ResultWas::ExplicitSkip ) {
return false;
}
std::string elementName;
switch ( result.getResultType() ) {
case ResultWas::ThrewException:
case ResultWas::FatalErrorCondition:
elementName = "error";
break;
case ResultWas::ExplicitFailure:
case ResultWas::ExpressionFailed:
case ResultWas::DidntThrowException:
elementName = "failure";
break;
case ResultWas::ExplicitSkip:
elementName = "skipped";
break;
// We should never see these here:
case ResultWas::Info:
case ResultWas::Warning:
case ResultWas::Ok:
case ResultWas::Unknown:
case ResultWas::FailureBit:
case ResultWas::Exception:
elementName = "internalError";
break;
}
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
xml.writeAttribute( "message"_sr, result.getExpression() );
xml.writeAttribute( "type"_sr, result.getTestMacroName() );
ReusableStringStream rss;
if ( result.getResultType() == ResultWas::ExplicitSkip ) {
rss << "SKIPPED\n";
} else {
rss << "FAILED:\n";
if ( result.hasExpression() ) {
rss << " ";
rss << result.getExpressionInMacro();
rss << '\n';
}
if ( result.hasExpandedExpression() ) {
rss << "with expansion:\n";
rss << TextFlow::Column( result.getExpandedExpression() )
.indent( 2 )
<< '\n';
}
}
if ( result.hasMessage() ) { rss << result.getMessage() << '\n'; }
for ( auto const& msg : stats.infoMessages ) {
if ( msg.type == ResultWas::Info ) { rss << msg.message << '\n'; }
}
rss << "at " << result.getSourceInfo();
xml.writeText( rss.str(), XmlFormatting::Newline );
return true;
}
} // end namespace Catch
+57 -30
View File
@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
// Catch v3.13.0
// Generated: 2026-02-15 22:54:59.817776
// Catch v3.14.0
// Generated: 2026-04-05 15:03:01.150393
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -201,10 +201,15 @@
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wc++20-extensions\"" )
# else
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
# endif
# if ( __clang_major__ >= 22 )
# define CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wc2y-extensions\"" )
# endif
# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
@@ -520,6 +525,9 @@
#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS )
# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS
#endif
#if !defined( CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS )
# define CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS
#endif
#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
@@ -678,8 +686,20 @@ namespace Catch {
#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED
// Fixme: Clang 22 has an annoying bug where the localized suppression
// below does not actually suppress the extension warning from
// using __COUNTER__, so we have to leak the suppression for the
// whole TU. Hopefully Clang 23 fixes this before full release.
// As AppleClang does its own thing version-wise, we ignore it
// completely.
#if defined( __clang__ ) && ( __clang_major__ >= 22 ) && !defined( __APPLE__ )
CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS
#endif
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#ifdef CATCH_CONFIG_COUNTER
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
#else
@@ -1011,35 +1031,16 @@ namespace Detail {
#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
// Adapted from donated nonius code.
#ifndef CATCH_CLOCK_HPP_INCLUDED
#define CATCH_CLOCK_HPP_INCLUDED
#include <chrono>
namespace Catch {
namespace Benchmark {
using IDuration = std::chrono::nanoseconds;
using FDuration = std::chrono::duration<double, std::nano>;
template <typename Clock>
using TimePoint = typename Clock::time_point;
using default_clock = std::chrono::steady_clock;
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_CLOCK_HPP_INCLUDED
namespace Catch {
namespace Detail {
struct DummyTemplateArgPlaceholder;
}
// We cannot forward declare the type with default template argument
// multiple times, so it is split out into a separate header so that
// we can prevent multiple declarations in dependencies
template <typename Duration = Benchmark::FDuration>
template <typename Duration = Detail::DummyTemplateArgPlaceholder>
struct BenchmarkStats;
} // end namespace Catch
@@ -1336,6 +1337,28 @@ namespace Catch {
// Adapted from donated nonius code.
#ifndef CATCH_CLOCK_HPP_INCLUDED
#define CATCH_CLOCK_HPP_INCLUDED
#include <chrono>
namespace Catch {
namespace Benchmark {
using IDuration = std::chrono::nanoseconds;
using FDuration = std::chrono::duration<double, std::nano>;
template <typename Clock>
using TimePoint = typename Clock::time_point;
using default_clock = std::chrono::steady_clock;
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_CLOCK_HPP_INCLUDED
// Adapted from donated nonius code.
#ifndef CATCH_ESTIMATE_HPP_INCLUDED
@@ -7514,7 +7537,7 @@ namespace Catch {
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_MINOR 14
#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -13967,7 +13990,8 @@ namespace Catch {
* format
*/
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions );
std::vector<ListenerDescription> const& descriptions,
Verbosity verbosity );
/**
* Lists tag information to the provided stream in user-friendly format
@@ -13976,7 +14000,10 @@ namespace Catch {
* bases. The output should be backwards compatible with the output of
* Catch2 v2 binaries.
*/
void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags,
bool isFiltered,
Verbosity verbosity );
/**
* Lists test case information to the provided stream in user-friendly
@@ -14126,7 +14153,7 @@ namespace Catch {
bool testOkToFail );
void writeAssertions(SectionNode const& sectionNode);
void writeAssertion(AssertionStats const& stats);
bool writeAssertion(AssertionStats const& stats);
XmlWriter xml;
Timer suiteTimer;
+1
View File
@@ -9,6 +9,7 @@
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <cstdint>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+1
View File
@@ -13,6 +13,7 @@
#include <string>
#include <string_view>
#include <cstdint>
template<class Callback>
+1 -1
View File
@@ -8,7 +8,7 @@
project(
'catch2',
'cpp',
version: '3.13.0', # CML version placeholder, don't delete
version: '3.14.0', # CML version placeholder, don't delete
license: 'BSL-1.0',
meson_version: '>=0.54.1',
)
@@ -8,6 +8,7 @@
#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED
#define CATCH_BENCHMARK_STATS_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_estimate.hpp>
#include <catch2/benchmark/catch_outlier_classification.hpp>
// The fwd decl & default specialization needs to be seen by VS2017 before
@@ -8,14 +8,16 @@
#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
namespace Catch {
namespace Detail {
struct DummyTemplateArgPlaceholder;
}
// We cannot forward declare the type with default template argument
// multiple times, so it is split out into a separate header so that
// we can prevent multiple declarations in dependencies
template <typename Duration = Benchmark::FDuration>
template <typename Duration = Detail::DummyTemplateArgPlaceholder>
struct BenchmarkStats;
} // end namespace Catch
+1 -1
View File
@@ -36,7 +36,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 3, 13, 0, "", 0 );
static Version version( 3, 14, 0, "", 0 );
return version;
}
+1 -1
View File
@@ -9,7 +9,7 @@
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_MINOR 14
#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -110,10 +110,15 @@
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wc++20-extensions\"" )
# else
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
# endif
# if ( __clang_major__ >= 22 )
# define CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wc2y-extensions\"" )
# endif
# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
@@ -429,6 +434,9 @@
#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS )
# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS
#endif
#if !defined( CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS )
# define CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS
#endif
#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
+14 -5
View File
@@ -60,9 +60,14 @@ namespace Catch {
// can be, so the tracker has to throw for a wrong
// filter to stop the execution flow.
if (filter.type == PathFilter::For::Section) {
// TBD: Explicit SKIP, or new exception that says
// "don't continue", but doesn't show in totals?
SKIP();
// We want the semantics of `SKIP()`, but we inline it
// to avoid issues with conditionally prefixed macros
INTERNAL_CATCH_MSG(
"SKIP",
Catch::ResultWas::ExplicitSkip,
Catch::ResultDisposition::Normal,
"" );
Catch::Detail::Unreachable();
}
// '*' is the wildcard for "all elements in generator"
// used for filtering sections below the generator, but
@@ -519,8 +524,12 @@ namespace Catch {
// TBD: Do we want to avoid the warning if the generator is filtered?
if ( m_config->warnAboutInfiniteGenerators() &&
!generator->isFinite() ) {
// TBD: Would it be better to expand this macro inline?
FAIL( "GENERATE() would run infinitely" );
// We want the semantics of `FAIL()`, but we inline it
// to avoid issues with conditionally prefixed macros
INTERNAL_CATCH_MSG( "FAIL",
Catch::ResultWas::ExplicitFailure,
Catch::ResultDisposition::Normal,
"GENERATE() would run infinitely" );
}
auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo );
+19
View File
@@ -26,6 +26,10 @@ namespace {
return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
}
bool isUtf8ContinuationByte( char c ) {
return ( static_cast<unsigned char>( c ) & 0xC0 ) == 0x80;
}
} // namespace
namespace Catch {
@@ -52,6 +56,11 @@ namespace Catch {
if ( it != m_string.end() ) {
++m_size;
++it;
// Skip UTF-8 continuation bytes
while ( it != m_string.end() &&
isUtf8ContinuationByte( *it ) ) {
++it;
}
}
}
}
@@ -114,6 +123,11 @@ namespace Catch {
void AnsiSkippingString::const_iterator::advance() {
assert( m_it != m_string->end() );
m_it++;
// Skip UTF-8 continuation bytes
while ( m_it != m_string->end() &&
isUtf8ContinuationByte( *m_it ) ) {
m_it++;
}
tryParseAnsiEscapes();
}
@@ -133,6 +147,11 @@ namespace Catch {
assert( *m_it == '\033' );
m_it--;
}
// Skip back over UTF-8 continuation bytes to the leading byte
while ( isUtf8ContinuationByte( *m_it ) ) {
assert( m_it != m_string->begin() );
m_it--;
}
}
static bool isBoundary( AnsiSkippingString const& line,
+13
View File
@@ -8,9 +8,22 @@
#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED
#define CATCH_UNIQUE_NAME_HPP_INCLUDED
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_config_counter.hpp>
// Fixme: Clang 22 has an annoying bug where the localized suppression
// below does not actually suppress the extension warning from
// using __COUNTER__, so we have to leak the suppression for the
// whole TU. Hopefully Clang 23 fixes this before full release.
// As AppleClang does its own thing version-wise, we ignore it
// completely.
#if defined( __clang__ ) && ( __clang_major__ >= 22 ) && !defined( __APPLE__ )
CATCH_INTERNAL_SUPPRESS_COUNTER_WARNINGS
#endif
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#ifdef CATCH_CONFIG_COUNTER
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
#else
@@ -26,12 +26,12 @@ namespace Catch {
void ReporterBase::listReporters(
std::vector<ReporterDescription> const& descriptions ) {
defaultListReporters(m_stream, descriptions, m_config->verbosity());
defaultListReporters( m_stream, descriptions, m_config->verbosity() );
}
void ReporterBase::listListeners(
std::vector<ListenerDescription> const& descriptions ) {
defaultListListeners( m_stream, descriptions );
defaultListListeners( m_stream, descriptions, m_config->verbosity() );
}
void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
@@ -43,7 +43,7 @@ namespace Catch {
}
void ReporterBase::listTags(std::vector<TagInfo> const& tags) {
defaultListTags( m_stream, tags, m_config->hasTestFilters() );
defaultListTags( m_stream, tags, m_config->hasTestFilters(), m_config->verbosity() );
}
} // namespace Catch
@@ -143,7 +143,15 @@ namespace Catch {
}
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions ) {
std::vector<ListenerDescription> const& descriptions,
Verbosity verbosity ) {
if ( verbosity == Verbosity::Quiet ) {
for ( auto const& desc : descriptions ) {
out << desc.name << '\n';
}
return;
}
out << "Registered listeners:\n";
if(descriptions.empty()) {
@@ -176,7 +184,14 @@ namespace Catch {
void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags,
bool isFiltered ) {
bool isFiltered,
Verbosity verbosity ) {
if (verbosity == Verbosity::Quiet) {
for (auto const& tagCount : tags) {
out << tagCount.all() << '\n';
}
return;
}
if ( isFiltered ) {
out << "Tags for matching test cases:\n";
} else {
@@ -195,7 +210,7 @@ namespace Catch {
return lhs.count < rhs.count;
} )
->count;
// more padding necessary for 3+ digits
if (maxTagCount >= 100) {
auto numDigits = 1 + std::floor( std::log10( maxTagCount ) );
@@ -55,7 +55,8 @@ namespace Catch {
* format
*/
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions );
std::vector<ListenerDescription> const& descriptions,
Verbosity verbosity );
/**
* Lists tag information to the provided stream in user-friendly format
@@ -64,7 +65,10 @@ namespace Catch {
* bases. The output should be backwards compatible with the output of
* Catch2 v2 binaries.
*/
void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags,
bool isFiltered,
Verbosity verbosity );
/**
* Lists test case information to the provided stream in user-friendly
+65 -58
View File
@@ -241,70 +241,77 @@ namespace Catch {
void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
if (assertionOrBenchmark.isAssertion()) {
writeAssertion(assertionOrBenchmark.asAssertion());
// JUnit XML format supports only 1 error/failure/skip
// assertion elements per test case
if (writeAssertion(assertionOrBenchmark.asAssertion())) {
break;
}
}
}
}
void JunitReporter::writeAssertion( AssertionStats const& stats ) {
bool JunitReporter::writeAssertion( AssertionStats const& stats ) {
AssertionResult const& result = stats.assertionResult;
if ( !result.isOk() ||
result.getResultType() == ResultWas::ExplicitSkip ) {
std::string elementName;
switch( result.getResultType() ) {
case ResultWas::ThrewException:
case ResultWas::FatalErrorCondition:
elementName = "error";
break;
case ResultWas::ExplicitFailure:
case ResultWas::ExpressionFailed:
case ResultWas::DidntThrowException:
elementName = "failure";
break;
case ResultWas::ExplicitSkip:
elementName = "skipped";
break;
// We should never see these here:
case ResultWas::Info:
case ResultWas::Warning:
case ResultWas::Ok:
case ResultWas::Unknown:
case ResultWas::FailureBit:
case ResultWas::Exception:
elementName = "internalError";
break;
}
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
xml.writeAttribute( "message"_sr, result.getExpression() );
xml.writeAttribute( "type"_sr, result.getTestMacroName() );
ReusableStringStream rss;
if ( result.getResultType() == ResultWas::ExplicitSkip ) {
rss << "SKIPPED\n";
} else {
rss << "FAILED" << ":\n";
if (result.hasExpression()) {
rss << " ";
rss << result.getExpressionInMacro();
rss << '\n';
}
if (result.hasExpandedExpression()) {
rss << "with expansion:\n";
rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n';
}
}
if( result.hasMessage() )
rss << result.getMessage() << '\n';
for( auto const& msg : stats.infoMessages )
if( msg.type == ResultWas::Info )
rss << msg.message << '\n';
rss << "at " << result.getSourceInfo();
xml.writeText( rss.str(), XmlFormatting::Newline );
if ( result.isOk() &&
result.getResultType() != ResultWas::ExplicitSkip ) {
return false;
}
std::string elementName;
switch ( result.getResultType() ) {
case ResultWas::ThrewException:
case ResultWas::FatalErrorCondition:
elementName = "error";
break;
case ResultWas::ExplicitFailure:
case ResultWas::ExpressionFailed:
case ResultWas::DidntThrowException:
elementName = "failure";
break;
case ResultWas::ExplicitSkip:
elementName = "skipped";
break;
// We should never see these here:
case ResultWas::Info:
case ResultWas::Warning:
case ResultWas::Ok:
case ResultWas::Unknown:
case ResultWas::FailureBit:
case ResultWas::Exception:
elementName = "internalError";
break;
}
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
xml.writeAttribute( "message"_sr, result.getExpression() );
xml.writeAttribute( "type"_sr, result.getTestMacroName() );
ReusableStringStream rss;
if ( result.getResultType() == ResultWas::ExplicitSkip ) {
rss << "SKIPPED\n";
} else {
rss << "FAILED:\n";
if ( result.hasExpression() ) {
rss << " ";
rss << result.getExpressionInMacro();
rss << '\n';
}
if ( result.hasExpandedExpression() ) {
rss << "with expansion:\n";
rss << TextFlow::Column( result.getExpandedExpression() )
.indent( 2 )
<< '\n';
}
}
if ( result.hasMessage() ) { rss << result.getMessage() << '\n'; }
for ( auto const& msg : stats.infoMessages ) {
if ( msg.type == ResultWas::Info ) { rss << msg.message << '\n'; }
}
rss << "at " << result.getSourceInfo();
xml.writeText( rss.str(), XmlFormatting::Newline );
return true;
}
} // end namespace Catch
@@ -41,7 +41,7 @@ namespace Catch {
bool testOkToFail );
void writeAssertions(SectionNode const& sectionNode);
void writeAssertion(AssertionStats const& stats);
bool writeAssertion(AssertionStats const& stats);
XmlWriter xml;
Timer suiteTimer;
+3 -3
View File
@@ -56,9 +56,9 @@ set(TESTS_DIR ${CATCH_DIR}/tests/ExtraTests)
add_executable(PrefixedMacros ${TESTS_DIR}/X01-PrefixedMacros.cpp)
target_compile_definitions(PrefixedMacros PRIVATE CATCH_CONFIG_PREFIX_ALL CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
# Macro configuration does not touch the compiled parts, so we can link
# it against the main library
target_link_libraries(PrefixedMacros Catch2WithMain)
# We want to verify that the main library can also be built with prefixed
# macros, regression test for #3087.
target_link_libraries(PrefixedMacros Catch2_buildall_interface)
add_test(NAME CATCH_CONFIG_PREFIX_ALL COMMAND PrefixedMacros -s)
set_tests_properties(CATCH_CONFIG_PREFIX_ALL
@@ -105,51 +105,6 @@ at Misc.tests.cpp:<line number>
<failure message="false != false" type="CHECK">
FAILED:
CHECK( false != false )
at Condition.tests.cpp:<line number>
</failure>
<failure message="true != true" type="CHECK">
FAILED:
CHECK( true != true )
at Condition.tests.cpp:<line number>
</failure>
<failure message="!true" type="CHECK">
FAILED:
CHECK( !true )
with expansion:
false
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(true)" type="CHECK_FALSE">
FAILED:
CHECK_FALSE( true )
with expansion:
!true
at Condition.tests.cpp:<line number>
</failure>
<failure message="!trueValue" type="CHECK">
FAILED:
CHECK( !trueValue )
with expansion:
false
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(trueValue)" type="CHECK_FALSE">
FAILED:
CHECK_FALSE( trueValue )
with expansion:
!true
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(1 == 1)" type="CHECK">
FAILED:
CHECK( !(1 == 1) )
with expansion:
false
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(1 == 1)" type="CHECK_FALSE">
FAILED:
CHECK_FALSE( 1 == 1 )
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -358,13 +313,6 @@ FAILED:
CHECK( &amp;o1 == &amp;o2 )
with expansion:
0x<hex digits> == 0x<hex digits>
at Tricky.tests.cpp:<line number>
</failure>
<failure message="o1 == o2" type="CHECK">
FAILED:
CHECK( o1 == o2 )
with expansion:
{?} == {?}
at Tricky.tests.cpp:<line number>
</failure>
</testcase>
@@ -400,12 +348,6 @@ with expansion:
2 > 10
at AssertionHandler.tests.cpp:<line number>
</failure>
<error message="foo( 2 ) == 2" type="CHECK">
FAILED:
CHECK( foo( 2 ) == 2 )
{ nested assertion failed }
at AssertionHandler.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="Assertions can be nested - REQUIRE" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
@@ -416,12 +358,6 @@ with expansion:
2 > 10
at AssertionHandler.tests.cpp:<line number>
</failure>
<error message="foo( 2 ) == 2" type="REQUIRE">
FAILED:
REQUIRE( foo( 2 ) == 2 )
{ nested assertion failed }
at AssertionHandler.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}" status="run"/>
@@ -511,13 +447,6 @@ FAILED:
with expansion:
"this string contains 'abc' as a substring" contains: "not there" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), ContainsSubstring( &quot;STRING&quot; )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), ContainsSubstring( "STRING" ) )
with expansion:
"this string contains 'abc' as a substring" contains: "STRING"
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -574,14 +503,6 @@ FAILED:
CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )
with expansion:
"this string contains 'abc' as a substring" ends with: "Substring"
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), EndsWith( &quot;this&quot;, Catch::CaseSensitive::No )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )
with expansion:
"this string contains 'abc' as a substring" ends with: "this" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -595,96 +516,6 @@ FAILED:
CHECK( data.int_seven == 6 )
with expansion:
7 == 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven == 8" type="CHECK">
FAILED:
CHECK( data.int_seven == 8 )
with expansion:
7 == 8
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven == 0" type="CHECK">
FAILED:
CHECK( data.int_seven == 0 )
with expansion:
7 == 0
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 9.11f )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 9.11f ) )
with expansion:
9.100000381f
==
Approx( 9.10999965667724609 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 9.0f )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 9.0f ) )
with expansion:
9.100000381f == Approx( 9.0 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 1 )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 1 ) )
with expansion:
9.100000381f == Approx( 1.0 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 0 )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 0 ) )
with expansion:
9.100000381f == Approx( 0.0 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.double_pi == Approx( 3.1415 )" type="CHECK">
FAILED:
CHECK( data.double_pi == Approx( 3.1415 ) )
with expansion:
3.14159265350000005
==
Approx( 3.14150000000000018 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello == &quot;goodbye&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello == "goodbye" )
with expansion:
"hello" == "goodbye"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello == &quot;hell&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello == "hell" )
with expansion:
"hello" == "hell"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello == &quot;hello1&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello == "hello1" )
with expansion:
"hello" == "hello1"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello.size() == 6" type="CHECK">
FAILED:
CHECK( data.str_hello.size() == 6 )
with expansion:
5 == 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="x == Approx( 1.301 )" type="CHECK">
FAILED:
CHECK( x == Approx( 1.301 ) )
with expansion:
1.30000000000000027
==
Approx( 1.30099999999999993 )
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -697,14 +528,6 @@ FAILED:
with expansion:
"this string contains 'abc' as a substring" equals: "this string contains
'ABC' as a substring"
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), Equals( &quot;something else&quot;, Catch::CaseSensitive::No )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), Equals( "something else", Catch::CaseSensitive::No ) )
with expansion:
"this string contains 'abc' as a substring" equals: "something else" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -713,11 +536,6 @@ at Matchers.tests.cpp:<line number>
<failure message="doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }" type="CHECK_THROWS_MATCHES">
FAILED:
CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } )
at Matchers.tests.cpp:<line number>
</failure>
<failure message="doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }" type="REQUIRE_THROWS_MATCHES">
FAILED:
REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } )
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -726,12 +544,6 @@ at Matchers.tests.cpp:<line number>
FAILED:
CHECK_THROWS_MATCHES( throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 } )
Unknown exception
at Matchers.tests.cpp:<line number>
</error>
<error message="throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 }" type="REQUIRE_THROWS_MATCHES">
FAILED:
REQUIRE_THROWS_MATCHES( throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 } )
Unknown exception
at Matchers.tests.cpp:<line number>
</error>
</testcase>
@@ -741,13 +553,6 @@ FAILED:
CHECK_THROWS_MATCHES( throwsSpecialException( 3 ), SpecialException, ExceptionMatcher{ 1 } )
with expansion:
SpecialException::what special exception has value of 1
at Matchers.tests.cpp:<line number>
</failure>
<failure message="throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 }" type="REQUIRE_THROWS_MATCHES">
FAILED:
REQUIRE_THROWS_MATCHES( throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 } )
with expansion:
SpecialException::what special exception has value of 1
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -764,17 +569,6 @@ at Matchers.tests.cpp:<line number>
FAILED:
CHECK_THROWS_AS( thisThrows(), std::string )
expected exception
at Exception.tests.cpp:<line number>
</error>
<failure message="thisDoesntThrow(), std::domain_error" type="CHECK_THROWS_AS">
FAILED:
CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error )
at Exception.tests.cpp:<line number>
</failure>
<error message="thisThrows()" type="CHECK_NOTHROW">
FAILED:
CHECK_NOTHROW( thisThrows() )
expected exception
at Exception.tests.cpp:<line number>
</error>
</testcase>
@@ -792,12 +586,6 @@ FAILED:
Throw a Catch::TestFailureException
at AssertionHandler.tests.cpp:<line number>
</failure>
<error message="do_fail()" type="CHECK_NOTHROW">
FAILED:
CHECK_NOTHROW( do_fail() )
{ nested assertion failed }
at AssertionHandler.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="FAIL does not require an argument" time="{duration}" status="run">
<failure type="FAIL">
@@ -931,16 +719,6 @@ with expansion:
2 == 1
this message may be logged later
this message should be logged
at Message.tests.cpp:<line number>
</failure>
<failure message="a == 0" type="CHECK">
FAILED:
CHECK( a == 0 )
with expansion:
2 == 0
this message may be logged later
this message should be logged
and this, but later
at Message.tests.cpp:<line number>
</failure>
</testcase>
@@ -971,38 +749,6 @@ FAILED:
CHECK( data.int_seven != 7 )
with expansion:
7 != 7
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one != Approx( 9.1f )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one != Approx( 9.1f ) )
with expansion:
9.100000381f
!=
Approx( 9.10000038146972656 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.double_pi != Approx( 3.1415926535 )" type="CHECK">
FAILED:
CHECK( data.double_pi != Approx( 3.1415926535 ) )
with expansion:
3.14159265350000005
!=
Approx( 3.14159265350000005 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello != &quot;hello&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello != "hello" )
with expansion:
"hello" != "hello"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello.size() != 5" type="CHECK">
FAILED:
CHECK( data.str_hello.size() != 5 )
with expansion:
5 != 5
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -1127,132 +873,6 @@ FAILED:
CHECK( data.int_seven > 7 )
with expansion:
7 > 7
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; 7" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; 7 )
with expansion:
7 &lt; 7
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven > 8" type="CHECK">
FAILED:
CHECK( data.int_seven > 8 )
with expansion:
7 > 8
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; 6" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; 6 )
with expansion:
7 &lt; 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; 0" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; 0 )
with expansion:
7 &lt; 0
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; -1" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; -1 )
with expansion:
7 &lt; -1
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven >= 8" type="CHECK">
FAILED:
CHECK( data.int_seven >= 8 )
with expansion:
7 >= 8
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt;= 6" type="CHECK">
FAILED:
CHECK( data.int_seven &lt;= 6 )
with expansion:
7 &lt;= 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one &lt; 9" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one &lt; 9 )
with expansion:
9.100000381f &lt; 9
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one > 10" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one > 10 )
with expansion:
9.100000381f > 10
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one > 9.2" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one > 9.2 )
with expansion:
9.100000381f > 9.19999999999999929
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello > &quot;hello&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello > "hello" )
with expansion:
"hello" > "hello"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt; &quot;hello&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt; "hello" )
with expansion:
"hello" &lt; "hello"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello > &quot;hellp&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello > "hellp" )
with expansion:
"hello" > "hellp"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello > &quot;z&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello > "z" )
with expansion:
"hello" > "z"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt; &quot;hellm&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt; "hellm" )
with expansion:
"hello" &lt; "hellm"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt; &quot;a&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt; "a" )
with expansion:
"hello" &lt; "a"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello >= &quot;z&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello >= "z" )
with expansion:
"hello" >= "z"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt;= &quot;a&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt;= "a" )
with expansion:
"hello" &lt;= "a"
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -1382,22 +1002,6 @@ FAILED:
with expansion:
"this string contains 'abc' as a substring" matches "this STRING contains
'abc' as a substring" case sensitively
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), Matches( &quot;contains 'abc' as a substring&quot; )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), Matches( "contains 'abc' as a substring" ) )
with expansion:
"this string contains 'abc' as a substring" matches "contains 'abc' as a
substring" case sensitively
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), Matches( &quot;this string contains 'abc' as a&quot; )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), Matches( "this string contains 'abc' as a" ) )
with expansion:
"this string contains 'abc' as a substring" matches "this string contains
'abc' as a" case sensitively
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1462,12 +1066,6 @@ at Matchers.tests.cpp:<line number>
FAILED:
CHECK( false )
This will be reported multiple times
at Message.tests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
FAILED:
CHECK( false )
This will be reported multiple times
at Message.tests.cpp:<line number>
</failure>
</testcase>
@@ -1512,14 +1110,6 @@ FAILED:
CHECK_THAT( testStringForMatching(), StartsWith( "This String" ) )
with expansion:
"this string contains 'abc' as a substring" starts with: "This String"
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), StartsWith( &quot;string&quot;, Catch::CaseSensitive::No )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), StartsWith( "string", Catch::CaseSensitive::No ) )
with expansion:
"this string contains 'abc' as a substring" starts with: "string" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1873,13 +1463,6 @@ FAILED:
CHECK_THAT( v, VectorContains( -1 ) )
with expansion:
{ 1, 2, 3 } Contains: -1
at Matchers.tests.cpp:<line number>
</failure>
<failure message="empty, VectorContains( 1 )" type="CHECK_THAT">
FAILED:
CHECK_THAT( empty, VectorContains( 1 ) )
with expansion:
{ } Contains: 1
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1889,13 +1472,6 @@ FAILED:
CHECK_THAT( empty, Contains( v ) )
with expansion:
{ } Contains: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="v, Contains( v2 )" type="CHECK_THAT">
FAILED:
CHECK_THAT( v, Contains( v2 ) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2, 4 }
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1905,27 +1481,6 @@ FAILED:
CHECK_THAT( v, Equals( v2 ) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="v2, Equals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( v2, Equals( v ) )
with expansion:
{ 1, 2 } Equals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="empty, Equals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( empty, Equals( v ) )
with expansion:
{ } Equals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="v, Equals( empty )" type="CHECK_THAT">
FAILED:
CHECK_THAT( v, Equals( empty ) )
with expansion:
{ 1, 2, 3 } Equals: { }
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1935,27 +1490,6 @@ FAILED:
CHECK_THAT( v, UnorderedEquals( empty ) )
with expansion:
{ 1, 2, 3 } UnorderedEquals: { }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="empty, UnorderedEquals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( empty, UnorderedEquals( v ) )
with expansion:
{ } UnorderedEquals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="permuted, UnorderedEquals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( permuted, UnorderedEquals( v ) )
with expansion:
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="permuted, UnorderedEquals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( permuted, UnorderedEquals( v ) )
with expansion:
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -2063,11 +1597,6 @@ at Misc.tests.cpp:<line number>
<skipped type="SKIP">
SKIPPED
skipping because answer = 41
at Skip.tests.cpp:<line number>
</skipped>
<skipped type="SKIP">
SKIPPED
skipping because answer = 43
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
@@ -2086,28 +1615,12 @@ FAILED:
CHECK( 3 == 4 )
at Skip.tests.cpp:<line number>
</failure>
<skipped type="SKIP">
SKIPPED
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
<testcase classname="<exe-name>.global" name="failing for some generator values causes entire test case to fail" time="{duration}" status="run">
<failure type="FAIL">
FAILED:
at Skip.tests.cpp:<line number>
</failure>
<skipped type="SKIP">
SKIPPED
at Skip.tests.cpp:<line number>
</skipped>
<failure type="FAIL">
FAILED:
at Skip.tests.cpp:<line number>
</failure>
<skipped type="SKIP">
SKIPPED
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
<testcase classname="<exe-name>.global" name="failing in some unskipped sections causes entire test case to fail/skipped" time="{duration}" status="run">
<skipped type="SKIP">
@@ -2176,46 +1689,6 @@ FAILED:
with expansion:
1 == 0
Testing if fib[0] (1) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[1] (1) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[3] (3) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[4] (5) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[6] (13) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[7] (21) is even
at Misc.tests.cpp:<line number>
</failure>
</testcase>
@@ -2360,15 +1833,6 @@ Count 1 to 3...
1
2
3
at Message.tests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
FAILED:
CHECK( false )
Count 4 to 6...
4
5
6
at Message.tests.cpp:<line number>
</failure>
</testcase>
@@ -104,51 +104,6 @@ at Misc.tests.cpp:<line number>
<failure message="false != false" type="CHECK">
FAILED:
CHECK( false != false )
at Condition.tests.cpp:<line number>
</failure>
<failure message="true != true" type="CHECK">
FAILED:
CHECK( true != true )
at Condition.tests.cpp:<line number>
</failure>
<failure message="!true" type="CHECK">
FAILED:
CHECK( !true )
with expansion:
false
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(true)" type="CHECK_FALSE">
FAILED:
CHECK_FALSE( true )
with expansion:
!true
at Condition.tests.cpp:<line number>
</failure>
<failure message="!trueValue" type="CHECK">
FAILED:
CHECK( !trueValue )
with expansion:
false
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(trueValue)" type="CHECK_FALSE">
FAILED:
CHECK_FALSE( trueValue )
with expansion:
!true
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(1 == 1)" type="CHECK">
FAILED:
CHECK( !(1 == 1) )
with expansion:
false
at Condition.tests.cpp:<line number>
</failure>
<failure message="!(1 == 1)" type="CHECK_FALSE">
FAILED:
CHECK_FALSE( 1 == 1 )
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -357,13 +312,6 @@ FAILED:
CHECK( &amp;o1 == &amp;o2 )
with expansion:
0x<hex digits> == 0x<hex digits>
at Tricky.tests.cpp:<line number>
</failure>
<failure message="o1 == o2" type="CHECK">
FAILED:
CHECK( o1 == o2 )
with expansion:
{?} == {?}
at Tricky.tests.cpp:<line number>
</failure>
</testcase>
@@ -399,12 +347,6 @@ with expansion:
2 > 10
at AssertionHandler.tests.cpp:<line number>
</failure>
<error message="foo( 2 ) == 2" type="CHECK">
FAILED:
CHECK( foo( 2 ) == 2 )
{ nested assertion failed }
at AssertionHandler.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="Assertions can be nested - REQUIRE" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
@@ -415,12 +357,6 @@ with expansion:
2 > 10
at AssertionHandler.tests.cpp:<line number>
</failure>
<error message="foo( 2 ) == 2" type="REQUIRE">
FAILED:
REQUIRE( foo( 2 ) == 2 )
{ nested assertion failed }
at AssertionHandler.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}" status="run"/>
@@ -510,13 +446,6 @@ FAILED:
with expansion:
"this string contains 'abc' as a substring" contains: "not there" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), ContainsSubstring( &quot;STRING&quot; )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), ContainsSubstring( "STRING" ) )
with expansion:
"this string contains 'abc' as a substring" contains: "STRING"
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -573,14 +502,6 @@ FAILED:
CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )
with expansion:
"this string contains 'abc' as a substring" ends with: "Substring"
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), EndsWith( &quot;this&quot;, Catch::CaseSensitive::No )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )
with expansion:
"this string contains 'abc' as a substring" ends with: "this" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -594,96 +515,6 @@ FAILED:
CHECK( data.int_seven == 6 )
with expansion:
7 == 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven == 8" type="CHECK">
FAILED:
CHECK( data.int_seven == 8 )
with expansion:
7 == 8
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven == 0" type="CHECK">
FAILED:
CHECK( data.int_seven == 0 )
with expansion:
7 == 0
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 9.11f )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 9.11f ) )
with expansion:
9.100000381f
==
Approx( 9.10999965667724609 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 9.0f )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 9.0f ) )
with expansion:
9.100000381f == Approx( 9.0 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 1 )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 1 ) )
with expansion:
9.100000381f == Approx( 1.0 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one == Approx( 0 )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one == Approx( 0 ) )
with expansion:
9.100000381f == Approx( 0.0 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.double_pi == Approx( 3.1415 )" type="CHECK">
FAILED:
CHECK( data.double_pi == Approx( 3.1415 ) )
with expansion:
3.14159265350000005
==
Approx( 3.14150000000000018 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello == &quot;goodbye&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello == "goodbye" )
with expansion:
"hello" == "goodbye"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello == &quot;hell&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello == "hell" )
with expansion:
"hello" == "hell"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello == &quot;hello1&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello == "hello1" )
with expansion:
"hello" == "hello1"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello.size() == 6" type="CHECK">
FAILED:
CHECK( data.str_hello.size() == 6 )
with expansion:
5 == 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="x == Approx( 1.301 )" type="CHECK">
FAILED:
CHECK( x == Approx( 1.301 ) )
with expansion:
1.30000000000000027
==
Approx( 1.30099999999999993 )
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -696,14 +527,6 @@ FAILED:
with expansion:
"this string contains 'abc' as a substring" equals: "this string contains
'ABC' as a substring"
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), Equals( &quot;something else&quot;, Catch::CaseSensitive::No )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), Equals( "something else", Catch::CaseSensitive::No ) )
with expansion:
"this string contains 'abc' as a substring" equals: "something else" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -712,11 +535,6 @@ at Matchers.tests.cpp:<line number>
<failure message="doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }" type="CHECK_THROWS_MATCHES">
FAILED:
CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } )
at Matchers.tests.cpp:<line number>
</failure>
<failure message="doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }" type="REQUIRE_THROWS_MATCHES">
FAILED:
REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } )
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -725,12 +543,6 @@ at Matchers.tests.cpp:<line number>
FAILED:
CHECK_THROWS_MATCHES( throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 } )
Unknown exception
at Matchers.tests.cpp:<line number>
</error>
<error message="throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 }" type="REQUIRE_THROWS_MATCHES">
FAILED:
REQUIRE_THROWS_MATCHES( throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 } )
Unknown exception
at Matchers.tests.cpp:<line number>
</error>
</testcase>
@@ -740,13 +552,6 @@ FAILED:
CHECK_THROWS_MATCHES( throwsSpecialException( 3 ), SpecialException, ExceptionMatcher{ 1 } )
with expansion:
SpecialException::what special exception has value of 1
at Matchers.tests.cpp:<line number>
</failure>
<failure message="throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 }" type="REQUIRE_THROWS_MATCHES">
FAILED:
REQUIRE_THROWS_MATCHES( throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 } )
with expansion:
SpecialException::what special exception has value of 1
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -763,17 +568,6 @@ at Matchers.tests.cpp:<line number>
FAILED:
CHECK_THROWS_AS( thisThrows(), std::string )
expected exception
at Exception.tests.cpp:<line number>
</error>
<failure message="thisDoesntThrow(), std::domain_error" type="CHECK_THROWS_AS">
FAILED:
CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error )
at Exception.tests.cpp:<line number>
</failure>
<error message="thisThrows()" type="CHECK_NOTHROW">
FAILED:
CHECK_NOTHROW( thisThrows() )
expected exception
at Exception.tests.cpp:<line number>
</error>
</testcase>
@@ -791,12 +585,6 @@ FAILED:
Throw a Catch::TestFailureException
at AssertionHandler.tests.cpp:<line number>
</failure>
<error message="do_fail()" type="CHECK_NOTHROW">
FAILED:
CHECK_NOTHROW( do_fail() )
{ nested assertion failed }
at AssertionHandler.tests.cpp:<line number>
</error>
</testcase>
<testcase classname="<exe-name>.global" name="FAIL does not require an argument" time="{duration}" status="run">
<failure type="FAIL">
@@ -930,16 +718,6 @@ with expansion:
2 == 1
this message may be logged later
this message should be logged
at Message.tests.cpp:<line number>
</failure>
<failure message="a == 0" type="CHECK">
FAILED:
CHECK( a == 0 )
with expansion:
2 == 0
this message may be logged later
this message should be logged
and this, but later
at Message.tests.cpp:<line number>
</failure>
</testcase>
@@ -970,38 +748,6 @@ FAILED:
CHECK( data.int_seven != 7 )
with expansion:
7 != 7
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one != Approx( 9.1f )" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one != Approx( 9.1f ) )
with expansion:
9.100000381f
!=
Approx( 9.10000038146972656 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.double_pi != Approx( 3.1415926535 )" type="CHECK">
FAILED:
CHECK( data.double_pi != Approx( 3.1415926535 ) )
with expansion:
3.14159265350000005
!=
Approx( 3.14159265350000005 )
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello != &quot;hello&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello != "hello" )
with expansion:
"hello" != "hello"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello.size() != 5" type="CHECK">
FAILED:
CHECK( data.str_hello.size() != 5 )
with expansion:
5 != 5
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -1126,132 +872,6 @@ FAILED:
CHECK( data.int_seven > 7 )
with expansion:
7 > 7
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; 7" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; 7 )
with expansion:
7 &lt; 7
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven > 8" type="CHECK">
FAILED:
CHECK( data.int_seven > 8 )
with expansion:
7 > 8
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; 6" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; 6 )
with expansion:
7 &lt; 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; 0" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; 0 )
with expansion:
7 &lt; 0
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt; -1" type="CHECK">
FAILED:
CHECK( data.int_seven &lt; -1 )
with expansion:
7 &lt; -1
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven >= 8" type="CHECK">
FAILED:
CHECK( data.int_seven >= 8 )
with expansion:
7 >= 8
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.int_seven &lt;= 6" type="CHECK">
FAILED:
CHECK( data.int_seven &lt;= 6 )
with expansion:
7 &lt;= 6
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one &lt; 9" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one &lt; 9 )
with expansion:
9.100000381f &lt; 9
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one > 10" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one > 10 )
with expansion:
9.100000381f > 10
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.float_nine_point_one > 9.2" type="CHECK">
FAILED:
CHECK( data.float_nine_point_one > 9.2 )
with expansion:
9.100000381f > 9.19999999999999929
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello > &quot;hello&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello > "hello" )
with expansion:
"hello" > "hello"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt; &quot;hello&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt; "hello" )
with expansion:
"hello" &lt; "hello"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello > &quot;hellp&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello > "hellp" )
with expansion:
"hello" > "hellp"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello > &quot;z&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello > "z" )
with expansion:
"hello" > "z"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt; &quot;hellm&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt; "hellm" )
with expansion:
"hello" &lt; "hellm"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt; &quot;a&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt; "a" )
with expansion:
"hello" &lt; "a"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello >= &quot;z&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello >= "z" )
with expansion:
"hello" >= "z"
at Condition.tests.cpp:<line number>
</failure>
<failure message="data.str_hello &lt;= &quot;a&quot;" type="CHECK">
FAILED:
CHECK( data.str_hello &lt;= "a" )
with expansion:
"hello" &lt;= "a"
at Condition.tests.cpp:<line number>
</failure>
</testcase>
@@ -1381,22 +1001,6 @@ FAILED:
with expansion:
"this string contains 'abc' as a substring" matches "this STRING contains
'abc' as a substring" case sensitively
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), Matches( &quot;contains 'abc' as a substring&quot; )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), Matches( "contains 'abc' as a substring" ) )
with expansion:
"this string contains 'abc' as a substring" matches "contains 'abc' as a
substring" case sensitively
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), Matches( &quot;this string contains 'abc' as a&quot; )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), Matches( "this string contains 'abc' as a" ) )
with expansion:
"this string contains 'abc' as a substring" matches "this string contains
'abc' as a" case sensitively
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1461,12 +1065,6 @@ at Matchers.tests.cpp:<line number>
FAILED:
CHECK( false )
This will be reported multiple times
at Message.tests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
FAILED:
CHECK( false )
This will be reported multiple times
at Message.tests.cpp:<line number>
</failure>
</testcase>
@@ -1511,14 +1109,6 @@ FAILED:
CHECK_THAT( testStringForMatching(), StartsWith( "This String" ) )
with expansion:
"this string contains 'abc' as a substring" starts with: "This String"
at Matchers.tests.cpp:<line number>
</failure>
<failure message="testStringForMatching(), StartsWith( &quot;string&quot;, Catch::CaseSensitive::No )" type="CHECK_THAT">
FAILED:
CHECK_THAT( testStringForMatching(), StartsWith( "string", Catch::CaseSensitive::No ) )
with expansion:
"this string contains 'abc' as a substring" starts with: "string" (case
insensitive)
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1872,13 +1462,6 @@ FAILED:
CHECK_THAT( v, VectorContains( -1 ) )
with expansion:
{ 1, 2, 3 } Contains: -1
at Matchers.tests.cpp:<line number>
</failure>
<failure message="empty, VectorContains( 1 )" type="CHECK_THAT">
FAILED:
CHECK_THAT( empty, VectorContains( 1 ) )
with expansion:
{ } Contains: 1
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1888,13 +1471,6 @@ FAILED:
CHECK_THAT( empty, Contains( v ) )
with expansion:
{ } Contains: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="v, Contains( v2 )" type="CHECK_THAT">
FAILED:
CHECK_THAT( v, Contains( v2 ) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2, 4 }
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1904,27 +1480,6 @@ FAILED:
CHECK_THAT( v, Equals( v2 ) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="v2, Equals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( v2, Equals( v ) )
with expansion:
{ 1, 2 } Equals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="empty, Equals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( empty, Equals( v ) )
with expansion:
{ } Equals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="v, Equals( empty )" type="CHECK_THAT">
FAILED:
CHECK_THAT( v, Equals( empty ) )
with expansion:
{ 1, 2, 3 } Equals: { }
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -1934,27 +1489,6 @@ FAILED:
CHECK_THAT( v, UnorderedEquals( empty ) )
with expansion:
{ 1, 2, 3 } UnorderedEquals: { }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="empty, UnorderedEquals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( empty, UnorderedEquals( v ) )
with expansion:
{ } UnorderedEquals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="permuted, UnorderedEquals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( permuted, UnorderedEquals( v ) )
with expansion:
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
<failure message="permuted, UnorderedEquals( v )" type="CHECK_THAT">
FAILED:
CHECK_THAT( permuted, UnorderedEquals( v ) )
with expansion:
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
at Matchers.tests.cpp:<line number>
</failure>
</testcase>
@@ -2062,11 +1596,6 @@ at Misc.tests.cpp:<line number>
<skipped type="SKIP">
SKIPPED
skipping because answer = 41
at Skip.tests.cpp:<line number>
</skipped>
<skipped type="SKIP">
SKIPPED
skipping because answer = 43
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
@@ -2085,28 +1614,12 @@ FAILED:
CHECK( 3 == 4 )
at Skip.tests.cpp:<line number>
</failure>
<skipped type="SKIP">
SKIPPED
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
<testcase classname="<exe-name>.global" name="failing for some generator values causes entire test case to fail" time="{duration}" status="run">
<failure type="FAIL">
FAILED:
at Skip.tests.cpp:<line number>
</failure>
<skipped type="SKIP">
SKIPPED
at Skip.tests.cpp:<line number>
</skipped>
<failure type="FAIL">
FAILED:
at Skip.tests.cpp:<line number>
</failure>
<skipped type="SKIP">
SKIPPED
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
<testcase classname="<exe-name>.global" name="failing in some unskipped sections causes entire test case to fail/skipped" time="{duration}" status="run">
<skipped type="SKIP">
@@ -2175,46 +1688,6 @@ FAILED:
with expansion:
1 == 0
Testing if fib[0] (1) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[1] (1) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[3] (3) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[4] (5) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[6] (13) is even
at Misc.tests.cpp:<line number>
</failure>
<failure message="( fib[i] % 2 ) == 0" type="CHECK">
FAILED:
CHECK( ( fib[i] % 2 ) == 0 )
with expansion:
1 == 0
Testing if fib[7] (21) is even
at Misc.tests.cpp:<line number>
</failure>
</testcase>
@@ -2359,15 +1832,6 @@ Count 1 to 3...
1
2
3
at Message.tests.cpp:<line number>
</failure>
<failure message="false" type="CHECK">
FAILED:
CHECK( false )
Count 4 to 6...
4
5
6
at Message.tests.cpp:<line number>
</failure>
</testcase>
@@ -54,7 +54,7 @@ TEST_CASE( "The default listing implementation write to provided stream",
SECTION( "Listing tags" ) {
std::vector<Catch::TagInfo> tags(1);
tags[0].add("fakeTag"_catch_sr);
Catch::defaultListTags(sstream.stream(), tags, false);
Catch::defaultListTags(sstream.stream(), tags, false, Catch::Verbosity::Normal);
auto listingString = sstream.str();
REQUIRE_THAT(listingString, ContainsSubstring("[fakeTag]"s));
@@ -87,7 +87,7 @@ TEST_CASE( "The default listing implementation write to provided stream",
std::vector<Catch::ListenerDescription> listeners(
{ { "fakeListener"_catch_sr, "fake description" } } );
Catch::defaultListListeners( sstream.stream(), listeners );
Catch::defaultListListeners( sstream.stream(), listeners, Catch::Verbosity::Normal );
auto listingString = sstream.str();
REQUIRE_THAT( listingString,
ContainsSubstring( "fakeListener"s ) &&
@@ -381,6 +381,81 @@ TEST_CASE( "TextFlow::AnsiSkippingString substrings properly",
}
}
TEST_CASE( "TextFlow::AnsiSkippingString counts UTF-8 codepoints",
"[TextFlow][ansiskippingstring][approvals]" ) {
SECTION( "2-byte codepoints" ) {
AnsiSkippingString str( "\xC3\xA4\xC3\xB6\xC3\xBC" ); // äöü
CHECK( str.size() == 3 );
}
SECTION( "3-byte codepoints" ) {
AnsiSkippingString str( "\xE4\xB8\xAD\xE6\x96\x87" ); // 中文
CHECK( str.size() == 2 );
}
SECTION( "4-byte codepoints" ) {
// U+1F600 U+1F60E
AnsiSkippingString str( "\xF0\x9F\x98\x80\xF0\x9F\x98\x8E" );
CHECK( str.size() == 2 );
}
SECTION( "mixed ASCII and UTF-8" ) {
AnsiSkippingString str( "a\xC3\xA4" "b" ); // aäb
CHECK( str.size() == 3 );
}
SECTION( "UTF-8 with ANSI escapes" ) {
AnsiSkippingString str( "\033[31m\xC3\xA4\xC3\xB6\xC3\xBC\033[0m" );
CHECK( str.size() == 3 );
}
}
TEST_CASE( "TextFlow::AnsiSkippingString iterates UTF-8 codepoints",
"[TextFlow][ansiskippingstring][approvals]" ) {
// "aäb" = 'a' (0x61), 'ä' (0xC3 0xA4), 'b' (0x62)
std::string text = "a\xC3\xA4" "b";
AnsiSkippingString str( text );
SECTION( "forward iteration has correct count" ) {
int count = 0;
for ( auto it = str.begin(); it != str.end(); ++it ) {
++count;
}
CHECK( count == 3 );
}
SECTION( "backward iteration has correct count" ) {
auto it = str.end();
int count = 0;
while ( it != str.begin() ) {
--it;
++count;
}
CHECK( count == 3 );
}
SECTION( "substring preserves full UTF-8 bytes" ) {
auto a = str.begin();
auto b = str.begin();
++b; // past 'a'
++b; // past 'ä'
CHECK( str.substring( a, b ) == "a\xC3\xA4" );
}
}
TEST_CASE( "TextFlow::Column wraps UTF-8 text correctly",
"[TextFlow][column][approvals]" ) {
// "äöü äöü äöü" = 11 codepoints, 17 bytes
Column col( "\xC3\xA4\xC3\xB6\xC3\xBC \xC3\xA4\xC3\xB6\xC3\xBC \xC3\xA4\xC3\xB6\xC3\xBC" );
SECTION( "width=8" ) {
col.width( 8 );
// 7 visible codepoints "äöü äöü" fit, then wrap
REQUIRE( as_written( col ) ==
"\xC3\xA4\xC3\xB6\xC3\xBC \xC3\xA4\xC3\xB6\xC3\xBC\n"
"\xC3\xA4\xC3\xB6\xC3\xBC" );
}
SECTION( "width=80" ) {
col.width( 80 );
REQUIRE( as_written( col ) ==
"\xC3\xA4\xC3\xB6\xC3\xBC \xC3\xA4\xC3\xB6\xC3\xBC \xC3\xA4\xC3\xB6\xC3\xBC" );
}
}
TEST_CASE( "TextFlow::Column skips ansi escape sequences",
"[TextFlow][column][approvals]" ) {
std::string text = "\033[38;2;98;174;239m\033[38;2;198;120;221mThe quick brown \033[38;2;198;120;221mfox jumped over the lazy dog\033[0m";
+10 -9
View File
@@ -6,15 +6,6 @@
// SPDX-License-Identifier: BSL-1.0
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
// Wdouble-promotion is not supported until 3.8
# if (__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ > 7)
# pragma clang diagnostic ignored "-Wdouble-promotion"
# endif
#endif
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
@@ -24,6 +15,16 @@ using Catch::Approx;
#include <limits>
#include <cstdint>
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
// Wdouble-promotion is not supported until 3.8
# if ( __clang_major__ > 3 ) || \
( __clang_major__ == 3 && __clang_minor__ > 7 )
# pragma clang diagnostic ignored "-Wdouble-promotion"
# endif
#endif
namespace {
struct TestData {
@@ -281,6 +281,11 @@ TEST_CASE("#1913 - GENERATEs can share a line", "[regression][generators]") {
REQUIRE(i != j);
}
#if defined( __clang__ )
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif
namespace {
class test_generator : public Catch::Generators::IGenerator<int> {
public:
@@ -306,6 +311,10 @@ namespace {
} // namespace
#if defined( __clang__ )
# pragma clang diagnostic pop
#endif
TEST_CASE( "#2615 - Throwing in constructor generator fails test case but does not abort",
"[!shouldfail][regression][generators]" ) {
// this should fail the test case, but not abort the application