Add generic generator modifiers

This means mutiple generic generators and some inference helper
* take(n, generator)
* filter(predicate, generator)
* map(func, generator)
* repeat(generator, repeats)
This commit is contained in:
Martin Hořeňovský 2019-01-27 23:50:43 +01:00
parent e46a70f829
commit 5929d9530c
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
9 changed files with 1262 additions and 25 deletions

View File

@ -16,6 +16,10 @@ namespace Catch {
IGeneratorTracker::~IGeneratorTracker() {}
const char* GeneratorException::what() const noexcept {
return m_msg;
}
namespace Generators {
GeneratorUntypedBase::~GeneratorUntypedBase() {}

View File

@ -16,8 +16,21 @@
#include <cassert>
#include <utility>
#include <exception>
namespace Catch {
class GeneratorException : public std::exception {
const char* const m_msg = "";
public:
GeneratorException(const char* msg):
m_msg(msg)
{}
const char* what() const noexcept override final;
};
namespace Generators {
// !TBD move this into its own location?
@ -166,6 +179,175 @@ namespace Generators {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
}
template <typename T>
class TakeGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
size_t m_returned = 0;
size_t m_target;
public:
TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
m_generator(std::move(generator)),
m_target(target)
{
assert(target != 0 && "Empty generators are not allowed");
}
T const& get() const override {
return m_generator.get();
}
bool next() override {
++m_returned;
if (m_returned >= m_target) {
return false;
}
const auto success = m_generator.next();
// If the underlying generator does not contain enough values
// then we cut short as well
if (!success) {
m_returned = m_target;
}
return success;
}
};
template <typename T>
GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
}
template <typename T, typename Predicate>
class FilterGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
Predicate m_predicate;
public:
template <typename P = Predicate>
FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
m_generator(std::move(generator)),
m_predicate(std::forward<P>(pred))
{
if (!m_predicate(m_generator.get())) {
// It might happen that there are no values that pass the
// filter. In that case we throw an exception.
auto has_initial_value = next();
if (!has_initial_value) {
Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
}
}
}
T const& get() const override {
return m_generator.get();
}
bool next() override {
bool success = m_generator.next();
if (!success) {
return false;
}
while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
return success;
}
};
template <typename T, typename Predicate>
GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
}
template <typename T>
class RepeatGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
mutable std::vector<T> m_returned;
size_t m_target_repeats;
size_t m_current_repeat = 0;
size_t m_repeat_index = 0;
public:
RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
m_generator(std::move(generator)),
m_target_repeats(repeats)
{
assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
}
T const& get() const override {
if (m_current_repeat == 0) {
m_returned.push_back(m_generator.get());
return m_returned.back();
}
return m_returned[m_repeat_index];
}
bool next() override {
// There are 2 basic cases:
// 1) We are still reading the generator
// 2) We are reading our own cache
// In the first case, we need to poke the underlying generator.
// If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
if (m_current_repeat == 0) {
const auto success = m_generator.next();
if (!success) {
++m_current_repeat;
}
return m_current_repeat < m_target_repeats;
}
// In the second case, we need to move indices forward and check that we haven't run up against the end
++m_repeat_index;
if (m_repeat_index == m_returned.size()) {
m_repeat_index = 0;
++m_current_repeat;
}
return m_current_repeat < m_target_repeats;
}
};
template <typename T>
GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
}
template <typename T, typename U, typename Func>
class MapGenerator : public IGenerator<T> {
// TBD: provide static assert for mapping function, for friendly error message
GeneratorWrapper<U> m_generator;
Func m_function;
// To avoid returning dangling reference, we have to save the values
T m_cache;
public:
template <typename F2 = Func>
MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
m_generator(std::move(generator)),
m_function(std::forward<F2>(function)),
m_cache(m_function(m_generator.get()))
{}
T const& get() const override {
return m_cache;
}
bool next() override {
const auto success = m_generator.next();
if (success) {
m_cache = m_function(m_generator.get());
}
return success;
}
};
template <typename T, typename U, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
);
}
template <typename T, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
);
}
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;

View File

@ -399,6 +399,24 @@ Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, 0.f)
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0)
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i < 4 for: 1 < 4
Generators.tests.cpp:<line number>: passed: i < 4 for: 2 < 4
Generators.tests.cpp:<line number>: passed: i < 4 for: 3 < 4
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 1
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1
@ -442,6 +460,37 @@ GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "bb" for: "bb" == "
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "cc" for: "cc" == "cc"
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2.0 for: 2.0 == 2.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4.0 for: 4.0 == 4.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 6.0 for: 6.0 == 6.0
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.22 ) for: 1.23 >= Approx( 1.22 )
Approx.tests.cpp:<line number>: passed: d >= Approx( 1.23 ) for: 1.23 >= Approx( 1.23 )
Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))

View File

@ -1170,6 +1170,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 244 | 184 passed | 56 failed | 4 failed as expected
assertions: 1248 | 1112 passed | 115 failed | 21 failed as expected
test cases: 245 | 185 passed | 56 failed | 4 failed as expected
assertions: 1297 | 1161 passed | 115 failed | 21 failed as expected

View File

@ -2850,6 +2850,228 @@ Matchers.tests.cpp:<line number>: PASSED:
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( WithinULP(1.f, -1), std::domain_error )
-------------------------------------------------------------------------------
Generators -- adapters
Filtering by predicate
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i % 2 == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
Generators -- adapters
Filtering by predicate
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i % 2 == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
Generators -- adapters
Filtering by predicate
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i % 2 == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
Generators -- adapters
Shortening a range
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i < 4 )
with expansion:
1 < 4
-------------------------------------------------------------------------------
Generators -- adapters
Shortening a range
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i < 4 )
with expansion:
2 < 4
-------------------------------------------------------------------------------
Generators -- adapters
Shortening a range
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i < 4 )
with expansion:
3 < 4
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Same type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i % 2 == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Same type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i % 2 == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Same type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i % 2 == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Different type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Different type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Different type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( j > 0 )
with expansion:
1 > 0
-------------------------------------------------------------------------------
Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( j > 0 )
with expansion:
2 > 0
-------------------------------------------------------------------------------
Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( j > 0 )
with expansion:
3 > 0
-------------------------------------------------------------------------------
Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( j > 0 )
with expansion:
1 > 0
-------------------------------------------------------------------------------
Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( j > 0 )
with expansion:
2 > 0
-------------------------------------------------------------------------------
Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( j > 0 )
with expansion:
3 > 0
-------------------------------------------------------------------------------
Generators -- simple
one
@ -3219,6 +3441,205 @@ GeneratorsImpl.tests.cpp:<line number>: PASSED:
with expansion:
!false
-------------------------------------------------------------------------------
Generators internals
Filter generator
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 1 )
with expansion:
1 == 1
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 3 )
with expansion:
3 == 3
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter([] (int) { return false; }, value(1)), Catch::GeneratorException )
-------------------------------------------------------------------------------
Generators internals
Take generator
Take less
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 1 )
with expansion:
1 == 1
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 2 )
with expansion:
2 == 2
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
-------------------------------------------------------------------------------
Generators internals
Take generator
Take more
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 1 )
with expansion:
1 == 1
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
-------------------------------------------------------------------------------
Generators internals
Map
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 2.0 )
with expansion:
2.0 == 2.0
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 4.0 )
with expansion:
4.0 == 4.0
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 6.0 )
with expansion:
6.0 == 6.0
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
-------------------------------------------------------------------------------
Generators internals
Repeat
Singular repeat
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 3 )
with expansion:
3 == 3
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
-------------------------------------------------------------------------------
Generators internals
Repeat
Actual repeat
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 1 )
with expansion:
1 == 1
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 2 )
with expansion:
2 == 2
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 3 )
with expansion:
3 == 3
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 1 )
with expansion:
1 == 1
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 2 )
with expansion:
2 == 2
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 3 )
with expansion:
3 == 3
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
-------------------------------------------------------------------------------
Greater-than inequalities with different epsilons
-------------------------------------------------------------------------------
@ -9726,6 +10147,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 244 | 171 passed | 69 failed | 4 failed as expected
assertions: 1262 | 1112 passed | 129 failed | 21 failed as expected
test cases: 245 | 172 passed | 69 failed | 4 failed as expected
assertions: 1311 | 1161 passed | 129 failed | 21 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="113" tests="1263" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="113" tests="1312" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
@ -339,12 +339,23 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Same type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Different type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Repeating a generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- simple/one" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- simple/two" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Preset values" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Generator combinator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Explicitly typed generator sequence" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Filter generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take less" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take more" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Map" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Singular repeat" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Actual repeat" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">

View File

@ -3538,6 +3538,225 @@
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Generators -- adapters" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i % 2 == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i % 2 == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i % 2 == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Shortening a range" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i &lt; 4
</Original>
<Expanded>
1 &lt; 4
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Shortening a range" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i &lt; 4
</Original>
<Expanded>
2 &lt; 4
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Shortening a range" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i &lt; 4
</Original>
<Expanded>
3 &lt; 4
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Same type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i % 2 == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Same type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i % 2 == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Same type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i % 2 == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Different type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i.size() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Different type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i.size() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Different type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i.size() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
j > 0
</Original>
<Expanded>
1 > 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
j > 0
</Original>
<Expanded>
2 > 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
j > 0
</Original>
<Expanded>
3 > 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
j > 0
</Original>
<Expanded>
1 > 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
j > 0
</Original>
<Expanded>
2 > 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
j > 0
</Original>
<Expanded>
3 > 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Generators -- simple" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
@ -3952,6 +4171,284 @@
</Expression>
<OverallResults successes="7" failures="0" expectedFailures="0"/>
</Section>
<Section name="Filter generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 3
</Original>
<Expanded>
3 == 3
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
filter([] (int) { return false; }, value(1)), Catch::GeneratorException
</Original>
<Expanded>
filter([] (int) { return false; }, value(1)), Catch::GeneratorException
</Expanded>
</Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
</Section>
<Section name="Take generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Section name="Take less" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 2
</Original>
<Expanded>
2 == 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Take generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Section name="Take more" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="Map" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 2.0
</Original>
<Expanded>
2.0 == 2.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 4.0
</Original>
<Expanded>
4.0 == 4.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 6.0
</Original>
<Expanded>
6.0 == 6.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Section name="Singular repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 3
</Original>
<Expanded>
3 == 3
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Section name="Actual repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 2
</Original>
<Expanded>
2 == 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 3
</Original>
<Expanded>
3 == 3
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 2
</Original>
<Expanded>
2 == 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 3
</Original>
<Expanded>
3 == 3
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="12" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="12" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Greater-than inequalities with different epsilons" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
@ -11654,7 +12151,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="1112" failures="130" expectedFailures="21"/>
<OverallResults successes="1161" failures="130" expectedFailures="21"/>
</Group>
<OverallResults successes="1112" failures="129" expectedFailures="21"/>
<OverallResults successes="1161" failures="129" expectedFailures="21"/>
</Catch>

View File

@ -43,4 +43,61 @@ TEST_CASE("Generators internals", "[generators][internals]") {
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") {
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("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());
}
}
}

View File

@ -56,24 +56,7 @@ TEST_CASE("tables", "[generators]") {
#ifdef __cpp_structured_bindings
// One way to do pairs of values (actual/ expected?)
// For a simple case like this I'd recommend writing out a series of REQUIREs
// but it demonstrates a possible usage.
// Spelling out the pair like this is a bit verbose, so read on for better examples
// - the use of structured bindings here is an optional convenience
TEST_CASE( "strlen", "[approvals][generators]" ) {
auto [test_input, expected] = GENERATE( values<std::pair<std::string_view, size_t>>({
{"one", 3},
{"two", 3},
{"three", 5},
{"four", 4}
}));
REQUIRE( test_input.size() == expected );
}
// A nicer way to do pairs (or more) of values - using the table generator.
// Note, you must specify the types up-front.
// Structured bindings make the table utility much nicer to use
TEST_CASE( "strlen2", "[approvals][generators]" ) {
auto [test_input, expected] = GENERATE( table<std::string, size_t>({
{"one", 3},
@ -129,3 +112,36 @@ SCENARIO("Eating cucumbers", "[generators][approvals]") {
}
}
#endif
// There are also some generic generator manipulators
TEST_CASE("Generators -- adapters", "[generators]") {
// TODO: This won't work yet, introduce GENERATE_VAR?
//auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 });
SECTION("Filtering by predicate") {
// This filters out all odd (false) numbers, giving [2, 4, 6]
auto i = GENERATE(filter([] (int val) { return val % 2 == 0; }, values({ 1, 2, 3, 4, 5, 6 })));
REQUIRE(i % 2 == 0);
}
SECTION("Shortening a range") {
// This takes the first 3 elements from the values, giving back [1, 2, 3]
auto i = GENERATE(take(3, values({ 1, 2, 3, 4, 5, 6 })));
REQUIRE(i < 4);
}
SECTION("Transforming elements") {
SECTION("Same type") {
// This doubles values [1, 2, 3] into [2, 4, 6]
auto i = GENERATE(map([] (int val) { return val * 2; }, values({ 1, 2, 3 })));
REQUIRE(i % 2 == 0);
}
SECTION("Different type") {
// This takes a generator that returns ints and maps them into strings
auto i = GENERATE(map<std::string>([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
REQUIRE(i.size() == 1);
}
}
SECTION("Repeating a generator") {
// This will return values [1, 2, 3, 1, 2, 3]
auto j = GENERATE(repeat(2, values({ 1, 2, 3 })));
REQUIRE(j > 0);
}
}