Squashed 'externals/catch/' changes from ab6c7375b..53d0d913a

53d0d913a v3.5.0
1648c30ec Look just for 'Catch2 X.Y.Z' in doc placeholder update
d4e9fb8aa Highlight that SECTIONs rerun the entire test case from beginning (#2749)
b606bc280 Remove obsolete section in limitations.md
4ab0af8ba Fix minor typos in documentation (#2769)
b7d70ddcd Ensure we always read 32 bit seed from std::random_device
a6f22c516 Remove static instance of std::random_device in Benchmark::analyse_samples
1887d42e3 Use our PCG32 RNG instead of mt19937 in Benchmark::analyse_samples
1774dbfd5 Make it clearer that the JSON reporter is WIP
cb07ff9a7 Fix uniform_floating_point_distribution for unit ranges
ae4fe16b8 Make the user-facing random Generators reproducible
28c66fdc5 Make uniform_floating_point_distribution reproducible
ed9d672b5 Add uniform_integer_distribution
04a829b0e Add helpers for implementing uniform integer distribution
ab1b079e4 Add uniform_floating_point_distribution
d139b4ff7 Add implementation of helpers for uniform float distribution
bfd9f0f5a Move nextafter polyfill to polyfills.hpp
9a1e73568 Add test showing literals and complex generators in one GENERATE
21d2da23b Fix typo in tostring.md
d1d7414eb Always run apt-get update before apt-get install
dacbf4fd6 Drop VS 2017 support
0520ff443 [DOC] Replaced broken link (fixes #2770)
4a7be16c8 Fix compilation on Xbox platforms
32d9ae24b JSONWriter deals in StringRefs instead of std::strings
de7ba4e88 fn need to be in parenthesis
733b901dd Fix special character escaping in JsonWriter
7bf136b50 Add JSON reporter (#2706)
2c68a0d05 lifted suggested version
01cac90c6 Bump up actions/checkout version to v4 (#2760)
b735dfce2 Increase build parallelism on macOS (#2759)
caffe79a3 Fix missing include in catch_message.hpp
a8cf3e671 Mark `CATCH_CONFIG_` options as advanced
79d39a195 Fix tests for C++23's multi-arg index operator
6ebc013b8 Fix UDL definitions for C++23
966d36155 Improve formatting of test specification docs
766541d12 why-catch.md: Add JetBrains survey link
7b793314e Catch.cmake: Support CMake multi-config with PRE_TEST discovery mode (#2739)
0fb817e41 fix some bugprone-macro-parentheses warnings
f161110be Merge pull request #2747 from xandox/devel
db495acdb correct argument references in CatchAddTests.cmake
9c541ca72 Add test for multiple streaming parts in UNSCOPED_INFO
92672591c Make jackknife TU-local to stats.cpp
56fcd584c Make directCompare TU-local to stats.cpp
aafe09bc1 Update meson.build to fix #2722 (#2742)
47a2c9693 Reduce the number of templates in Benchmarking
fb96279ae Remove superfluous stdlib includes from catch_benchmark.hpp
e14a08d73 Remove unused typedef from Benchmark::Environment
9bba07cb8 Replace vector iterator args in benchmarks with ptr args
b4ffba508 Update sample output in docs/benchmarks.md
3a5cde55b implement stringify for std::nullopt_t
2a19ae16b Rewrite commandline test spec docs
f24d39e42 Support C arrays and ADL ranges in from_range generator
85eb4652b Add nice license headers to files in examples/ and fuzzing/
5bba3e403 Edited amalgamated file generator, to block REUSE from getting confused
e09de7222 Small cleanup in XML reporter
a64ff326b Change 'estimated' to 'est run time' in console reporter output
ad5646347 Flush stream after benchmarkStarting in ConsoleReporter
9538d1600 Mention missing catch_user_config.hpp in FAQ
a94bee771 Add missing line for v3.4.0 to ToC in release-notes.md
d7304f0c4 Constify section hints in static-analysis mode
cd60a0301 Assert Info reset need to also reset result disposition to normal to handle uncaught exception correctly (#2723)
b593be211 Always default empty destructors
ed4acded3 Don't define tryTranslators function if exception are disabled
4acc51828 Introduce CATCH_CONFIG_PREFIX_MESSAGES to only prefix a few logging related macros. (#2544)
6e79e682b v3.4.0
683c85772 Clean up explanation in tests
1b049bdba 2 more TEST_CASEs to DiscoverTests/register-tests.cpp
e4b16053a Escape Catch2 test names in catch_discover_tests tests
42ee66b5e Fix handling of semicolon and backslash characters in CMake test discovery (#2676)
a0c6a2846 Fix possible FP in catch_discover_tests tests
c8363143e Add test scaffolding for catch_discover_tests
7a52dfa77 Fix typo in cross-docs links
913173663 Bazel support: Update skylib
0631b607e Test & document SKIP in generator constructor
dff7513b2 Static analysis cleanup in tests
bf5aa7b38 Experimental static analysis support in TEST_CASE and SECTION
dba9197ec Add new config option: STATIC_ANALYSIS_SUPPORT
f60c15364 Add macro for suppressing Wshadow
b3cf1bfb5 Avoid unused variable warning in GeneratorsImpl tests
73b93ce6b Include catch_user_config.hpp in all catch_config_* files
8008625d7 Merge pull request #2693 from Ali-Amir/u/ali/optional-meson-unit-tests
ce7b15302 Add option to disable building unit tests in Meson build file.
535205e2a Suppress -Wunused-result warning in gcc
689fdcd7d Fix some tests never being run
a153fce72 Improve error messages for TEST_CASE tag parsing errors
06c0e1cfa Merge pull request #2689 from ThePhD/fix/includes/header-exception
05d7eb5a0 🛠 Add <exception> header where strictly necessary
f53bb3ae7 meson: require version >=0.54.1
ce8a7b339 Merge pull request #2687 from ChrisThrasher/sfml
6dce539fa Add SFML to the list of open source users
5a40b2275 Update CatchConfigOptions.cmake
598895d04 Fix Wredundant-decls
0dc82e08d Move CATCH_INTERNAL_STRINGIFY macro into its own header
8ca504cbc Move AssertionResult when passing it inside RunContext
c57b5cdf4 Move-enable Catch::optional
d84777c9c Fix assertionStarting events being sent after the expr is evaluated
51fdbedd1 Internal linkage for outlier_variance
10f0a5864 Some template instantiation reductions
fe64c2892 Reduce compilation costs of benchmarks
7d07efc92 Clean up iterator usage in benchmarks
f3c678c0a Constexprify constants in estimate_clock.hpp
46539b6d9 Fix spelling
10596b227 Fix unreachable-code-return warnings
897fe2a01 cmake: Improve unreachable-code warnings
aad926baf Catch.cmake: Add new DISCOVERY_MODE option to catch_discover_tests
4e8399d83 CatchAddTests.cmake: Refactor into callable method
9a2a4eadc Bump xml-format-version in XML reporter
fb806da76 Add lineinfo to XML reporter output for INFO/WARN
50bf00e26 Fix reporter detection in catch_discover_tests
9f08097f5 Cleanup internal includes by splitting out some event structs
1f881ab46 Split ITestInvoker into its own header
c487b27d9 Reduce misc includes all around
3230760db Cleanup in translating exceptions to messages
b3ebce715 Cleanup benchmarking includes
d0f70fdfd Unify IReporterRegistry and ReporterRegistry
4f4ad8ada Sprinkle some constexpr around
5b665be64 Cut out catch_interfaces_capture.hpp include from the main include
2598116aa Mark various anonymous classes final
173aa3f1f Devirtualize Context
28437e121 Remove pointless member variable from RunContext
3c8fb6bbb Internal linkage for generator trackers
72f3ce4db Outline the actual registering of listener factories to cpp file
62167d756 Reduce internal includes
678341134 Fixed extras installation and shard impl location
7b4dd326c Remove obsolete comment in multireporter
1dfaa8abe Outline throwing of TestSkipException
ba94278bd Inline trivial function in AssertionHandler
8e5a4b6f7 Remove superfluous pointer copy in AssertionStats constructor
9b884d810 Fix refactoring
8a1b3b81c Add wxWidgets as another Open Source project using Catch
e5aabb671 Add xmlwrapp to the list of Open Source projects using Catch
3a1ef1409 Use hasMessage() instead of getMessage().empty()
13fae1e2f Move exception's translation into AssertionResultData message
3220ae6d4 Add support for the IAR compiler
0a0ebf500 Support elements without op!= in VectorEquals
69f35a5ac Bazel support: Update skylib version
3f0283de7 v3.3.2
6fbb3f072 Add IsNaN matcher
9ff3cde87 Simplify test name creation for list-templated test cases
4d802ca58 Use StringRef UDL in more preprocessor-generated strings
13711be7c Use StringRef UDL for generated generator names
27ba26f74 Merge pull request #2643 from kisielk/patch-1
a209bcfb5 Update build instructions in contributing.md
584973a48 Early evaluate line loc in NameAndLoc::operator==
4f7c8cb28 Avoid copying NameAndLocationRef when passed as argument
e1dbad4c9 Inline StringRef::operator==
2befd98da Inline some non-virtual functions in ITracker and TrackerContext
00f259aeb Move captured output into TestCaseStats when sending testCaseEnded
fed143624 Avoid allocating trimmed name for SectionTracker
0477326ad Directly construct empty string for invalid SectionInfo
f04c93462 Small refactoring in AssertionResult
1af351cea Remove unused TrackerContext::endRun function
dcc9fa3f3 Use StringRef UDL for more string literals when expanding macros
bf6a15a69 Rewrite -# docs
6135a78c3 Don't insert the foo part of [.foo] tag twice when parsing test spec
e8ba329b6 Add support for iterator+sentinel pairs in Contains matcher
4aa88299a Preconstruct error message in RunContext::handleIncomplete
4ff9be3bc cmake-integration.md: Use "tests" as test target name in all examples.
76cdaa3b5 Merge pull request #2637 from jbadwaik/nvhpc_unused_warning
644294df6 Suppress declared_but_not_referenced warning for NVHPC
cefa8fcf3 Enable use of UnorderedRangeEquals with iterator+sentinel pairs
772fa3f79 Add Catch::Detail::is_permutation that supports sentinels
f3c0a3cd0 Fix RangeEquals matcher to handle iterator + sentinel ranges
42d9d4533 Add test for empty result of filter generator
618d44c44 Update docs about thread safe assertions
388f7e173 Cleanup unneeded allocations from reporters
2ab20a0e0 v3.3.1
60264b880 Avoid copying strings in sonarqube when sorting tests by file
65ffee518 Don't take ownership of SECTION's name for inactive sections
43f02027e Avoid allocations when looking for trackers
906552f8c Clean up extraneous copies in Messages
356dfc143 Move name and sample analysis in benchmarks into BenchmarkStats
e5d1eb757 Move AssertionResultData into AssertionResult in RunContext
2403f5620 Move SectionEndInfo into sectionEnded call in SECTION's destructor
d58491c85 Move sectionInfo into sectionEndInfo when SECTION ends
c837cb4a8 v3.3.0
8359a6b24 Stop exceptions in generator constructors from aborting the binary
adf43494e Add missing version information to matchers.md
efca9a0f1 Added ElementsAre and UnorderedElementsAre  (#2377)
dd36f83b8 Merge pull request #2630 from ChrisThrasher/export_all_symbols
baab9e8d2 Export symbols for all compilers on Windows
2d3c9713a Remove VS2015 workaround from Detail::generate
956f915e3 Document template macros are in spearate header
aa8da505e Fix compatibility with previous CUDA versions
e27bb7198 Fix macro-redefinition issue with MSVC+CUDA
3486f8ed9 Update generator docs
b5be64204 catch_debugger.hpp: restore PPC support (#2619)
d59572f46 Reword the SKIP docs a bit
16f48f8c7 Add SUCCEED and FAIL docs next to SKIP docs
367c2cb24 Update doc about what counts as unique test case
d548be26e Add new SKIP macro for skipping tests at runtime (#2360)
52066dbc2 Fix build with GCC 13 (add missing <cstdint> include)
cdf604f30 Update command-line.md
04382af4c Slightly better clang-format
ac93f1943 Improved path normalization in approvalTests.py
72b60dfd2 Cleanup the Windows GHA builds
0c62167fe Merge pull request #2604 from ChrisThrasher/generated_includes_directory
1be954ff7 Keep generated headers within project binary directory
78bb4fda0 Mention that the benchmarks are not run by default next to example
e6ec1c238 Fix benchmarking example in the main readme
477c1f515 Fixed typo in code example in top level README.md
f8b9f7725 Prune Appveyor builds
77fbacb03 Add VS 2019-2022 C+14/17 jobs to GHA
e3fc97dff fix compiler warning in parseUint and catch only relevant exceptions (#2572)
9c0533a90 Add MessageMatches matcher for exception (#2570)
ed02710b8 Make AutoReg in test registration macros const
8b84438be Avoid usage of master when possible

git-subtree-dir: externals/catch
git-subtree-split: 53d0d913a422d356b23dd927547febdf69ee9081
This commit is contained in:
Yang Liu
2023-12-31 14:00:46 +08:00
parent 6879e5bb1c
commit ba06a404d1
272 changed files with 22238 additions and 7949 deletions

View File

@@ -0,0 +1,94 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_is_permutation.hpp>
#include <helpers/range_test_helpers.hpp>
#include <array>
namespace {
template <typename Range1, typename Range2>
static bool is_permutation(Range1 const& r1, Range2 const& r2) {
using std::begin; using std::end;
return Catch::Detail::is_permutation(
begin( r1 ), end( r1 ), begin( r2 ), end( r2 ), std::equal_to<>{} );
}
}
TEST_CASE("is_permutation", "[algorithms][approvals]") {
SECTION( "Handle empty ranges" ) {
std::array<int, 0> empty;
std::array<int, 2> non_empty{ { 2, 3 } };
REQUIRE( is_permutation( empty, empty ) );
REQUIRE_FALSE( is_permutation( empty, non_empty ) );
REQUIRE_FALSE( is_permutation( non_empty, empty ) );
}
SECTION( "Different length ranges" ) {
std::array<int, 6> arr1{ { 1, 3, 5, 7, 8, 9 } };
// arr2 is prefix of arr1
std::array<int, 4> arr2{ { 1, 3, 5, 7 } };
// arr3 shares prefix with arr1 and arr2, but is not a permutation
std::array<int, 5> arr3{ { 1, 3, 5, 9, 8 } };
REQUIRE_FALSE( is_permutation( arr1, arr2 ) );
REQUIRE_FALSE( is_permutation( arr1, arr3 ) );
REQUIRE_FALSE( is_permutation( arr2, arr3 ) );
}
SECTION( "Same length ranges" ) {
SECTION( "Shared elements, but different counts" ) {
const std::array<int, 6>
arr1{ { 1, 1, 1, 1, 2, 2 } },
arr2{ { 1, 1, 2, 2, 2, 2 } };
REQUIRE_FALSE( is_permutation( arr1, arr2 ) );
}
SECTION( "Identical ranges" ) {
const std::array<int, 6>
arr1{ { 1, 1, 1, 1, 2, 2 } },
arr2{ { 1, 1, 2, 2, 2, 2 } };
REQUIRE( is_permutation( arr1, arr1 ) );
REQUIRE( is_permutation( arr2, arr2 ) );
}
SECTION( "Completely distinct elements" ) {
// Completely distinct elements
const std::array<int, 4>
arr1{ { 1, 2, 3, 4 } },
arr2{ { 10, 20, 30, 40 } };
REQUIRE_FALSE( is_permutation( arr1, arr2 ) );
}
SECTION( "Reverse ranges" ) {
const std::array<int, 5>
arr1{ { 1, 2, 3, 4, 5 } },
arr2{ { 5, 4, 3, 2, 1 } };
REQUIRE( is_permutation( arr1, arr2 ) );
}
SECTION( "Shared prefix & permuted elements" ) {
const std::array<int, 5>
arr1{ { 1, 1, 2, 3, 4 } },
arr2{ { 1, 1, 4, 2, 3 } };
REQUIRE( is_permutation( arr1, arr2 ) );
}
SECTION( "Permutations with element count > 1" ) {
const std::array<int, 7>
arr1{ { 2, 2, 3, 3, 3, 1, 1 } },
arr2{ { 3, 2, 1, 3, 2, 1, 3 } };
REQUIRE( is_permutation( arr1, arr2 ) );
}
}
}
TEST_CASE("is_permutation supports iterator + sentinel pairs",
"[algorithms][is-permutation][approvals]") {
const has_different_begin_end_types<int>
range_1{ 1, 2, 3, 4 },
range_2{ 4, 3, 2, 1 };
REQUIRE( is_permutation( range_1, range_2 ) );
const has_different_begin_end_types<int> range_3{ 3, 3, 2, 1 };
REQUIRE_FALSE( is_permutation( range_1, range_3 ) );
}

View File

@@ -0,0 +1,17 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
TEST_CASE( "Incomplete AssertionHandler", "[assertion-handler][!shouldfail]" ) {
Catch::AssertionHandler catchAssertionHandler(
"REQUIRE"_catch_sr,
CATCH_INTERNAL_LINEINFO,
"Dummy",
Catch::ResultDisposition::Normal );
}

View File

@@ -89,6 +89,47 @@ TEST_CASE("Optional comparison ops", "[optional][approvals]") {
}
}
namespace {
struct MoveChecker {
bool has_moved = false;
MoveChecker() = default;
MoveChecker( MoveChecker const& rhs ) = default;
MoveChecker& operator=( MoveChecker const& rhs ) = default;
MoveChecker( MoveChecker&& rhs ) noexcept { rhs.has_moved = true; }
MoveChecker& operator=( MoveChecker&& rhs ) noexcept {
rhs.has_moved = true;
return *this;
}
};
}
TEST_CASE( "Optional supports move ops", "[optional][approvals]" ) {
using Catch::Optional;
MoveChecker a;
Optional<MoveChecker> opt_A( a );
REQUIRE_FALSE( a.has_moved );
REQUIRE_FALSE( opt_A->has_moved );
SECTION( "Move construction from element" ) {
Optional<MoveChecker> opt_B( CATCH_MOVE( a ) );
REQUIRE( a.has_moved );
}
SECTION( "Move assignment from element" ) {
opt_A = CATCH_MOVE( a );
REQUIRE( a.has_moved );
}
SECTION( "Move construction from optional" ) {
Optional<MoveChecker> opt_B( CATCH_MOVE( opt_A ) );
REQUIRE( opt_A->has_moved );
}
SECTION( "Move assignment from optional" ) {
Optional<MoveChecker> opt_B( opt_A );
REQUIRE_FALSE( opt_A->has_moved );
opt_B = CATCH_MOVE( opt_A );
REQUIRE( opt_A->has_moved );
}
}
TEST_CASE( "Decomposer checks that the argument is 0 when handling "
"only-0-comparable types",
"[decomposition][approvals]" ) {

View File

@@ -9,7 +9,9 @@
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_template_test_macros.hpp>
#include <catch2/internal/catch_floating_point_helpers.hpp>
#include <catch2/internal/catch_random_floating_point_helpers.hpp>
#include <limits>
TEST_CASE("convertToBits", "[floating-point][conversion]") {
using Catch::Detail::convertToBits;
@@ -72,3 +74,60 @@ TEST_CASE("UlpDistance", "[floating-point][ulp][approvals]") {
CHECK( ulpDistance( 1.f, 2.f ) == 0x80'00'00 );
CHECK( ulpDistance( -2.f, 2.f ) == 0x80'00'00'00 );
}
TEMPLATE_TEST_CASE("gamma", "[approvals][floating-point][ulp][gamma]", float, double) {
using Catch::Detail::gamma;
using Catch::Detail::directCompare;
// We need to butcher the equal tests with the directCompare helper,
// because the Wfloat-equal triggers in decomposer rather than here,
// so we cannot locally disable it. Goddamn GCC.
CHECK( directCompare( gamma( TestType( -1. ), TestType( 1. ) ),
gamma( TestType( 0.2332 ), TestType( 1.0 ) ) ) );
CHECK( directCompare( gamma( TestType( -2. ), TestType( 0 ) ),
gamma( TestType( 1. ), TestType( 1.5 ) ) ) );
CHECK( gamma( TestType( 0. ), TestType( 1.0 ) ) <
gamma( TestType( 1.0 ), TestType( 1.5 ) ) );
CHECK( gamma( TestType( 0 ), TestType( 1. ) ) <
std::numeric_limits<TestType>::epsilon() );
CHECK( gamma( TestType( -1. ), TestType( -0. ) ) <
std::numeric_limits<TestType>::epsilon() );
CHECK( directCompare( gamma( TestType( 1. ), TestType( 2. ) ),
std::numeric_limits<TestType>::epsilon() ) );
CHECK( directCompare( gamma( TestType( -2. ), TestType( -1. ) ),
std::numeric_limits<TestType>::epsilon() ) );
}
TEMPLATE_TEST_CASE("count_equidistant_floats",
"[approvals][floating-point][distance]",
float,
double) {
using Catch::Detail::count_equidistant_floats;
auto count_steps = []( TestType a, TestType b ) {
return count_equidistant_floats( a, b, Catch::Detail::gamma( a, b ) );
};
CHECK( count_steps( TestType( -1. ), TestType( 1. ) ) ==
2 * count_steps( TestType( 0. ), TestType( 1. ) ) );
}
TEST_CASE( "count_equidistant_floats",
"[approvals][floating-point][distance]" ) {
using Catch::Detail::count_equidistant_floats;
auto count_floats_with_scaled_ulp = []( auto a, auto b ) {
return count_equidistant_floats( a, b, Catch::Detail::gamma( a, b ) );
};
CHECK( count_floats_with_scaled_ulp( 1., 1.5 ) == 1ull << 51 );
CHECK( count_floats_with_scaled_ulp( 1.25, 1.5 ) == 1ull << 50 );
CHECK( count_floats_with_scaled_ulp( 1.f, 1.5f ) == 1 << 22 );
STATIC_REQUIRE( std::is_same<std::uint64_t,
decltype( count_floats_with_scaled_ulp(
0., 1. ) )>::value );
STATIC_REQUIRE( std::is_same<std::uint32_t,
decltype( count_floats_with_scaled_ulp(
0.f, 1.f ) )>::value );
}

View File

@@ -10,12 +10,15 @@
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
#include <helpers/range_test_helpers.hpp>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generator_exception.hpp>
#include <catch2/generators/catch_generators_adapters.hpp>
#include <catch2/generators/catch_generators_random.hpp>
#include <catch2/generators/catch_generators_range.hpp>
#include <catch2/generators/catch_generator_exception.hpp>
// Tests of generator implementation details
TEST_CASE("Generators internals", "[generators][internals]") {
@@ -411,6 +414,7 @@ TEST_CASE("GENERATE handles function (pointers)", "[generators][compilation][app
TEST_CASE("GENERATE decays arrays", "[generators][compilation][approvals]") {
auto str = GENERATE("abc", "def", "gh");
(void)str;
STATIC_REQUIRE(std::is_same<decltype(str), const char*>::value);
}
@@ -534,3 +538,39 @@ TEST_CASE( "Random generators can be seeded", "[generators][approvals]" ) {
}
}
}
TEST_CASE("Filter generator throws exception for empty generator",
"[generators]") {
using namespace Catch::Generators;
REQUIRE_THROWS_AS(
filter( []( int ) { return false; }, value( 3 ) ),
Catch::GeneratorException );
}
TEST_CASE("from_range(container) supports ADL begin/end and arrays", "[generators][from-range][approvals]") {
using namespace Catch::Generators;
SECTION("C array") {
int arr[3]{ 5, 6, 7 };
auto gen = from_range( arr );
REQUIRE( gen.get() == 5 );
REQUIRE( gen.next() );
REQUIRE( gen.get() == 6 );
REQUIRE( gen.next() );
REQUIRE( gen.get() == 7 );
REQUIRE_FALSE( gen.next() );
}
SECTION( "ADL range" ) {
unrelated::needs_ADL_begin<int> range{ 1, 2, 3 };
auto gen = from_range( range );
REQUIRE( gen.get() == 1 );
REQUIRE( gen.next() );
REQUIRE( gen.get() == 2 );
REQUIRE( gen.next() );
REQUIRE( gen.get() == 3 );
REQUIRE_FALSE( gen.next() );
}
}

View File

@@ -0,0 +1,150 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_random_integer_helpers.hpp>
namespace {
template <typename Int>
static void
CommutativeMultCheck( Int a, Int b, Int upper_result, Int lower_result ) {
using Catch::Detail::extendedMult;
using Catch::Detail::ExtendedMultResult;
CHECK( extendedMult( a, b ) ==
ExtendedMultResult<Int>{ upper_result, lower_result } );
CHECK( extendedMult( b, a ) ==
ExtendedMultResult<Int>{ upper_result, lower_result } );
}
} // namespace
TEST_CASE( "extendedMult 64x64", "[Integer][approvals]" ) {
// a x 0 == 0
CommutativeMultCheck<uint64_t>( 0x1234'5678'9ABC'DEFF, 0, 0, 0 );
// bit carried from low half to upper half
CommutativeMultCheck<uint64_t>( uint64_t( 1 ) << 63, 2, 1, 0 );
// bits in upper half on one side, bits in lower half on other side
CommutativeMultCheck<uint64_t>( 0xcdcd'dcdc'0000'0000,
0x0000'0000'aeae'aeae,
0x0000'0000'8c6e'5a77,
0x7391'a588'0000'0000 );
// Some input numbers without interesting patterns
CommutativeMultCheck<uint64_t>( 0xaaaa'aaaa'aaaa'aaaa,
0xbbbb'bbbb'bbbb'bbbb,
0x7d27'd27d'27d2'7d26,
0xd82d'82d8'2d82'd82e );
CommutativeMultCheck<uint64_t>( 0x7d27'd27d'27d2'7d26,
0xd82d'82d8'2d82'd82e,
0x69af'd991'8256'b953,
0x8724'8909'fcb6'8cd4 );
CommutativeMultCheck<uint64_t>( 0xdead'beef'dead'beef,
0xfeed'feed'feed'feef,
0xddbf'680b'2b0c'b558,
0x7a36'b06f'2ce9'6321 );
CommutativeMultCheck<uint64_t>( 0xddbf'680b'2b0c'b558,
0x7a36'b06f'2ce9'6321,
0x69dc'96c9'294b'fc7f,
0xd038'39fa'a3dc'6858 );
CommutativeMultCheck<uint64_t>( 0x61c8'8646'80b5'83eb,
0x61c8'8646'80b5'83eb,
0x2559'92d3'8220'8bbe,
0xdf44'2d22'ce48'59b9 );
}
TEST_CASE( "SizedUnsignedType helpers", "[integer][approvals]" ) {
using Catch::Detail::SizedUnsignedType_t;
using Catch::Detail::DoubleWidthUnsignedType_t;
STATIC_REQUIRE( sizeof( SizedUnsignedType_t<1> ) == 1 );
STATIC_REQUIRE( sizeof( SizedUnsignedType_t<2> ) == 2 );
STATIC_REQUIRE( sizeof( SizedUnsignedType_t<4> ) == 4 );
STATIC_REQUIRE( sizeof( SizedUnsignedType_t<8> ) == 8 );
STATIC_REQUIRE( sizeof( DoubleWidthUnsignedType_t<std::uint8_t> ) == 2 );
STATIC_REQUIRE( std::is_unsigned<DoubleWidthUnsignedType_t<std::uint8_t>>::value );
STATIC_REQUIRE( sizeof( DoubleWidthUnsignedType_t<std::uint16_t> ) == 4 );
STATIC_REQUIRE( std::is_unsigned<DoubleWidthUnsignedType_t<std::uint16_t>>::value );
STATIC_REQUIRE( sizeof( DoubleWidthUnsignedType_t<std::uint32_t> ) == 8 );
STATIC_REQUIRE( std::is_unsigned<DoubleWidthUnsignedType_t<std::uint32_t>>::value );
}
TEST_CASE( "extendedMult 32x32", "[integer][approvals]" ) {
// a x 0 == 0
CommutativeMultCheck<uint32_t>( 0x1234'5678, 0, 0, 0 );
// bit carried from low half to upper half
CommutativeMultCheck<uint32_t>( uint32_t(1) << 31, 2, 1, 0 );
// bits in upper half on one side, bits in lower half on other side
CommutativeMultCheck<uint32_t>( 0xdcdc'0000, 0x0000'aabb, 0x0000'934b, 0x6cb4'0000 );
// Some input numbers without interesting patterns
CommutativeMultCheck<uint32_t>(
0xaaaa'aaaa, 0xbbbb'bbbb, 0x7d27'd27c, 0x2d82'd82e );
CommutativeMultCheck<uint32_t>(
0x7d27'd27c, 0x2d82'd82e, 0x163f'f7e8, 0xc5b8'7248 );
CommutativeMultCheck<uint32_t>(
0xdead'beef, 0xfeed'feed, 0xddbf'6809, 0x6f8d'e543 );
CommutativeMultCheck<uint32_t>(
0xddbf'6809, 0x6f8d'e543, 0x60a0'e71e, 0x751d'475b );
}
TEST_CASE( "extendedMult 8x8", "[integer][approvals]" ) {
// a x 0 == 0
CommutativeMultCheck<uint8_t>( 0xcd, 0, 0, 0 );
// bit carried from low half to upper half
CommutativeMultCheck<uint8_t>( uint8_t( 1 ) << 7, 2, 1, 0 );
// bits in upper half on one side, bits in lower half on other side
CommutativeMultCheck<uint8_t>( 0x80, 0x03, 0x01, 0x80 );
// Some input numbers without interesting patterns
CommutativeMultCheck<uint8_t>( 0xaa, 0xbb, 0x7c, 0x2e );
CommutativeMultCheck<uint8_t>( 0x7c, 0x2e, 0x16, 0x48 );
CommutativeMultCheck<uint8_t>( 0xdc, 0xcd, 0xb0, 0x2c );
CommutativeMultCheck<uint8_t>( 0xb0, 0x2c, 0x1e, 0x40 );
}
TEST_CASE( "negative and positive signed integers keep their order after transposeToNaturalOrder",
"[integer][approvals]") {
using Catch::Detail::transposeToNaturalOrder;
int32_t negative( -1 );
int32_t positive( 1 );
uint32_t adjusted_negative =
transposeToNaturalOrder<int32_t>( static_cast<uint32_t>( negative ) );
uint32_t adjusted_positive =
transposeToNaturalOrder<int32_t>( static_cast<uint32_t>( positive ) );
REQUIRE( adjusted_negative < adjusted_positive );
REQUIRE( adjusted_positive - adjusted_negative == 2 );
// Conversion has to be reversible
REQUIRE( negative == static_cast<int32_t>( transposeToNaturalOrder<int32_t>(
adjusted_negative ) ) );
REQUIRE( positive == static_cast<int32_t>( transposeToNaturalOrder<int32_t>(
adjusted_positive ) ) );
}
TEST_CASE( "unsigned integers are unchanged by transposeToNaturalOrder",
"[integer][approvals]") {
using Catch::Detail::transposeToNaturalOrder;
uint32_t max = std::numeric_limits<uint32_t>::max();
uint32_t zero = 0;
REQUIRE( max == transposeToNaturalOrder<uint32_t>( max ) );
REQUIRE( zero == transposeToNaturalOrder<uint32_t>( zero ) );
}

View File

@@ -22,6 +22,8 @@
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
#include <catch2/benchmark/detail/catch_estimate_clock.hpp>
#include <numeric>
namespace {
struct manual_clock {
public:
@@ -154,8 +156,12 @@ TEST_CASE("uniform samples", "[benchmark]") {
std::vector<double> samples(100);
std::fill(samples.begin(), samples.end(), 23);
using it = std::vector<double>::iterator;
auto e = Catch::Benchmark::Detail::bootstrap(0.95, samples.begin(), samples.end(), samples, [](it a, it b) {
auto e = Catch::Benchmark::Detail::bootstrap(
0.95,
samples.data(),
samples.data() + samples.size(),
samples,
[]( double const* a, double const* b ) {
auto sum = std::accumulate(a, b, 0.);
return sum / (b - a);
});
@@ -196,7 +202,7 @@ TEST_CASE("normal_quantile", "[benchmark]") {
TEST_CASE("mean", "[benchmark]") {
std::vector<double> x{ 10., 20., 14., 16., 30., 24. };
auto m = Catch::Benchmark::Detail::mean(x.begin(), x.end());
auto m = Catch::Benchmark::Detail::mean(x.data(), x.data() + x.size());
REQUIRE(m == 19.);
}
@@ -204,9 +210,9 @@ TEST_CASE("mean", "[benchmark]") {
TEST_CASE("weighted_average_quantile", "[benchmark]") {
std::vector<double> x{ 10., 20., 14., 16., 30., 24. };
auto q1 = Catch::Benchmark::Detail::weighted_average_quantile(1, 4, x.begin(), x.end());
auto med = Catch::Benchmark::Detail::weighted_average_quantile(1, 2, x.begin(), x.end());
auto q3 = Catch::Benchmark::Detail::weighted_average_quantile(3, 4, x.begin(), x.end());
auto q1 = Catch::Benchmark::Detail::weighted_average_quantile(1, 4, x.data(), x.data() + x.size());
auto med = Catch::Benchmark::Detail::weighted_average_quantile(1, 2, x.data(), x.data() + x.size());
auto q3 = Catch::Benchmark::Detail::weighted_average_quantile(3, 4, x.data(), x.data() + x.size());
REQUIRE(q1 == 14.5);
REQUIRE(med == 18.);
@@ -225,7 +231,8 @@ TEST_CASE("classify_outliers", "[benchmark]") {
SECTION("none") {
std::vector<double> x{ 10., 20., 14., 16., 30., 24. };
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
auto o = Catch::Benchmark::Detail::classify_outliers(
x.data(), x.data() + x.size() );
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
require_outliers(o, 0, 0, 0, 0);
@@ -233,7 +240,8 @@ TEST_CASE("classify_outliers", "[benchmark]") {
SECTION("low severe") {
std::vector<double> x{ -12., 20., 14., 16., 30., 24. };
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
auto o = Catch::Benchmark::Detail::classify_outliers(
x.data(), x.data() + x.size() );
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
require_outliers(o, 1, 0, 0, 0);
@@ -241,7 +249,8 @@ TEST_CASE("classify_outliers", "[benchmark]") {
SECTION("low mild") {
std::vector<double> x{ 1., 20., 14., 16., 30., 24. };
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
auto o = Catch::Benchmark::Detail::classify_outliers(
x.data(), x.data() + x.size() );
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
require_outliers(o, 0, 1, 0, 0);
@@ -249,7 +258,8 @@ TEST_CASE("classify_outliers", "[benchmark]") {
SECTION("high mild") {
std::vector<double> x{ 10., 20., 14., 16., 36., 24. };
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
auto o = Catch::Benchmark::Detail::classify_outliers(
x.data(), x.data() + x.size() );
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
require_outliers(o, 0, 0, 1, 0);
@@ -257,7 +267,8 @@ TEST_CASE("classify_outliers", "[benchmark]") {
SECTION("high severe") {
std::vector<double> x{ 10., 20., 14., 16., 49., 24. };
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
auto o = Catch::Benchmark::Detail::classify_outliers(
x.data(), x.data() + x.size() );
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
require_outliers(o, 0, 0, 0, 1);
@@ -265,7 +276,8 @@ TEST_CASE("classify_outliers", "[benchmark]") {
SECTION("mixed") {
std::vector<double> x{ -20., 20., 14., 16., 39., 24. };
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
auto o = Catch::Benchmark::Detail::classify_outliers(
x.data(), x.data() + x.size() );
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
require_outliers(o, 1, 0, 1, 0);
@@ -280,15 +292,13 @@ TEST_CASE("analyse", "[approvals][benchmark]") {
data.benchmarkSamples = 99;
Catch::Config config{data};
using Duration = Catch::Benchmark::FloatDuration<Catch::Benchmark::default_clock>;
Catch::Benchmark::Environment<Duration> env;
std::vector<Duration> samples(99);
using FDuration = Catch::Benchmark::FDuration;
std::vector<FDuration> samples(99);
for (size_t i = 0; i < samples.size(); ++i) {
samples[i] = Duration(23 + (i % 3 - 1));
samples[i] = FDuration(23 + (i % 3 - 1));
}
auto analysis = Catch::Benchmark::Detail::analyse(config, env, samples.begin(), samples.end());
auto analysis = Catch::Benchmark::Detail::analyse(config, samples.data(), samples.data() + samples.size());
CHECK( analysis.mean.point.count() == 23 );
CHECK( analysis.mean.lower_bound.count() < 23 );
CHECK(analysis.mean.lower_bound.count() > 22);
@@ -321,15 +331,13 @@ TEST_CASE("analyse no analysis", "[benchmark]") {
data.benchmarkSamples = 99;
Catch::Config config{ data };
using Duration = Catch::Benchmark::FloatDuration<Catch::Benchmark::default_clock>;
Catch::Benchmark::Environment<Duration> env;
std::vector<Duration> samples(99);
using FDuration = Catch::Benchmark::FDuration;
std::vector<FDuration> samples(99);
for (size_t i = 0; i < samples.size(); ++i) {
samples[i] = Duration(23 + (i % 3 - 1));
samples[i] = FDuration(23 + (i % 3 - 1));
}
auto analysis = Catch::Benchmark::Detail::analyse(config, env, samples.begin(), samples.end());
auto analysis = Catch::Benchmark::Detail::analyse(config, samples.data(), samples.data() + samples.size());
CHECK(analysis.mean.point.count() == 23);
CHECK(analysis.mean.lower_bound.count() == 23);
CHECK(analysis.mean.upper_bound.count() == 23);
@@ -442,6 +450,6 @@ TEST_CASE("Failing benchmarks", "[!benchmark][.approvals]") {
}
TEST_CASE( "Failing benchmark respects should-fail",
"[!shouldfail][!benchmark][.approvals]" ) {
"[!shouldfail][!benchmark][approvals]" ) {
BENCHMARK( "Asserting benchmark" ) { REQUIRE( 1 == 2 ); };
}

View File

@@ -0,0 +1,152 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_jsonwriter.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include <sstream>
namespace {
struct Custom {};
static std::ostream& operator<<( std::ostream& os, Custom const& ) {
return os << "custom";
}
} // namespace
TEST_CASE( "JsonWriter", "[JSON][JsonWriter]" ) {
std::stringstream stream;
SECTION( "Newly constructed JsonWriter does nothing" ) {
Catch::JsonValueWriter writer{ stream };
REQUIRE( stream.str() == "" );
}
SECTION( "Calling writeObject will create an empty pair of braces" ) {
{ auto writer = Catch::JsonValueWriter{ stream }.writeObject(); }
REQUIRE( stream.str() == "{\n}" );
}
SECTION( "Calling writeObject with key will create an object to write the "
"value" ) {
using Catch::Matchers::ContainsSubstring;
{
auto writer = Catch::JsonValueWriter{ stream }.writeObject();
writer.write( "int" ).write( 1 );
writer.write( "double" ).write( 1.5 );
writer.write( "true" ).write( true );
writer.write( "false" ).write( false );
writer.write( "string" ).write( "this is a string" );
writer.write( "array" ).writeArray().write( 1 ).write( 2 );
}
REQUIRE_THAT(
stream.str(),
ContainsSubstring( "\"int\": 1," ) &&
ContainsSubstring( "\"double\": 1.5," ) &&
ContainsSubstring( "\"true\": true," ) &&
ContainsSubstring( "\"false\": false," ) &&
ContainsSubstring( "\"string\": \"this is a string\"," ) &&
ContainsSubstring( "\"array\": [\n 1,\n 2\n ]\n}" ) );
}
SECTION( "nesting objects" ) {
using Catch::Matchers::ContainsSubstring;
{
auto writer = Catch::JsonValueWriter{ stream }.writeObject();
writer.write( "empty_object" ).writeObject();
writer.write( "fully_object" )
.writeObject()
.write( "key" )
.write( 1 );
}
REQUIRE_THAT( stream.str(),
ContainsSubstring( "\"empty_object\": {\n }," ) &&
ContainsSubstring(
"\"fully_object\": {\n \"key\": 1\n }" ) );
}
SECTION( "Calling writeArray will create an empty pair of braces" ) {
{ auto writer = Catch::JsonValueWriter{ stream }.writeArray(); }
REQUIRE( stream.str() == "[\n]" );
}
SECTION( "Calling writeArray creates array to write the values to" ) {
{
auto writer = Catch::JsonValueWriter{ stream }.writeArray();
writer.write( 1 );
writer.write( 1.5 );
writer.write( true );
writer.write( false );
writer.write( "this is a string" );
writer.writeObject().write( "object" ).write( 42 );
writer.writeArray().write( "array" ).write( 42.5 );
}
REQUIRE( stream.str() == "[\n 1,\n 1.5,\n true,\n false,\n \"this is a string\",\n {\n \"object\": 42\n },\n [\n \"array\",\n 42.5\n ]\n]" );
}
SECTION(
"Moved from JsonObjectWriter shall not insert superfluous brace" ) {
{
auto writer = Catch::JsonObjectWriter{ stream };
auto another_writer = std::move( writer );
}
REQUIRE( stream.str() == "{\n}" );
}
SECTION(
"Moved from JsonArrayWriter shall not insert superfluous bracket" ) {
{
auto writer = Catch::JsonArrayWriter{ stream };
auto another_writer = std::move( writer );
}
REQUIRE( stream.str() == "[\n]" );
}
SECTION( "Custom class shall be quoted" ) {
Catch::JsonValueWriter{ stream }.write( Custom{} );
REQUIRE( stream.str() == "\"custom\"" );
}
}
TEST_CASE( "JsonWriter escapes charaters in strings properly", "[JsonWriter]" ) {
std::stringstream sstream;
SECTION( "Quote in a string is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\"" );
REQUIRE( sstream.str() == "\"\\\"\"" );
}
SECTION("Backslash in a string is escaped") {
Catch::JsonValueWriter{ sstream }.write( "\\" );
REQUIRE( sstream.str() == "\"\\\\\"" );
}
SECTION( "Forward slash in a string is **not** escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "/" );
REQUIRE( sstream.str() == "\"/\"" );
}
SECTION( "Backspace in a string is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\b" );
REQUIRE( sstream.str() == "\"\\b\"" );
}
SECTION( "Formfeed in a string is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\f" );
REQUIRE( sstream.str() == "\"\\f\"" );
}
SECTION( "linefeed in a string is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\n" );
REQUIRE( sstream.str() == "\"\\n\"" );
}
SECTION( "carriage return in a string is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\r" );
REQUIRE( sstream.str() == "\"\\r\"" );
}
SECTION( "tab in a string is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\t" );
REQUIRE( sstream.str() == "\"\\t\"" );
}
SECTION( "combination of characters is escaped" ) {
Catch::JsonValueWriter{ sstream }.write( "\\/\t\r\n" );
REQUIRE( sstream.str() == "\"\\\\/\\t\\r\\n\"" );
}
}

View File

@@ -14,8 +14,8 @@
using namespace Catch;
namespace {
Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) {
return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) );
Catch::TestCaseTracking::NameAndLocationRef makeNAL( StringRef name ) {
return Catch::TestCaseTracking::NameAndLocationRef( name, Catch::SourceLineInfo("",0) );
}
}

View File

@@ -7,9 +7,17 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_template_test_macros.hpp>
#include <catch2/internal/catch_floating_point_helpers.hpp>
#include <catch2/internal/catch_random_integer_helpers.hpp>
#include <catch2/internal/catch_random_number_generator.hpp>
#include <catch2/internal/catch_random_seed_generation.hpp>
#include <catch2/internal/catch_uniform_floating_point_distribution.hpp>
#include <catch2/internal/catch_uniform_integer_distribution.hpp>
#include <catch2/generators/catch_generators.hpp>
#include <catch2/matchers/catch_matchers_range_equals.hpp>
#include <random>
TEST_CASE("Our PCG implementation provides expected results for known seeds", "[rng]") {
Catch::SimplePcg32 rng;
@@ -60,3 +68,523 @@ TEST_CASE("Random seed generation accepts known methods", "[rng][seed]") {
REQUIRE_NOTHROW(Catch::generateRandomSeed(method));
}
TEMPLATE_TEST_CASE("uniform_floating_point_distribution never returns infs from finite range",
"[rng][distribution][floating-point][approvals]", float, double) {
std::random_device rd{};
Catch::SimplePcg32 pcg( rd() );
Catch::uniform_floating_point_distribution<TestType> dist(
-std::numeric_limits<TestType>::max(),
std::numeric_limits<TestType>::max() );
for (size_t i = 0; i < 10'000; ++i) {
auto ret = dist( pcg );
REQUIRE_FALSE( std::isinf( ret ) );
REQUIRE_FALSE( std::isnan( ret ) );
}
}
TEST_CASE( "fillBitsFrom - shortening and stretching", "[rng][approvals]" ) {
using Catch::Detail::fillBitsFrom;
// The seed is not important, but the numbers below have to be repeatable.
// They should also exhibit the same general pattern of being prefixes
Catch::SimplePcg32 pcg( 0xaabb'ccdd );
SECTION( "Shorten to 8 bits" ) {
// We cast the result to avoid dealing with char-like type in uint8_t
auto shortened = static_cast<uint32_t>( fillBitsFrom<uint8_t>( pcg ) );
REQUIRE( shortened == 0xcc );
}
SECTION( "Shorten to 16 bits" ) {
auto shortened = fillBitsFrom<uint16_t>( pcg );
REQUIRE( shortened == 0xccbe );
}
SECTION( "Keep at 32 bits" ) {
auto n = fillBitsFrom<uint32_t>( pcg );
REQUIRE( n == 0xccbe'5f04 );
}
SECTION( "Stretch to 64 bits" ) {
auto stretched = fillBitsFrom<uint64_t>( pcg );
REQUIRE( stretched == 0xccbe'5f04'a424'a486 );
}
}
TEST_CASE("uniform_integer_distribution can return the bounds", "[rng][distribution]") {
Catch::uniform_integer_distribution<int32_t> dist( -10, 10 );
REQUIRE( dist.a() == -10 );
REQUIRE( dist.b() == 10 );
}
namespace {
template <typename T>
static void CheckReturnValue(Catch::uniform_integer_distribution<T>& dist,
Catch::SimplePcg32& rng,
T target) {
REQUIRE( dist.a() == dist.b() );
for (int i = 0; i < 1'000; ++i) {
REQUIRE( dist( rng ) == target );
}
}
}
TEMPLATE_TEST_CASE( "uniform_integer_distribution can handle unit ranges",
"[rng][distribution][approvals]",
unsigned char,
signed char,
char,
uint8_t,
int8_t,
uint16_t,
int16_t,
uint32_t,
int32_t,
uint64_t,
int64_t ) {
// We want random seed to sample different parts of the rng state,
// the output is predetermined anyway
std::random_device rd;
auto seed = rd();
CAPTURE( seed );
Catch::SimplePcg32 pcg( seed );
// We check unitary ranges of 3 different values, min for type, max for type,
// some value inbetween just to make sure
SECTION("lowest value") {
constexpr auto lowest = std::numeric_limits<TestType>::min();
Catch::uniform_integer_distribution<TestType> dist( lowest, lowest );
CheckReturnValue( dist, pcg, lowest );
}
SECTION( "highest value" ) {
constexpr auto highest = std::numeric_limits<TestType>::max();
Catch::uniform_integer_distribution<TestType> dist( highest, highest );
CheckReturnValue( dist, pcg, highest );
}
SECTION( "some value" ) {
constexpr auto some = TestType( 42 );
Catch::uniform_integer_distribution<TestType> dist( some, some );
CheckReturnValue( dist, pcg, some );
}
}
// Bool needs its own test because it doesn't have a valid "third" value
TEST_CASE( "uniform_integer_distribution can handle boolean unit ranges",
"[rng][distribution][approvals]" ) {
// We want random seed to sample different parts of the rng state,
// the output is predetermined anyway
std::random_device rd;
auto seed = rd();
CAPTURE( seed );
Catch::SimplePcg32 pcg( seed );
// We check unitary ranges of 3 different values, min for type, max for
// type, some value inbetween just to make sure
SECTION( "lowest value" ) {
Catch::uniform_integer_distribution<bool> dist( false, false );
CheckReturnValue( dist, pcg, false );
}
SECTION( "highest value" ) {
Catch::uniform_integer_distribution<bool> dist( true, true );
CheckReturnValue( dist, pcg, true );
}
}
TEMPLATE_TEST_CASE( "uniform_integer_distribution can handle full width ranges",
"[rng][distribution][approvals]",
unsigned char,
signed char,
char,
uint8_t,
int8_t,
uint16_t,
int16_t,
uint32_t,
int32_t,
uint64_t,
int64_t ) {
// We want random seed to sample different parts of the rng state,
// the output is predetermined anyway
std::random_device rd;
auto seed = rd();
CAPTURE( seed );
Catch::SimplePcg32 pcg( seed );
constexpr auto lowest = std::numeric_limits<TestType>::min();
constexpr auto highest = std::numeric_limits<TestType>::max();
Catch::uniform_integer_distribution<TestType> dist( lowest, highest );
STATIC_REQUIRE( std::is_same<TestType, decltype( dist( pcg ) )>::value );
// We need to do bit operations on the results, so we will have to
// cast them to unsigned type.
using BitType = std::make_unsigned_t<TestType>;
BitType ORs = 0;
BitType ANDs = BitType(-1);
for (int i = 0; i < 100; ++i) {
auto bits = static_cast<BitType>( dist( pcg ) );
ORs |= bits;
ANDs &= bits;
}
// Assuming both our RNG and distribution are unbiased, asking for
// the full range should essentially give us random bit generator.
// Over long run, OR of all the generated values should have all
// bits set to 1, while AND should have all bits set to 0.
// The chance of this test failing for unbiased pipeline is
// 1 / 2**iters, which for 100 iterations is astronomical.
REQUIRE( ORs == BitType( -1 ) );
REQUIRE( ANDs == 0 );
}
namespace {
template <typename T>
struct uniform_integer_test_params;
template <>
struct uniform_integer_test_params<bool> {
static constexpr bool lowest = false;
static constexpr bool highest = true;
// This seems weird, but it is an artifact of the specific seed
static constexpr bool expected[] = { true,
true,
true,
true,
true,
true,
false,
true,
true,
true,
true,
true,
false,
true,
true };
};
template <>
struct uniform_integer_test_params<char> {
static constexpr char lowest = 32;
static constexpr char highest = 126;
static constexpr char expected[] = { 'k',
'\\',
'Z',
'X',
'`',
'Q',
';',
'o',
']',
'T',
'v',
'p',
':',
'S',
't' };
};
template <>
struct uniform_integer_test_params<uint8_t> {
static constexpr uint8_t lowest = 3;
static constexpr uint8_t highest = 123;
static constexpr uint8_t expected[] = { 'c',
'P',
'M',
'J',
'U',
'A',
'%',
'h',
'Q',
'F',
'q',
'i',
'$',
'E',
'o' };
};
template <>
struct uniform_integer_test_params<int8_t> {
static constexpr int8_t lowest = -27;
static constexpr int8_t highest = 73;
static constexpr int8_t expected[] = { '5',
'%',
'#',
' ',
'*',
25,
2,
'9',
'&',
29,
'A',
':',
1,
28,
'?' };
};
template <>
struct uniform_integer_test_params<uint16_t> {
static constexpr uint16_t lowest = 123;
static constexpr uint16_t highest = 33333;
static constexpr uint16_t expected[] = { 26684,
21417,
20658,
19791,
22896,
17433,
9806,
27948,
21767,
18588,
30556,
28244,
9439,
18293,
29949 };
};
template <>
struct uniform_integer_test_params<int16_t> {
static constexpr int16_t lowest = -17222;
static constexpr int16_t highest = 17222;
static constexpr int16_t expected[] = { 10326,
4863,
4076,
3177,
6397,
731,
-7179,
11637,
5226,
1929,
14342,
11944,
-7560,
1623,
13712 };
};
template <>
struct uniform_integer_test_params<uint32_t> {
static constexpr uint32_t lowest = 17222;
static constexpr uint32_t highest = 234234;
static constexpr uint32_t expected[] = { 190784,
156367,
151409,
145743,
166032,
130337,
80501,
199046,
158654,
137883,
216091,
200981,
78099,
135954,
212120 };
};
template <>
struct uniform_integer_test_params<int32_t> {
static constexpr int32_t lowest = -237272;
static constexpr int32_t highest = 234234;
static constexpr int32_t expected[] = { 139829,
65050,
54278,
41969,
86051,
8494,
-99785,
157781,
70021,
24890,
194815,
161985,
-105004,
20699,
186186 };
};
template <>
struct uniform_integer_test_params<uint64_t> {
static constexpr uint64_t lowest = 1234;
static constexpr uint64_t highest = 1234567890;
static constexpr uint64_t expected[] = { 987382749,
763380386,
846572137,
359990258,
804599765,
1131353566,
346324913,
1108760730,
1141693933,
856999148,
879390623,
1149485521,
900556586,
952385958,
807916408 };
};
template <>
struct uniform_integer_test_params<int64_t> {
static constexpr int64_t lowest = -1234567890;
static constexpr int64_t highest = 1234567890;
static constexpr int64_t expected[] = { 740197113,
292191940,
458575608,
-514589122,
374630781,
1028139036,
-541919840,
982953318,
1048819790,
479429651,
524212647,
1064402981,
566544615,
670203462,
381264073 };
};
// We need these definitions for C++14 and earlier, but
// GCC will complain about them in newer C++ standards
#if __cplusplus <= 201402L
constexpr bool uniform_integer_test_params<bool>::expected[];
constexpr char uniform_integer_test_params<char>::expected[];
constexpr uint8_t uniform_integer_test_params<uint8_t>::expected[];
constexpr int8_t uniform_integer_test_params<int8_t>::expected[];
constexpr uint16_t uniform_integer_test_params<uint16_t>::expected[];
constexpr int16_t uniform_integer_test_params<int16_t>::expected[];
constexpr uint32_t uniform_integer_test_params<uint32_t>::expected[];
constexpr int32_t uniform_integer_test_params<int32_t>::expected[];
constexpr uint64_t uniform_integer_test_params<uint64_t>::expected[];
constexpr int64_t uniform_integer_test_params<int64_t>::expected[];
#endif
}
TEMPLATE_TEST_CASE( "uniform_integer_distribution is reproducible",
"[rng][distribution][approvals]",
bool,
char,
uint8_t,
int8_t,
uint16_t,
int16_t,
uint32_t,
int32_t,
uint64_t,
int64_t) {
Catch::SimplePcg32 pcg( 0xaabb'ccdd );
constexpr auto lowest = uniform_integer_test_params<TestType>::lowest;
constexpr auto highest = uniform_integer_test_params<TestType>::highest;
Catch::uniform_integer_distribution<TestType> dist(lowest, highest);
constexpr auto iters = 15;
std::array<TestType, iters> generated;
for (int i = 0; i < iters; ++i) {
generated[i] = dist( pcg );
}
REQUIRE_THAT(generated, Catch::Matchers::RangeEquals(uniform_integer_test_params<TestType>::expected));
}
namespace {
template <typename T>
struct uniform_fp_test_params;
template<>
struct uniform_fp_test_params<float> {
// These are exactly representable
static constexpr float lowest = -256.125f;
static constexpr float highest = 385.125f;
// These are just round-trip formatted
static constexpr float expected[] = { 92.56961f,
-23.170044f,
310.81833f,
-53.023132f,
105.03287f,
198.77591f,
-172.72931f,
51.805176f,
-241.10156f,
64.66101f,
212.12509f,
-49.24292f,
-177.1399f,
245.23679f,
173.22421f };
};
template <>
struct uniform_fp_test_params<double> {
// These are exactly representable
static constexpr double lowest = -234582.9921875;
static constexpr double highest = 261238.015625;
// These are just round-trip formatted
static constexpr double expected[] = { 35031.207052832615,
203783.3401838024,
44667.940405848756,
-170100.5877224467,
-222966.7418051684,
127472.72630072923,
-173510.88209096913,
97394.16172239158,
119123.6921592663,
22595.741022785165,
8988.68409120926,
136906.86520606978,
33369.19104222473,
60912.7615841752,
-149060.05936760217 };
};
// We need these definitions for C++14 and earlier, but
// GCC will complain about them in newer C++ standards
#if __cplusplus <= 201402L
constexpr float uniform_fp_test_params<float>::expected[];
constexpr double uniform_fp_test_params<double>::expected[];
#endif
} // namespace
TEMPLATE_TEST_CASE( "uniform_floating_point_distribution is reproducible",
"[rng][distribution][floating-point][approvals]",
float,
double ) {
Catch::SimplePcg32 pcg( 0xaabb'aabb );
const auto lowest = uniform_fp_test_params<TestType>::lowest;
const auto highest = uniform_fp_test_params<TestType>::highest;
Catch::uniform_floating_point_distribution<TestType> dist( lowest, highest );
constexpr auto iters = 15;
std::array<TestType, iters> generated;
for ( int i = 0; i < iters; ++i ) {
generated[i] = dist( pcg );
}
REQUIRE_THAT( generated, Catch::Matchers::RangeEquals( uniform_fp_test_params<TestType>::expected ) );
}
TEMPLATE_TEST_CASE( "uniform_floating_point_distribution can handle unitary ranges",
"[rng][distribution][floating-point][approvals]",
float,
double ) {
std::random_device rd;
auto seed = rd();
CAPTURE( seed );
Catch::SimplePcg32 pcg( seed );
const auto highest = uniform_fp_test_params<TestType>::highest;
Catch::uniform_floating_point_distribution<TestType> dist( highest,
highest );
constexpr auto iters = 20;
for (int i = 0; i < iters; ++i) {
REQUIRE( Catch::Detail::directCompare( dist( pcg ), highest ) );
}
}

View File

@@ -12,7 +12,6 @@
#include <catch2/catch_config.hpp>
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_registry.hpp>
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_list.hpp>
@@ -110,7 +109,9 @@ TEST_CASE( "Reporter's write listings to provided stream", "[reporters]" ) {
auto sstream = Catch::Detail::make_unique<StringIStream>();
auto& sstreamRef = *sstream.get();
Catch::Config config( Catch::ConfigData{} );
Catch::ConfigData cfg_data;
cfg_data.rngSeed = 1234;
Catch::Config config( cfg_data );
auto reporter = factory.second->create( Catch::ReporterConfig{
&config, CATCH_MOVE( sstream ), Catch::ColourMode::None, {} } );
@@ -164,7 +165,7 @@ namespace {
std::vector<std::string>& recorder,
Catch::IConfig const* config ):
EventListenerBase( config ),
m_witness( witness ),
m_witness( CATCH_MOVE(witness) ),
m_recorder( recorder )
{}
@@ -182,7 +183,7 @@ namespace {
std::vector<std::string>& recorder,
Catch::ReporterConfig&& config ):
StreamingReporterBase( CATCH_MOVE(config) ),
m_witness( witness ),
m_witness( CATCH_MOVE(witness) ),
m_recorder( recorder )
{}

View File

@@ -177,7 +177,7 @@ TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") {
STATIC_REQUIRE_FALSE(sr1.empty());
STATIC_REQUIRE(sr1.size() == 3);
using Catch::operator"" _sr;
using Catch::operator""_sr;
constexpr auto sr2 = ""_sr;
STATIC_REQUIRE(sr2.empty());
STATIC_REQUIRE(sr2.size() == 0);

View File

@@ -98,7 +98,20 @@ TEST_CASE( "Test case with identical tags keeps just one", "[tags]" ) {
REQUIRE( testCase.tags[0] == Tag( "tag1" ) );
}
TEST_CASE( "Empty tag is not allowed" ) {
REQUIRE_THROWS( Catch::TestCaseInfo(
"", { "fake test name", "[]" }, dummySourceLineInfo ) );
TEST_CASE("Mismatched square brackets in tags are caught and reported",
"[tags][approvals]") {
using Catch::TestCaseInfo;
using Catch::Matchers::ContainsSubstring;
REQUIRE_THROWS_WITH( TestCaseInfo( "",
{ "test with unclosed tag", "[abc" },
dummySourceLineInfo ),
ContainsSubstring("registering test case 'test with unclosed tag'") );
REQUIRE_THROWS_WITH( TestCaseInfo( "",
{ "test with nested tags", "[abc[def]]" },
dummySourceLineInfo ),
ContainsSubstring("registering test case 'test with nested tags'") );
REQUIRE_THROWS_WITH( TestCaseInfo( "",
{ "test with superfluous close tags", "[abc][def]]" },
dummySourceLineInfo ),
ContainsSubstring("registering test case 'test with superfluous close tags'") );
}