Home | History | Annotate | Download | only in UsageTests
      1 #include "catch.hpp"
      2 
      3 #include <cstring>
      4 
      5 
      6 // Generators and sections can be nested freely
      7 TEST_CASE("Generators -- simple", "[generators]") {
      8     auto i = GENERATE(1, 2, 3);
      9     SECTION("one") {
     10         auto j = GENERATE(values({ -3, -2, -1 }));
     11         REQUIRE(j < i);
     12     }
     13 
     14     SECTION("two") {
     15         // You can also explicitly set type for generators via Catch::Generators::as
     16         auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
     17         REQUIRE(4u * i > str.size());
     18     }
     19 }
     20 
     21 // You can create a cartesian-product of generators by creating multiple ones
     22 TEST_CASE("3x3x3 ints", "[generators]") {
     23     auto x = GENERATE(1, 2, 3);
     24     auto y = GENERATE(4, 5, 6);
     25     auto z = GENERATE(7, 8, 9);
     26     // These assertions will be run 27 times (3x3x3)
     27     CHECK(x < y);
     28     CHECK(y < z);
     29     REQUIRE(x < z);
     30 }
     31 
     32 // You can also create data tuples
     33 TEST_CASE("tables", "[generators]") {
     34     // Note that this will not compile with libstdc++ older than libstdc++6
     35     // See https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
     36     // for possible workarounds
     37     //    auto data = GENERATE(table<char const*, int>({
     38     //        {"first", 5},
     39     //        {"second", 6},
     40     //        {"third", 5},
     41     //        {"etc...", 6}
     42     //    }));
     43 
     44     // Workaround for the libstdc++ bug mentioned above
     45     using tuple_type = std::tuple<char const*, int>;
     46     auto data = GENERATE(table<char const*, int>({
     47         tuple_type{"first", 5},
     48         tuple_type{"second", 6},
     49         tuple_type{"third", 5},
     50         tuple_type{"etc...", 6}
     51     }));
     52 
     53     REQUIRE(strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)));
     54 }
     55 
     56 
     57 #ifdef __cpp_structured_bindings
     58 
     59 // Structured bindings make the table utility much nicer to use
     60 TEST_CASE( "strlen2", "[approvals][generators]" ) {
     61     auto [test_input, expected] = GENERATE( table<std::string, size_t>({
     62             {"one", 3},
     63             {"two", 3},
     64             {"three", 5},
     65             {"four", 4}
     66         }));
     67 
     68     REQUIRE( test_input.size() == expected );
     69 }
     70 #endif
     71 
     72 
     73 // An alternate way of doing data tables without structured bindings
     74 struct Data { std::string str; size_t len; };
     75 
     76 TEST_CASE( "strlen3", "[generators]" ) {
     77     auto data = GENERATE( values<Data>({
     78             {"one", 3},
     79             {"two", 3},
     80             {"three", 5},
     81             {"four", 4}
     82         }));
     83 
     84     REQUIRE( data.str.size() == data.len );
     85 }
     86 
     87 
     88 
     89 #ifdef __cpp_structured_bindings
     90 
     91 // Based on example from https://docs.cucumber.io/gherkin/reference/#scenario-outline
     92 // (thanks to https://github.com/catchorg/Catch2/issues/850#issuecomment-399504851)
     93 
     94 // Note that GIVEN, WHEN, and THEN now forward onto DYNAMIC_SECTION instead of SECTION.
     95 // DYNAMIC_SECTION takes its name as a stringstream-style expression, so can be formatted using
     96 // variables in scope - such as the generated variables here. This reads quite nicely in the
     97 // test name output (the full scenario description).
     98 
     99 static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
    100 
    101 SCENARIO("Eating cucumbers", "[generators][approvals]") {
    102 
    103     auto [start, eat, left] = GENERATE( table<int,int,int> ({
    104             { 12, 5, 7 },
    105             { 20, 5, 15 }
    106         }));
    107 
    108     GIVEN( "there are " << start << " cucumbers" )
    109     WHEN( "I eat " << eat << " cucumbers" )
    110     THEN( "I should have " << left << " cucumbers" ) {
    111         REQUIRE( eatCucumbers( start, eat ) == left );
    112     }
    113 }
    114 #endif
    115 
    116 // There are also some generic generator manipulators
    117 TEST_CASE("Generators -- adapters", "[generators][generic]") {
    118     // TODO: This won't work yet, introduce GENERATE_VAR?
    119     //auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 });
    120     SECTION("Filtering by predicate") {
    121         SECTION("Basic usage") {
    122             // This filters out all odd (false) numbers, giving [2, 4, 6]
    123             auto i = GENERATE(filter([] (int val) { return val % 2 == 0; }, values({ 1, 2, 3, 4, 5, 6 })));
    124             REQUIRE(i % 2 == 0);
    125         }
    126         SECTION("Throws if there are no matching values") {
    127             using namespace Catch::Generators;
    128             REQUIRE_THROWS_AS(filter([] (int) {return false; }, value(1)), Catch::GeneratorException);
    129         }
    130     }
    131     SECTION("Shortening a range") {
    132         // This takes the first 3 elements from the values, giving back [1, 2, 3]
    133         auto i = GENERATE(take(3, values({ 1, 2, 3, 4, 5, 6 })));
    134         REQUIRE(i < 4);
    135     }
    136     SECTION("Transforming elements") {
    137         SECTION("Same type") {
    138             // This doubles values [1, 2, 3] into [2, 4, 6]
    139             auto i = GENERATE(map([] (int val) { return val * 2; }, values({ 1, 2, 3 })));
    140             REQUIRE(i % 2 == 0);
    141         }
    142         SECTION("Different type") {
    143             // This takes a generator that returns ints and maps them into strings
    144             auto i = GENERATE(map<std::string>([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
    145             REQUIRE(i.size() == 1);
    146         }
    147     }
    148     SECTION("Repeating a generator") {
    149         // This will return values [1, 2, 3, 1, 2, 3]
    150         auto j = GENERATE(repeat(2, values({ 1, 2, 3 })));
    151         REQUIRE(j > 0);
    152     }
    153     SECTION("Chunking a generator into sized pieces") {
    154         SECTION("Number of elements in source is divisible by chunk size") {
    155             auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3, 3 })));
    156             REQUIRE(chunk2.size() == 2);
    157             REQUIRE(chunk2.front() == chunk2.back());
    158         }
    159         SECTION("Number of elements in source is not divisible by chunk size") {
    160             auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3 })));
    161             REQUIRE(chunk2.size() == 2);
    162             REQUIRE(chunk2.front() == chunk2.back());
    163             REQUIRE(chunk2.front() < 3);
    164         }
    165         SECTION("Throws on too small generators") {
    166             using namespace Catch::Generators;
    167             REQUIRE_THROWS_AS(chunk(2, value(1)), Catch::GeneratorException);
    168         }
    169     }
    170 }
    171 
    172 // Note that because of the non-reproducibility of distributions,
    173 // anything involving the random generators cannot be part of approvals
    174 TEST_CASE("Random generator", "[generators][.][approvals]") {
    175     SECTION("Infer int from integral arguments") {
    176         auto val = GENERATE(take(4, random(0, 1)));
    177         STATIC_REQUIRE(std::is_same<decltype(val), int>::value);
    178         static_cast<void>(val); // Silence VS 2015 unused variable warning
    179     }
    180     SECTION("Infer double from double arguments") {
    181         auto val = GENERATE(take(4, random(0., 1.)));
    182         STATIC_REQUIRE(std::is_same<decltype(val), double>::value);
    183         static_cast<void>(val); // Silence VS 2015 unused variable warning
    184     }
    185 }
    186