1 #include "catch.hpp"
2
3 // Tests of generator implementation details
4 TEST_CASE("Generators internals", "[generators][internals]") {
5 using namespace Catch::Generators;
6
7 SECTION("Single value") {
8 auto gen = value(123);
9 REQUIRE(gen.get() == 123);
10 REQUIRE_FALSE(gen.next());
11 }
12 SECTION("Preset values") {
13 auto gen = values({ 1, 3, 5 });
14 REQUIRE(gen.get() == 1);
15 REQUIRE(gen.next());
16 REQUIRE(gen.get() == 3);
17 REQUIRE(gen.next());
18 REQUIRE(gen.get() == 5);
19 REQUIRE_FALSE(gen.next());
20 }
21 SECTION("Generator combinator") {
22 auto gen = makeGenerators(1, 5, values({ 2, 4 }), 0);
23 REQUIRE(gen.get() == 1);
24 REQUIRE(gen.next());
25 REQUIRE(gen.get() == 5);
26 REQUIRE(gen.next());
27 REQUIRE(gen.get() == 2);
28 REQUIRE(gen.next());
29 REQUIRE(gen.get() == 4);
30 REQUIRE(gen.next());
31 REQUIRE(gen.get() == 0);
32 REQUIRE_FALSE(gen.next());
33 }
34 SECTION("Explicitly typed generator sequence") {
35 auto gen = makeGenerators(as<std::string>{}, "aa", "bb", "cc");
36 // This just checks that the type is std::string:
37 REQUIRE(gen.get().size() == 2);
38 // Iterate over the generator
39 REQUIRE(gen.get() == "aa");
40 REQUIRE(gen.next());
41 REQUIRE(gen.get() == "bb");
42 REQUIRE(gen.next());
43 REQUIRE(gen.get() == "cc");
44 REQUIRE_FALSE(gen.next());
45 }
46 SECTION("Filter generator") {
47 // Normal usage
__anone09ecf910102(int i) 48 auto gen = filter([] (int i) { return i != 2; }, values({ 2, 1, 2, 3, 2, 2 }));
49 REQUIRE(gen.get() == 1);
50 REQUIRE(gen.next());
51 REQUIRE(gen.get() == 3);
52 REQUIRE_FALSE(gen.next());
53
54 // Completely filtered-out generator should throw on construction
__anone09ecf910202(int) 55 REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), Catch::GeneratorException);
56 }
57 SECTION("Take generator") {
58 SECTION("Take less") {
59 auto gen = take(2, values({ 1, 2, 3 }));
60 REQUIRE(gen.get() == 1);
61 REQUIRE(gen.next());
62 REQUIRE(gen.get() == 2);
63 REQUIRE_FALSE(gen.next());
64 }
65 SECTION("Take more") {
66 auto gen = take(2, value(1));
67 REQUIRE(gen.get() == 1);
68 REQUIRE_FALSE(gen.next());
69 }
70 }
71 SECTION("Map with explicit return type") {
__anone09ecf910302(int i) 72 auto gen = map<double>([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
73 REQUIRE(gen.get() == 2.0);
74 REQUIRE(gen.next());
75 REQUIRE(gen.get() == 4.0);
76 REQUIRE(gen.next());
77 REQUIRE(gen.get() == 6.0);
78 REQUIRE_FALSE(gen.next());
79 }
80 SECTION("Map with deduced return type") {
__anone09ecf910402(int i) 81 auto gen = map([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
82 REQUIRE(gen.get() == 2.0);
83 REQUIRE(gen.next());
84 REQUIRE(gen.get() == 4.0);
85 REQUIRE(gen.next());
86 REQUIRE(gen.get() == 6.0);
87 REQUIRE_FALSE(gen.next());
88 }
89 SECTION("Repeat") {
90 SECTION("Singular repeat") {
91 auto gen = repeat(1, value(3));
92 REQUIRE(gen.get() == 3);
93 REQUIRE_FALSE(gen.next());
94 }
95 SECTION("Actual repeat") {
96 auto gen = repeat(2, values({ 1, 2, 3 }));
97 REQUIRE(gen.get() == 1);
98 REQUIRE(gen.next());
99 REQUIRE(gen.get() == 2);
100 REQUIRE(gen.next());
101 REQUIRE(gen.get() == 3);
102 REQUIRE(gen.next());
103 REQUIRE(gen.get() == 1);
104 REQUIRE(gen.next());
105 REQUIRE(gen.get() == 2);
106 REQUIRE(gen.next());
107 REQUIRE(gen.get() == 3);
108 REQUIRE_FALSE(gen.next());
109 }
110 }
111 SECTION("Range") {
112 SECTION("Positive auto step") {
113 SECTION("Integer") {
114 auto gen = range(-2, 2);
115 REQUIRE(gen.get() == -2);
116 REQUIRE(gen.next());
117 REQUIRE(gen.get() == -1);
118 REQUIRE(gen.next());
119 REQUIRE(gen.get() == 0);
120 REQUIRE(gen.next());
121 REQUIRE(gen.get() == 1);
122 REQUIRE_FALSE(gen.next());
123 }
124 }
125 SECTION("Negative auto step") {
126 SECTION("Integer") {
127 auto gen = range(2, -2);
128 REQUIRE(gen.get() == 2);
129 REQUIRE(gen.next());
130 REQUIRE(gen.get() == 1);
131 REQUIRE(gen.next());
132 REQUIRE(gen.get() == 0);
133 REQUIRE(gen.next());
134 REQUIRE(gen.get() == -1);
135 REQUIRE_FALSE(gen.next());
136 }
137 }
138 SECTION("Positive manual step") {
139 SECTION("Integer") {
140 SECTION("Exact") {
141 auto gen = range(-7, 5, 3);
142 REQUIRE(gen.get() == -7);
143 REQUIRE(gen.next());
144 REQUIRE(gen.get() == -4);
145 REQUIRE(gen.next());
146 REQUIRE(gen.get() == -1);
147 REQUIRE(gen.next());
148 REQUIRE(gen.get() == 2);
149 REQUIRE_FALSE(gen.next());
150 }
151 SECTION("Slightly over end") {
152 auto gen = range(-7, 4, 3);
153 REQUIRE(gen.get() == -7);
154 REQUIRE(gen.next());
155 REQUIRE(gen.get() == -4);
156 REQUIRE(gen.next());
157 REQUIRE(gen.get() == -1);
158 REQUIRE(gen.next());
159 REQUIRE(gen.get() == 2);
160 REQUIRE_FALSE(gen.next());
161 }
162 SECTION("Slightly under end") {
163 auto gen = range(-7, 6, 3);
164 REQUIRE(gen.get() == -7);
165 REQUIRE(gen.next());
166 REQUIRE(gen.get() == -4);
167 REQUIRE(gen.next());
168 REQUIRE(gen.get() == -1);
169 REQUIRE(gen.next());
170 REQUIRE(gen.get() == 2);
171 REQUIRE(gen.next());
172 REQUIRE(gen.get() == 5);
173 REQUIRE_FALSE(gen.next());
174 }
175 }
176
177 SECTION("Floating Point") {
178 SECTION("Exact") {
179 const auto rangeStart = -1.;
180 const auto rangeEnd = 1.;
181 const auto step = .1;
182
183 auto gen = range(rangeStart, rangeEnd, step);
184 auto expected = rangeStart;
185 while( (rangeEnd - expected) > step ) {
186 INFO( "Current expected value is " << expected )
187 REQUIRE(gen.get() == Approx(expected));
188 REQUIRE(gen.next());
189
190 expected += step;
191 }
192 REQUIRE(gen.get() == Approx( rangeEnd ) );
193 REQUIRE_FALSE(gen.next());
194 }
195 SECTION("Slightly over end") {
196 const auto rangeStart = -1.;
197 const auto rangeEnd = 1.;
198 const auto step = .3;
199
200 auto gen = range(rangeStart, rangeEnd, step);
201 auto expected = rangeStart;
202 while( (rangeEnd - expected) > step ) {
203 INFO( "Current expected value is " << expected )
204 REQUIRE(gen.get() == Approx(expected));
205 REQUIRE(gen.next());
206
207 expected += step;
208 }
209 REQUIRE_FALSE(gen.next());
210 }
211 SECTION("Slightly under end") {
212 const auto rangeStart = -1.;
213 const auto rangeEnd = .9;
214 const auto step = .3;
215
216 auto gen = range(rangeStart, rangeEnd, step);
217 auto expected = rangeStart;
218 while( (rangeEnd - expected) > step ) {
219 INFO( "Current expected value is " << expected )
220 REQUIRE(gen.get() == Approx(expected));
221 REQUIRE(gen.next());
222
223 expected += step;
224 }
225 REQUIRE_FALSE(gen.next());
226 }
227 }
228 }
229 SECTION("Negative manual step") {
230 SECTION("Integer") {
231 SECTION("Exact") {
232 auto gen = range(5, -7, -3);
233 REQUIRE(gen.get() == 5);
234 REQUIRE(gen.next());
235 REQUIRE(gen.get() == 2);
236 REQUIRE(gen.next());
237 REQUIRE(gen.get() == -1);
238 REQUIRE(gen.next());
239 REQUIRE(gen.get() == -4);
240 REQUIRE_FALSE(gen.next());
241 }
242 SECTION("Slightly over end") {
243 auto gen = range(5, -6, -3);
244 REQUIRE(gen.get() == 5);
245 REQUIRE(gen.next());
246 REQUIRE(gen.get() == 2);
247 REQUIRE(gen.next());
248 REQUIRE(gen.get() == -1);
249 REQUIRE(gen.next());
250 REQUIRE(gen.get() == -4);
251 REQUIRE_FALSE(gen.next());
252 }
253 SECTION("Slightly under end") {
254 auto gen = range(5, -8, -3);
255 REQUIRE(gen.get() == 5);
256 REQUIRE(gen.next());
257 REQUIRE(gen.get() == 2);
258 REQUIRE(gen.next());
259 REQUIRE(gen.get() == -1);
260 REQUIRE(gen.next());
261 REQUIRE(gen.get() == -4);
262 REQUIRE(gen.next());
263 REQUIRE(gen.get() == -7);
264 REQUIRE_FALSE(gen.next());
265 }
266 }
267 }
268 }
269
270 }
271
272
273 // todo: uncopyable type used in a generator
274 // idea: uncopyable tag type for a stupid generator
275
276 namespace {
277 struct non_copyable {
278 non_copyable() = default;
279 non_copyable(non_copyable const&) = delete;
280 non_copyable& operator=(non_copyable const&) = delete;
281 int value = -1;
282 };
283
284 // This class shows how to implement a simple generator for Catch tests
285 class TestGen : public Catch::Generators::IGenerator<int> {
286 int current_number;
287 public:
288
TestGen(non_copyable const & nc)289 TestGen(non_copyable const& nc):
290 current_number(nc.value) {}
291
292 int const& get() const override;
next()293 bool next() override {
294 return false;
295 }
296 };
297
298 // Avoids -Wweak-vtables
get() const299 int const& TestGen::get() const {
300 return current_number;
301 }
302
303 }
304
305 TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
306 auto value = GENERATE(take(10, random(0, 10)));
307
308 non_copyable nc; nc.value = value;
309 // neither `GENERATE_COPY` nor plain `GENERATE` would compile here
310 auto value2 = GENERATE_REF(Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new TestGen(nc))));
311 REQUIRE(value == value2);
312 }
313
314 TEST_CASE("#1809 - GENERATE_COPY and SingleValueGenerator does not compile", "[generators][compilation][approvals]") {
315 // Verify Issue #1809 fix, only needs to compile.
316 auto a = GENERATE_COPY(1, 2);
317 (void)a;
318 auto b = GENERATE_COPY(as<long>{}, 1, 2);
319 (void)b;
320 int i = 1;
321 int j = 2;
322 auto c = GENERATE_COPY(i, j);
323 (void)c;
324 auto d = GENERATE_COPY(as<long>{}, i, j);
325 (void)d;
326 SUCCEED();
327 }
328
329 TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
330 SECTION("Integer") {
331 auto random1 = Catch::Generators::random(0, 1000);
332 auto random2 = Catch::Generators::random(0, 1000);
333 size_t same = 0;
334 for (size_t i = 0; i < 1000; ++i) {
335 same += random1.get() == random2.get();
336 random1.next(); random2.next();
337 }
338 // 0.5% seems like a sane bound for random identical elements within 1000 runs
339 REQUIRE(same < 5);
340 }
341 SECTION("Float") {
342 auto random1 = Catch::Generators::random(0., 1000.);
343 auto random2 = Catch::Generators::random(0., 1000.);
344 size_t same = 0;
345 for (size_t i = 0; i < 1000; ++i) {
346 same += random1.get() == random2.get();
347 random1.next(); random2.next();
348 }
349 // 0.5% seems like a sane bound for random identical elements within 1000 runs
350 REQUIRE(same < 5);
351 }
352 }
353