123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- #include "catch.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
- 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());
- // Completely filtered-out generator should throw on construction
- REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), 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") {
- 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>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new 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();
- }
- // 0.5% seems like a sane bound for random identical elements within 1000 runs
- REQUIRE(same < 5);
- }
- 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();
- }
- // 0.5% seems like a sane bound for random identical elements within 1000 runs
- REQUIRE(same < 5);
- }
- }
|