| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 | 
							
- //              Copyright Catch2 Authors
 
- // Distributed under the Boost Software License, Version 1.0.
 
- //   (See accompanying file LICENSE_1_0.txt or copy at
 
- //        https://www.boost.org/LICENSE_1_0.txt)
 
- // SPDX-License-Identifier: BSL-1.0
 
- #if defined( __GNUC__ ) || defined( __clang__ )
 
- #    pragma GCC diagnostic ignored "-Wfloat-equal"
 
- #endif
 
- #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>
 
- // Tests of generator implementation details
 
- TEST_CASE("Generators internals", "[generators][internals]") {
 
-     using namespace Catch::Generators;
 
-     SECTION("Single value") {
 
-         auto gen = value(123);
 
-         REQUIRE(gen.get() == 123);
 
-         REQUIRE_FALSE(gen.next());
 
-     }
 
-     SECTION("Preset values") {
 
-         auto gen = values({ 1, 3, 5 });
 
-         REQUIRE(gen.get() == 1);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 3);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 5);
 
-         REQUIRE_FALSE(gen.next());
 
-     }
 
-     SECTION("Generator combinator") {
 
-         auto gen = makeGenerators(1, 5, values({ 2, 4 }), 0);
 
-         REQUIRE(gen.get() == 1);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 5);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 2);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 4);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 0);
 
-         REQUIRE_FALSE(gen.next());
 
-     }
 
-     SECTION("Explicitly typed generator sequence") {
 
-         auto gen = makeGenerators(as<std::string>{}, "aa", "bb", "cc");
 
-         // This just checks that the type is std::string:
 
-         REQUIRE(gen.get().size() == 2);
 
-         // Iterate over the generator
 
-         REQUIRE(gen.get() == "aa");
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == "bb");
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == "cc");
 
-         REQUIRE_FALSE(gen.next());
 
-     }
 
-     SECTION("Filter generator") {
 
-         // Normal usage
 
-         SECTION("Simple filtering") {
 
-             auto gen = filter([](int i) { return i != 2; }, values({ 2, 1, 2, 3, 2, 2 }));
 
-             REQUIRE(gen.get() == 1);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 3);
 
-             REQUIRE_FALSE(gen.next());
 
-         }
 
-         SECTION("Filter out multiple elements at the start and end") {
 
-             auto gen = filter([](int i) { return i != 2; }, values({ 2, 2, 1, 3, 2, 2 }));
 
-             REQUIRE(gen.get() == 1);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 3);
 
-             REQUIRE_FALSE(gen.next());
 
-         }
 
-         SECTION("Throws on construction if it can't get initial element") {
 
-             REQUIRE_THROWS_AS(filter([](int) { return false; }, value(1)), Catch::GeneratorException);
 
-             REQUIRE_THROWS_AS(
 
-                 filter([](int) { return false; }, values({ 1, 2, 3 })),
 
-                 Catch::GeneratorException);
 
-         }
 
-     }
 
-     SECTION("Take generator") {
 
-         SECTION("Take less") {
 
-             auto gen = take(2, values({ 1, 2, 3 }));
 
-             REQUIRE(gen.get() == 1);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 2);
 
-             REQUIRE_FALSE(gen.next());
 
-         }
 
-         SECTION("Take more") {
 
-             auto gen = take(2, value(1));
 
-             REQUIRE(gen.get() == 1);
 
-             REQUIRE_FALSE(gen.next());
 
-         }
 
-     }
 
-     SECTION("Map with explicit return type") {
 
-         auto gen = map<double>([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
 
-         REQUIRE(gen.get() == 2.0);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 4.0);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 6.0);
 
-         REQUIRE_FALSE(gen.next());
 
-     }
 
-     SECTION("Map with deduced return type") {
 
-         auto gen = map([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
 
-         REQUIRE(gen.get() == 2.0);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 4.0);
 
-         REQUIRE(gen.next());
 
-         REQUIRE(gen.get() == 6.0);
 
-         REQUIRE_FALSE(gen.next());
 
-     }
 
-     SECTION("Repeat") {
 
-         SECTION("Singular repeat") {
 
-             auto gen = repeat(1, value(3));
 
-             REQUIRE(gen.get() == 3);
 
-             REQUIRE_FALSE(gen.next());
 
-         }
 
-         SECTION("Actual repeat") {
 
-             auto gen = repeat(2, values({ 1, 2, 3 }));
 
-             REQUIRE(gen.get() == 1);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 2);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 3);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 1);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 2);
 
-             REQUIRE(gen.next());
 
-             REQUIRE(gen.get() == 3);
 
-             REQUIRE_FALSE(gen.next());
 
-         }
 
-     }
 
-     SECTION("Range") {
 
-         SECTION("Positive auto step") {
 
-             SECTION("Integer") {
 
-                 auto gen = range(-2, 2);
 
-                 REQUIRE(gen.get() == -2);
 
-                 REQUIRE(gen.next());
 
-                 REQUIRE(gen.get() == -1);
 
-                 REQUIRE(gen.next());
 
-                 REQUIRE(gen.get() == 0);
 
-                 REQUIRE(gen.next());
 
-                 REQUIRE(gen.get() == 1);
 
-                 REQUIRE_FALSE(gen.next());
 
-             }
 
-         }
 
-         SECTION("Negative auto step") {
 
-             SECTION("Integer") {
 
-                 auto gen = range(2, -2);
 
-                 REQUIRE(gen.get() == 2);
 
-                 REQUIRE(gen.next());
 
-                 REQUIRE(gen.get() == 1);
 
-                 REQUIRE(gen.next());
 
-                 REQUIRE(gen.get() == 0);
 
-                 REQUIRE(gen.next());
 
-                 REQUIRE(gen.get() == -1);
 
-                 REQUIRE_FALSE(gen.next());
 
-             }
 
-         }
 
-         SECTION("Positive manual step") {
 
-             SECTION("Integer") {
 
-                 SECTION("Exact") {
 
-                     auto gen = range(-7, 5, 3);
 
-                     REQUIRE(gen.get() == -7);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -4);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -1);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 2);
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-                 SECTION("Slightly over end") {
 
-                     auto gen = range(-7, 4, 3);
 
-                     REQUIRE(gen.get() == -7);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -4);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -1);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 2);
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-                 SECTION("Slightly under end") {
 
-                     auto gen = range(-7, 6, 3);
 
-                     REQUIRE(gen.get() == -7);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -4);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -1);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 2);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 5);
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-             }
 
-             SECTION("Floating Point") {
 
-                 using Catch::Approx;
 
-                 SECTION("Exact") {
 
-                     const auto rangeStart = -1.;
 
-                     const auto rangeEnd = 1.;
 
-                     const auto step = .1;
 
-                     auto gen = range(rangeStart, rangeEnd, step);
 
-                     auto expected = rangeStart;
 
-                     while( (rangeEnd - expected) > step ) {
 
-                         INFO( "Current expected value is " << expected );
 
-                         REQUIRE(gen.get() == Approx(expected));
 
-                         REQUIRE(gen.next());
 
-                         expected += step;
 
-                     }
 
-                     REQUIRE(gen.get() == Approx( rangeEnd ) );
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-                 SECTION("Slightly over end") {
 
-                     const auto rangeStart = -1.;
 
-                     const auto rangeEnd = 1.;
 
-                     const auto step = .3;
 
-                     auto gen = range(rangeStart, rangeEnd, step);
 
-                     auto expected = rangeStart;
 
-                     while( (rangeEnd - expected) > step ) {
 
-                        INFO( "Current expected value is " << expected );
 
-                        REQUIRE(gen.get() == Approx(expected));
 
-                        REQUIRE(gen.next());
 
-                        expected += step;
 
-                     }
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-                 SECTION("Slightly under end") {
 
-                     const auto rangeStart = -1.;
 
-                     const auto rangeEnd = .9;
 
-                     const auto step = .3;
 
-                     auto gen = range(rangeStart, rangeEnd, step);
 
-                     auto expected = rangeStart;
 
-                     while( (rangeEnd - expected) > step ) {
 
-                        INFO( "Current expected value is " << expected );
 
-                        REQUIRE(gen.get() == Approx(expected));
 
-                        REQUIRE(gen.next());
 
-                        expected += step;
 
-                     }
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-             }
 
-         }
 
-         SECTION("Negative manual step") {
 
-             SECTION("Integer") {
 
-                 SECTION("Exact") {
 
-                     auto gen = range(5, -7, -3);
 
-                     REQUIRE(gen.get() == 5);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 2);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -1);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -4);
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-                 SECTION("Slightly over end") {
 
-                     auto gen = range(5, -6, -3);
 
-                     REQUIRE(gen.get() == 5);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 2);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -1);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -4);
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-                 SECTION("Slightly under end") {
 
-                     auto gen = range(5, -8, -3);
 
-                     REQUIRE(gen.get() == 5);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == 2);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -1);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -4);
 
-                     REQUIRE(gen.next());
 
-                     REQUIRE(gen.get() == -7);
 
-                     REQUIRE_FALSE(gen.next());
 
-                 }
 
-             }
 
-         }
 
-     }
 
- }
 
- // todo: uncopyable type used in a generator
 
- //  idea: uncopyable tag type for a stupid generator
 
- namespace {
 
- struct non_copyable {
 
-     non_copyable() = default;
 
-     non_copyable(non_copyable const&) = delete;
 
-     non_copyable& operator=(non_copyable const&) = delete;
 
-     int value = -1;
 
- };
 
- // This class shows how to implement a simple generator for Catch tests
 
- class TestGen : public Catch::Generators::IGenerator<int> {
 
-     int current_number;
 
- public:
 
-     TestGen(non_copyable const& nc):
 
-         current_number(nc.value) {}
 
-     int const& get() const override;
 
-     bool next() override {
 
-         return false;
 
-     }
 
- };
 
- // Avoids -Wweak-vtables
 
- int const& TestGen::get() const {
 
-     return current_number;
 
- }
 
- }
 
- TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
 
-     auto value = GENERATE(take(10, random(0, 10)));
 
-     non_copyable nc; nc.value = value;
 
-     // neither `GENERATE_COPY` nor plain `GENERATE` would compile here
 
-     auto value2 = GENERATE_REF(Catch::Generators::GeneratorWrapper<int>(Catch::Detail::make_unique<TestGen>(nc)));
 
-     REQUIRE(value == value2);
 
- }
 
- TEST_CASE("#1809 - GENERATE_COPY and SingleValueGenerator does not compile", "[generators][compilation][approvals]") {
 
-     // Verify Issue #1809 fix, only needs to compile.
 
-     auto a = GENERATE_COPY(1, 2);
 
-     (void)a;
 
-     auto b = GENERATE_COPY(as<long>{}, 1, 2);
 
-     (void)b;
 
-     int i = 1;
 
-     int j = 2;
 
-     auto c = GENERATE_COPY(i, j);
 
-     (void)c;
 
-     auto d = GENERATE_COPY(as<long>{}, i, j);
 
-     (void)d;
 
-     SUCCEED();
 
- }
 
- TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
 
-     SECTION("Integer") {
 
-         auto random1 = Catch::Generators::random(0, 1000);
 
-         auto random2 = Catch::Generators::random(0, 1000);
 
-         size_t same = 0;
 
-         for (size_t i = 0; i < 1000; ++i) {
 
-             same += random1.get() == random2.get();
 
-             random1.next(); random2.next();
 
-         }
 
-         // Because the previous low bound failed CI couple of times,
 
-         // we use a very high threshold of 20% before failure is reported.
 
-         REQUIRE(same < 200);
 
-     }
 
-     SECTION("Float") {
 
-         auto random1 = Catch::Generators::random(0., 1000.);
 
-         auto random2 = Catch::Generators::random(0., 1000.);
 
-         size_t same = 0;
 
-         for (size_t i = 0; i < 1000; ++i) {
 
-             same += random1.get() == random2.get();
 
-             random1.next(); random2.next();
 
-         }
 
-         // Because the previous low bound failed CI couple of times,
 
-         // we use a very high threshold of 20% before failure is reported.
 
-         REQUIRE(same < 200);
 
-     }
 
- }
 
- TEST_CASE("#2040 - infinite compilation recursion in GENERATE with MSVC", "[generators][compilation][approvals]") {
 
-     int x = 42;
 
-     auto test = GENERATE_COPY(1, x, 2 * x);
 
-     CHECK(test < 100);
 
- }
 
- namespace {
 
-     static bool always_true(int) {
 
-         return true;
 
-     }
 
-     static bool is_even(int n) {
 
-         return n % 2 == 0;
 
-     }
 
-     static bool is_multiple_of_3(int n) {
 
-         return n % 3 == 0;
 
-     }
 
- }
 
- TEST_CASE("GENERATE handles function (pointers)", "[generators][compilation][approvals]") {
 
-     auto f = GENERATE(always_true, is_even, is_multiple_of_3);
 
-     REQUIRE(f(6));
 
- }
 
- TEST_CASE("GENERATE decays arrays", "[generators][compilation][approvals]") {
 
-     auto str = GENERATE("abc", "def", "gh");
 
-     STATIC_REQUIRE(std::is_same<decltype(str), const char*>::value);
 
- }
 
- TEST_CASE("Generators count returned elements", "[generators][approvals]") {
 
-     auto generator = Catch::Generators::FixedValuesGenerator<int>( { 1, 2, 3 } );
 
-     REQUIRE( generator.currentElementIndex() == 0 );
 
-     REQUIRE( generator.countedNext() );
 
-     REQUIRE( generator.currentElementIndex() == 1 );
 
-     REQUIRE( generator.countedNext() );
 
-     REQUIRE( generator.currentElementIndex() == 2 );
 
-     REQUIRE_FALSE( generator.countedNext() );
 
-     REQUIRE( generator.currentElementIndex() == 2 );
 
- }
 
- TEST_CASE( "Generators can stringify their elements",
 
-            "[generators][approvals]" ) {
 
-     auto generator =
 
-         Catch::Generators::FixedValuesGenerator<int>( { 1, 2, 3 } );
 
-     REQUIRE( generator.currentElementAsString() == "1"_catch_sr );
 
-     REQUIRE( generator.countedNext() );
 
-     REQUIRE( generator.currentElementAsString() == "2"_catch_sr );
 
-     REQUIRE( generator.countedNext() );
 
-     REQUIRE( generator.currentElementAsString() == "3"_catch_sr );
 
- }
 
- namespace {
 
-     class CustomStringifyGenerator
 
-         : public Catch::Generators::IGenerator<bool> {
 
-         bool m_first = true;
 
-         std::string stringifyImpl() const override {
 
-             return m_first ? "first" : "second";
 
-         }
 
-         bool next() override {
 
-             if ( m_first ) {
 
-                 m_first = false;
 
-                 return true;
 
-             }
 
-             return false;
 
-         }
 
-     public:
 
-         bool const& get() const override;
 
-     };
 
-     // Avoids -Wweak-vtables
 
-     bool const& CustomStringifyGenerator::get() const { return m_first; }
 
- } // namespace
 
- TEST_CASE( "Generators can override element stringification",
 
-            "[generators][approvals]" ) {
 
-     CustomStringifyGenerator generator;
 
-     REQUIRE( generator.currentElementAsString() == "first"_catch_sr );
 
-     REQUIRE( generator.countedNext() );
 
-     REQUIRE( generator.currentElementAsString() == "second"_catch_sr );
 
- }
 
- namespace {
 
-     class StringifyCountingGenerator
 
-         : public Catch::Generators::IGenerator<bool> {
 
-         bool m_first = true;
 
-         mutable size_t m_stringificationCalls = 0;
 
-         std::string stringifyImpl() const override {
 
-             ++m_stringificationCalls;
 
-             return m_first ? "first" : "second";
 
-         }
 
-         bool next() override {
 
-             if ( m_first ) {
 
-                 m_first = false;
 
-                 return true;
 
-             }
 
-             return false;
 
-         }
 
-     public:
 
-         bool const& get() const override;
 
-         size_t stringificationCalls() const { return m_stringificationCalls; }
 
-     };
 
-     // Avoids -Wweak-vtables
 
-     bool const& StringifyCountingGenerator::get() const { return m_first; }
 
- } // namespace
 
- TEST_CASE( "Generator element stringification is cached",
 
-            "[generators][approvals]" ) {
 
-     StringifyCountingGenerator generator;
 
-     REQUIRE( generator.currentElementAsString() == "first"_catch_sr );
 
-     REQUIRE( generator.currentElementAsString() == "first"_catch_sr );
 
-     REQUIRE( generator.currentElementAsString() == "first"_catch_sr );
 
-     REQUIRE( generator.currentElementAsString() == "first"_catch_sr );
 
-     REQUIRE( generator.currentElementAsString() == "first"_catch_sr );
 
-     REQUIRE( generator.stringificationCalls() == 1 );
 
- }
 
- TEST_CASE( "Random generators can be seeded", "[generators][approvals]" ) {
 
-     SECTION( "Integer generator" ) {
 
-         using Catch::Generators::RandomIntegerGenerator;
 
-         RandomIntegerGenerator<int> rng1( 0, 100, 0x1234 ),
 
-                                     rng2( 0, 100, 0x1234 );
 
-         for ( size_t i = 0; i < 10; ++i ) {
 
-             REQUIRE( rng1.get() == rng2.get() );
 
-             rng1.next(); rng2.next();
 
-         }
 
-     }
 
-     SECTION("Float generator") {
 
-         using Catch::Generators::RandomFloatingGenerator;
 
-         RandomFloatingGenerator<double> rng1( 0., 100., 0x1234 ),
 
-                                         rng2( 0., 100., 0x1234 );
 
-         for ( size_t i = 0; i < 10; ++i ) {
 
-             REQUIRE( rng1.get() == rng2.get() );
 
-             rng1.next();
 
-             rng2.next();
 
-         }
 
-     }
 
- }
 
 
  |