1 #include <catch2/catch.hpp> 2 #include <rapidcheck/catch.h> 3 4 #include "rapidcheck/shrinkable/Operations.h" 5 #include "rapidcheck/shrinkable/Create.h" 6 7 #include "util/Generators.h" 8 9 using namespace rc; 10 11 TEST_CASE("shrinkable::all") { 12 prop("returns true if predicate returns true for all", __anon0fd8dcd30102null13 [] { 14 // TODO sized ranged 15 int x = *gen::inRange<int>(1, 5); 16 const auto shrinkable = shrinkable::shrinkRecur( 17 x, [](int y) { return seq::range(y - 1, 0); }); 18 19 RC_ASSERT(shrinkable::all( 20 shrinkable, 21 [](const Shrinkable<int> &s) { return s.value() != 0; })); 22 }); 23 24 prop("returns true if predicate returns false for at least one shrinkable", __anon0fd8dcd30402null25 [] { 26 // TODO sized ranged 27 int x = *gen::inRange<int>(0, 5); 28 const auto shrinkable = shrinkable::just( 29 x, seq::map(seq::range(x - 1, -1), &shrinkable::just<int>)); 30 31 RC_ASSERT(!shrinkable::all(shrinkable, 32 [](const Shrinkable<int> &s) { 33 return s.value() != 0; 34 })); 35 }); 36 } 37 38 TEST_CASE("shrinkable::findLocalMin") { 39 prop("returns the original value if no value matched predicate", __anon0fd8dcd30602(int x) 40 [](int x) { 41 auto result = 42 shrinkable::findLocalMin(shrinkable::just(x), fn::constant(true)); 43 RC_ASSERT(result.first == x); 44 }); 45 46 prop("return zero shrinks if no value matched predicate", __anon0fd8dcd30702null47 [] { 48 auto result = 49 shrinkable::findLocalMin(shrinkable::just(0), fn::constant(true)); 50 RC_ASSERT(result.second == 0U); 51 }); 52 53 prop( 54 "searches by descending into the first value of each shrinks Seq that" 55 " matches the predicate", __anon0fd8dcd30802null56 [] { 57 const auto expected = 58 *gen::container<std::vector<int>>(gen::inRange<int>(1, 101)); 59 60 const auto pred = [&](const std::vector<int> &x) { 61 int back = x.back(); 62 // We want to test that the first value is picked so we accept 63 // both zero and the corresponding value in the expected vector 64 // but since zero comes last, that will never be picked 65 return (x.size() <= expected.size()) && 66 ((back == 0) || (back == expected[x.size() - 1])); 67 }; 68 69 const auto shrinkable = 70 shrinkable::shrinkRecur(std::vector<int>(), 71 [](const std::vector<int> &vec) { 72 return seq::map(seq::range<int>(100, -1), 73 [=](int x) { 74 auto shrink = vec; 75 shrink.push_back(x); 76 return shrink; 77 }); 78 }); 79 80 const auto result = shrinkable::findLocalMin(shrinkable, pred); 81 RC_ASSERT(result.first == expected); 82 RC_ASSERT(result.second == expected.size()); 83 }); 84 } 85 86 TEST_CASE("shrinkable::immediateShrinks") { 87 prop( 88 "returns a Seq of the values of the immediate shrinks of the" 89 " Shrinkable", __anon0fd8dcd30c02(int x, const Seq<int> &seq) 90 [](int x, const Seq<int> &seq) { 91 const auto shrinkable = 92 shrinkable::just(x, seq::map(seq, &shrinkable::just<int>)); 93 RC_ASSERT(shrinkable::immediateShrinks(shrinkable) == seq); 94 }); 95 } 96 97 TEST_CASE("shrinkable::walkPath") { 98 prop("returns the shrinkable at the end of the path", __anon0fd8dcd30d02null99 [] { 100 const auto path = *gen::container<std::vector<std::size_t>>( 101 gen::inRange<std::size_t>(0, 100)); 102 const auto shrinkable = 103 shrinkable::shrinkRecur(std::vector<std::size_t>(), 104 [](const std::vector<std::size_t> &lambdaPath) { 105 return seq::map(seq::index(), 106 [=](std::size_t i) { 107 auto p = lambdaPath; 108 p.push_back(i); 109 return p; 110 }); 111 }); 112 113 const auto result = shrinkable::walkPath(shrinkable, path); 114 RC_ASSERT(result); 115 RC_ASSERT(result->value() == path); 116 }); 117 118 prop("returns something if path never goes outside tree", __anon0fd8dcd31002null119 [] { 120 const auto limit = *gen::inRange<std::size_t>(0, 100); 121 const auto shrinkable = shrinkable::shrinkRecur( 122 std::size_t(0), 123 [=](std::size_t x) { return seq::range<std::size_t>(0, limit); }); 124 auto path = *gen::container<std::vector<std::size_t>>( 125 gen::inRange<std::size_t>(0, limit)); 126 127 const auto result = shrinkable::walkPath(shrinkable, path); 128 RC_ASSERT(result); 129 }); 130 131 prop("returns Nothing if path ever goes outside tree", __anon0fd8dcd31202null132 [] { 133 const auto limit = *gen::inRange<std::size_t>(0, 100); 134 const auto shrinkable = shrinkable::shrinkRecur( 135 std::size_t(0), 136 [=](std::size_t x) { return seq::range<std::size_t>(0, limit); }); 137 auto path = *gen::container<std::vector<std::size_t>>( 138 gen::inRange<std::size_t>(0, limit)); 139 const auto i = *gen::inRange<std::size_t>(0, path.size() + 1); 140 path.insert(begin(path) + i, limit); 141 const auto result = shrinkable::walkPath(shrinkable, path); 142 RC_ASSERT(!result); 143 }); 144 } 145